wmi-1.3.16 from opsview.com
This commit is contained in:
@@ -0,0 +1,184 @@
|
||||
# COM Header generation
|
||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
package Parse::Pidl::Samba4::COM::Header;
|
||||
|
||||
use Parse::Pidl::Typelist qw(mapType);
|
||||
use Parse::Pidl::Util qw(has_property is_constant);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
sub HeaderType($)
|
||||
{
|
||||
my($e) = @_;
|
||||
if (has_property($e, "charset")) {
|
||||
return "const char";
|
||||
} else {
|
||||
return mapType($e->{TYPE});
|
||||
}
|
||||
}
|
||||
|
||||
sub GetArgumentProto($)
|
||||
{
|
||||
my $a = shift;
|
||||
my $res = HeaderType($a) . " ";
|
||||
|
||||
my $l = $a->{POINTERS};
|
||||
$l-- if (Parse::Pidl::Typelist::scalar_is_reference($a->{TYPE}));
|
||||
foreach my $i (1..$l) {
|
||||
$res .= "*";
|
||||
}
|
||||
|
||||
if (defined $a->{ARRAY_LEN}[0] && !is_constant($a->{ARRAY_LEN}[0]) &&
|
||||
!$a->{POINTERS}) {
|
||||
$res .= "*";
|
||||
}
|
||||
$res .= $a->{NAME};
|
||||
if (defined $a->{ARRAY_LEN}[0] && is_constant($a->{ARRAY_LEN}[0])) {
|
||||
$res .= "[$a->{ARRAY_LEN}[0]]";
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub GetArgumentProtoList
|
||||
{
|
||||
my ($f,$filter) = @_;
|
||||
my $res = "";
|
||||
|
||||
foreach my $a (@{$f->{ELEMENTS}}) {
|
||||
next if defined($filter) && !has_property($a, $filter);
|
||||
$res .= ", " . GetArgumentProto($a);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub GetArgumentList
|
||||
{
|
||||
my ($f,$filter) = @_;
|
||||
my $res = "";
|
||||
|
||||
foreach (@{$f->{ELEMENTS}}) {
|
||||
next if defined($filter) && !has_property($_, $filter);
|
||||
$res .= ", $_->{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}) {
|
||||
if ($d->{TYPE} eq "FUNCTION") {
|
||||
# $res .= "\t" . mapType($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n";
|
||||
$res .= "\tstruct composite_context *(*$d->{NAME}_send) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d, "in") . ");\\\n";
|
||||
}
|
||||
}
|
||||
$res .= "\n";
|
||||
$res .= "struct $interface->{NAME}_vtable {\n";
|
||||
$res .= "\tstruct GUID iid;\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 OBJREF obj;
|
||||
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");
|
||||
|
||||
my $defname = ($d->{NAME} =~ /^$if->{NAME}_(.*)$/) ? $1 : $d->{NAME};
|
||||
# $res .= "#define $if->{NAME}_${defname}(interface, mem_ctx" . GetArgumentList($d) . ") ";
|
||||
# $res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))";
|
||||
$res .= mapType($d->{RETURN_TYPE}) . " $if->{NAME}_${defname}(struct $if->{NAME} *interface, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\n";
|
||||
$res .= "#define $if->{NAME}_${defname}_send(interface, mem_ctx" . GetArgumentList($d, "in") . ") ";
|
||||
$res .= "((interface)->vtable->$d->{NAME}_send(interface, mem_ctx" . GetArgumentList($d, "in") . "))";
|
||||
$res .="\n";
|
||||
# $res .= "#define $if->{NAME}_${defname}_recv(c" . GetArgumentList($d, "out") . ") ";
|
||||
# $res .= "((interface)->vtable->$d->{NAME}_recv(c" . GetArgumentList($d, "out") . "))";
|
||||
$res .= mapType($d->{RETURN_TYPE}) . " $if->{NAME}_${defname}_recv(struct composite_context *c" . GetArgumentProtoList($d, "out") . ");\n";
|
||||
$res .="\n";
|
||||
}
|
||||
$res .= "\nNTSTATUS dcom_proxy_$if->{NAME}_init(void);\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub ParseCoClass($)
|
||||
{
|
||||
my $c = shift;
|
||||
my $res = "";
|
||||
$res .= "#define CLSID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{uuid}\n";
|
||||
if (has_property($c, "progid")) {
|
||||
$res .= "#define PROGID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{progid}\n";
|
||||
}
|
||||
$res .= "\n";
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub Parse($$)
|
||||
{
|
||||
my ($idl,$ndr_header) = @_;
|
||||
my $res = "";
|
||||
|
||||
$res .= "#include \"librpc/gen_ndr/orpc.h\"\n" .
|
||||
"#include \"$ndr_header\"\n\n";
|
||||
|
||||
foreach (@{$idl})
|
||||
{
|
||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
||||
$res.="struct $_->{NAME};\n";
|
||||
foreach my $s (@{$_->{DATA}}) {
|
||||
next if ($s->{TYPE} ne "TYPEDEF" || defined($s->{DATA_TYPE}) || $s->{DATA}{TYPE} ne "STRUCT");
|
||||
$res.="struct $s->{NAME};\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (@{$idl})
|
||||
{
|
||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
||||
$res.=ParseInterface($_);
|
||||
}
|
||||
|
||||
if ($_->{TYPE} eq "COCLASS") {
|
||||
$res.=ParseCoClass($_);
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,397 @@
|
||||
###################################################
|
||||
# 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 Parse::Pidl::Samba4::COM::Proxy;
|
||||
|
||||
use Parse::Pidl::Samba4::COM::Header;
|
||||
use Parse::Pidl::Util qw(has_property);
|
||||
use Parse::Pidl::Typelist qw(mapType);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my($res);
|
||||
|
||||
sub ParseVTable($$)
|
||||
{
|
||||
my $interface = shift;
|
||||
my $name = shift;
|
||||
|
||||
# Generate the vtable
|
||||
$res .="\tstruct $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 .= "\nNTSTATUS dcom_proxy_$interface->{NAME}_init(void)
|
||||
{
|
||||
struct $interface->{NAME}_vtable *proxy_vtable = talloc(talloc_autofree_context(), struct $interface->{NAME}_vtable);
|
||||
";
|
||||
|
||||
if (defined($interface->{BASE})) {
|
||||
$res.= "
|
||||
struct GUID base_iid;
|
||||
const void *base_vtable;
|
||||
|
||||
base_iid = dcerpc_table_$interface->{BASE}.syntax_id.uuid;
|
||||
|
||||
base_vtable = dcom_proxy_vtable_by_iid(&base_iid);
|
||||
if (base_vtable == NULL) {
|
||||
DEBUG(0, (\"No proxy registered for base interface '$interface->{BASE}'\\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");
|
||||
|
||||
# $res .= "\tproxy_vtable->$x->{NAME} = dcom_proxy_$interface->{NAME}_$x->{NAME};\n";
|
||||
$res .= "\tproxy_vtable->$x->{NAME}_send = dcom_proxy_$interface->{NAME}_$x->{NAME}_send;\n";
|
||||
}
|
||||
|
||||
$res.= "
|
||||
proxy_vtable->iid = dcerpc_table_$interface->{NAME}.syntax_id.uuid;
|
||||
|
||||
return dcom_register_proxy((struct IUnknown_vtable *)proxy_vtable);
|
||||
}\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseFunction($$)
|
||||
{
|
||||
my $interface = shift;
|
||||
my $fn = shift;
|
||||
my $name = $fn->{NAME};
|
||||
my $short_name = ($fn->{NAME} =~ /^$interface->{NAME}_(.*)$/) ? $1 : $fn->{NAME};
|
||||
my $uname = uc $name;
|
||||
my $args_in = 0;
|
||||
my $args_out = 0;
|
||||
my $if_in = 0;
|
||||
my $if_out = 0;
|
||||
|
||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||
$args_in++ if has_property($a, "in");
|
||||
$args_out++ if has_property($a, "out");
|
||||
$if_in++ if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE") && has_property($a, "in"));
|
||||
$if_out++ if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE") && has_property($a, "out"));
|
||||
}
|
||||
$args_out++ if $fn->{RETURN_TYPE} ne "void";
|
||||
|
||||
#### declarations ############################################
|
||||
$res.="
|
||||
static void dcom_proxy_$interface->{NAME}_${name}_recv_rpc(struct rpc_request *req);
|
||||
";
|
||||
##### *_out struct ###########################################
|
||||
if ($args_out > 0) {
|
||||
$res.="
|
||||
struct $interface->{NAME}_${name}_out {
|
||||
";
|
||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "out"));
|
||||
my $decl = Parse::Pidl::Samba4::COM::Header::GetArgumentProto($a);
|
||||
$decl =~ s/ \*/ /;
|
||||
$res.= "\t" . $decl . ";\n";
|
||||
}
|
||||
if ($fn->{RETURN_TYPE} ne "void") {
|
||||
$res.= "\t" . mapType($fn->{RETURN_TYPE}) . " result;\n";
|
||||
}
|
||||
$res.="};\n";
|
||||
}
|
||||
|
||||
#### *_send ##################################################
|
||||
$res.="
|
||||
static struct composite_context *dcom_proxy_$interface->{NAME}_${name}_send(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn, "in") . ")
|
||||
{
|
||||
struct composite_context *c, *c_pipe;
|
||||
struct dcom_proxy_async_call_state *s;
|
||||
struct ${name} *r;
|
||||
" . ($if_in > 0 ? "\tNTSTATUS status;\n" : "" ) . "
|
||||
c = composite_create(mem_ctx, d->ctx->event_ctx);
|
||||
if (c == NULL) return NULL;
|
||||
|
||||
s = talloc_zero(c, struct dcom_proxy_async_call_state);
|
||||
if (composite_nomem(s, c)) return c;
|
||||
c->private_data = s;
|
||||
|
||||
r = talloc_zero(s, struct ${name});
|
||||
if (composite_nomem(r, c)) return c;
|
||||
|
||||
s->d = (struct IUnknown *)d;
|
||||
s->table = &dcerpc_table_$interface->{NAME};
|
||||
s->opnum = DCERPC_$uname;
|
||||
s->continuation = dcom_proxy_$interface->{NAME}_${name}_recv_rpc;
|
||||
s->mem_ctx = mem_ctx;
|
||||
s->r = r;
|
||||
|
||||
r->in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
|
||||
r->in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
|
||||
r->in.ORPCthis.cid = GUID_random();
|
||||
";
|
||||
# Put arguments into r
|
||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "in"));
|
||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||
my $varname;
|
||||
my $ctx = "mem_ctx";
|
||||
my $n;
|
||||
foreach $n (0..$a->{POINTERS}-1) {
|
||||
$res .=sprintf(("\t" x $n)."\tif (%s$a->{NAME}) {\n", ("*" x $n));
|
||||
$varname = ("*" x $n) . "r->in.$a->{NAME}";
|
||||
$res .=sprintf(("\t" x $n)."\t\t$varname = talloc_zero($ctx, struct MInterfacePointer%s);\n", ("*" x ($a->{POINTERS}-$n-1)));
|
||||
$ctx = $varname;
|
||||
}
|
||||
$n = $a->{POINTERS}-1;
|
||||
$res .=("\t" x $n)."\t\t(${varname})->size = sizeof(struct OBJREF);\n";
|
||||
$res .=sprintf(("\t" x $n)."\t\tstatus = dcom_OBJREF_from_IUnknown(&(*$varname).obj, (struct IUnknown *)%s$a->{NAME});\n", ("*" x ($a->{POINTERS}-1)));
|
||||
$res .= ("\t" x $n)."\t\tif (!NT_STATUS_IS_OK(status)) {\n"
|
||||
. ("\t" x $n)."\t\t\tcomposite_error(c, NT_STATUS_RPC_NT_CALL_FAILED);\n"
|
||||
. ("\t" x $n)."\t\t\treturn c;\n"
|
||||
. ("\t" x $n)."\t\t}\n";
|
||||
for ($n =$a->{POINTERS}; $n > 0; --$n) {
|
||||
$res .=("\t" x $n)."}\n";
|
||||
}
|
||||
} else {
|
||||
$res .= "\tr->in.$a->{NAME} = $a->{NAME};\n";
|
||||
}
|
||||
}
|
||||
|
||||
$res .="
|
||||
if (DEBUGLVL(12)) {
|
||||
NDR_PRINT_IN_DEBUG(${name}, r);
|
||||
}
|
||||
|
||||
c_pipe = dcom_get_pipe_send((struct IUnknown *)d, mem_ctx);
|
||||
composite_continue(c, c_pipe, dcom_proxy_async_call_recv_pipe_send_rpc, c);
|
||||
|
||||
return c;
|
||||
}
|
||||
";
|
||||
|
||||
#### *_recv_rpc ##############################################
|
||||
$res.="
|
||||
static void dcom_proxy_$interface->{NAME}_${name}_recv_rpc(struct rpc_request *req)
|
||||
{
|
||||
struct composite_context *c;
|
||||
struct dcom_proxy_async_call_state *s;
|
||||
struct $interface->{NAME}_${name}_out *out;
|
||||
struct ${name} *r;
|
||||
struct ORPCTHAT that;
|
||||
NTSTATUS status;
|
||||
";
|
||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "out"));
|
||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||
$res.="\tstruct MInterfacePointer *mip_$a->{NAME};\n";
|
||||
}
|
||||
}
|
||||
|
||||
$res.="
|
||||
c = req->async.private;
|
||||
s = c->private_data;
|
||||
r = s->r;
|
||||
out = talloc_zero(c, struct $interface->{NAME}_${name}_out);
|
||||
if (composite_nomem(out, c)) return;
|
||||
c->private_data = out;
|
||||
|
||||
r->out.ORPCthat = &that;
|
||||
";
|
||||
foreach $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "out"));
|
||||
|
||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||
$res.="\tr->out.$a->{NAME} = &mip_$a->{NAME};\n";
|
||||
} else {
|
||||
$res.="\tr->out.$a->{NAME} = &out->$a->{NAME};\n";
|
||||
}
|
||||
}
|
||||
|
||||
$res.="
|
||||
status = dcerpc_ndr_request_recv(req);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
composite_error(c, NT_STATUS_RPC_NT_CALL_FAILED);
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUGLVL(12)) {
|
||||
NDR_PRINT_OUT_DEBUG(${name}, r);
|
||||
}
|
||||
";
|
||||
foreach $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "out"));
|
||||
|
||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||
$res .=
|
||||
" if (r->out.$a->{NAME} && *r->out.$a->{NAME}) {
|
||||
status = dcom_IUnknown_from_OBJREF(s->d->ctx, (struct IUnknown **)&out->$a->{NAME}, &(**r->out.$a->{NAME}).obj);
|
||||
if (*r->out.$a->{NAME}) talloc_free(*r->out.$a->{NAME});
|
||||
} else {
|
||||
out->$a->{NAME} = NULL;
|
||||
}
|
||||
";
|
||||
} elsif (defined($a->{POINTERS}) and $a->{POINTERS} > 1) {
|
||||
$res .=
|
||||
" talloc_steal(s->mem_ctx, out->$a->{NAME});
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
if ($fn->{RETURN_TYPE} ne "void") {
|
||||
$res.="\tout->result = r->out.result;\n";
|
||||
}
|
||||
$res .="
|
||||
talloc_free(s);
|
||||
composite_done(c);
|
||||
}
|
||||
";
|
||||
|
||||
#### *_recv ##################################################
|
||||
$res.="
|
||||
" . mapType($fn->{RETURN_TYPE}) . " $interface->{NAME}_${name}_recv(struct composite_context *c" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn, "out") . ")
|
||||
{
|
||||
struct $interface->{NAME}_${name}_out *out;
|
||||
NTSTATUS status;
|
||||
" . (($fn->{RETURN_TYPE} ne "void") ? "\t" . mapType($fn->{RETURN_TYPE}) . " result;\n" : "") . "
|
||||
status = composite_wait(c);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
talloc_free(c);
|
||||
return";
|
||||
if ($fn->{RETURN_TYPE} eq "WERROR") {
|
||||
$res.=" ntstatus_to_werror(NT_STATUS_RPC_NT_CALL_FAILED)";
|
||||
} elsif($fn->{RETURN_TYPE} eq "uint32") {
|
||||
$res.=" 0";
|
||||
}
|
||||
$res .= ";
|
||||
}
|
||||
out = c->private_data;
|
||||
|
||||
";
|
||||
foreach $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "out"));
|
||||
$res.="\tif ($a->{NAME}) *$a->{NAME} = out->$a->{NAME};\n";
|
||||
}
|
||||
if ($fn->{RETURN_TYPE} ne "void") {
|
||||
$res.="\tresult = out->result;\n";
|
||||
}
|
||||
$res .= "
|
||||
talloc_free(c);
|
||||
" . (($fn->{RETURN_TYPE} ne "void") ? "\treturn result;" : "") . "
|
||||
}
|
||||
";
|
||||
|
||||
#### * sync ##################################################
|
||||
$res.="
|
||||
" . mapType($fn->{RETURN_TYPE}) . " $interface->{NAME}_${short_name}(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn) . ")
|
||||
{
|
||||
struct composite_context *c;
|
||||
|
||||
c = $interface->{NAME}_${short_name}_send(d, mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentList($fn, "in") . ");
|
||||
if (c == NULL) return";
|
||||
if ($fn->{RETURN_TYPE} eq "WERROR") {
|
||||
$res.=" WERR_NOMEM";
|
||||
} elsif($fn->{RETURN_TYPE} eq "uint32") {
|
||||
$res.=" 0";
|
||||
}
|
||||
$res.=";
|
||||
|
||||
" . (($fn->{RETURN_TYPE} ne "void") ? "return " : "") . "$interface->{NAME}_${name}_recv(c" . Parse::Pidl::Samba4::COM::Header::GetArgumentList($fn, "out") . ");
|
||||
}
|
||||
";
|
||||
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse the interface definitions
|
||||
sub ParseInterface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my($data) = $interface->{DATA};
|
||||
$res = "/* DCOM proxy for $interface->{NAME} generated by pidl */\n\n";
|
||||
foreach my $d (@{$data}) {
|
||||
($d->{TYPE} eq "FUNCTION") &&
|
||||
ParseFunction($interface, $d);
|
||||
}
|
||||
|
||||
ParseRegFunc($interface);
|
||||
}
|
||||
|
||||
sub RegistrationFunction($$)
|
||||
{
|
||||
my $idl = shift;
|
||||
my $basename = shift;
|
||||
|
||||
my $res = "\n\nNTSTATUS dcom_$basename\_init(void)\n";
|
||||
$res .= "{\n";
|
||||
$res .="\tNTSTATUS status = NT_STATUS_OK;\n";
|
||||
foreach my $interface (@{$idl}) {
|
||||
next if $interface->{TYPE} ne "INTERFACE";
|
||||
next if not has_property($interface, "object");
|
||||
|
||||
my $data = $interface->{DATA};
|
||||
my $count = 0;
|
||||
foreach my $d (@{$data}) {
|
||||
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
||||
}
|
||||
|
||||
next if ($count == 0);
|
||||
|
||||
$res .= "\tstatus = dcom_$interface->{NAME}_init();\n";
|
||||
$res .= "\tif (NT_STATUS_IS_ERR(status)) {\n";
|
||||
$res .= "\t\treturn status;\n";
|
||||
$res .= "\t}\n\n";
|
||||
}
|
||||
$res .= "\treturn status;\n";
|
||||
$res .= "}\n\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub Parse($$)
|
||||
{
|
||||
my ($pidl,$comh_filename) = @_;
|
||||
my $res = "";
|
||||
|
||||
$res .= "#include \"includes.h\"\n" .
|
||||
"#include \"librpc/rpc/dcerpc.h\"\n" .
|
||||
"#include \"lib/com/dcom/dcom.h\"\n" .
|
||||
"#include \"$comh_filename\"\n" .
|
||||
"#include \"libcli/composite/composite.h\"\n";
|
||||
|
||||
|
||||
foreach (@{$pidl}) {
|
||||
next if ($_->{TYPE} ne "INTERFACE");
|
||||
next if has_property($_, "local");
|
||||
next unless has_property($_, "object");
|
||||
|
||||
$res .= ParseInterface($_);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,327 @@
|
||||
###################################################
|
||||
# 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 Parse::Pidl::Samba4::COM::Stub;
|
||||
|
||||
use Parse::Pidl::Util qw(has_property);
|
||||
use strict;
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
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";
|
||||
if ($d->{RETURN_TYPE} && $d->{RETURN_TYPE} ne "void") {
|
||||
pidl "\t\tNTSTATUS result;\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\tresult = vtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
||||
} else {
|
||||
pidl "\t\tvtable->$d->{NAME}(iface, mem_ctx, r2);\n";
|
||||
}
|
||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} will reply async\\n\"));\n";
|
||||
pidl "\t\t}\n";
|
||||
pidl "\t\tbreak;\n\t}\n";
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################
|
||||
# generate the switch statement for function reply
|
||||
sub gen_reply_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 (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||
pidl "\t\t\tDEBUG(5,(\"function $d->{NAME} replied async\\n\"));\n";
|
||||
pidl "\t\t}\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 %s in $d->{NAME}\\n\", dcerpc_errstr(mem_ctx, 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 $name = $interface->{NAME};
|
||||
my $uname = uc $name;
|
||||
my $uuid = Parse::Pidl::Util::make_str($interface->{PROPERTIES}->{uuid});
|
||||
my $if_version = $interface->{PROPERTIES}->{version};
|
||||
|
||||
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_context *context, const struct dcesrv_interface *iface)
|
||||
{
|
||||
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
||||
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
dce_call->fault_code = 0;
|
||||
|
||||
if (opnum >= dcerpc_table_$name.num_calls) {
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
*r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
|
||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
||||
|
||||
/* unravel the NDR for the packet */
|
||||
status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||
&dce_call->pkt.u.request.stub_and_verifier);
|
||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||
{
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
struct GUID ipid = dce_call->pkt.u.request.object.object;
|
||||
struct dcom_interface_p *iface = dcom_get_local_iface_p(&ipid);
|
||||
const struct dcom_$name\_vtable *vtable = iface->vtable;
|
||||
|
||||
switch (opnum) {
|
||||
";
|
||||
gen_dispatch_switch($data);
|
||||
|
||||
pidl "
|
||||
default:
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dce_call->fault_code != 0) {
|
||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||
&dce_call->pkt.u.request.stub_and_verifier);
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||
{
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
switch (opnum) {
|
||||
";
|
||||
gen_reply_switch($data);
|
||||
|
||||
pidl "
|
||||
default:
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dce_call->fault_code != 0) {
|
||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||
&dce_call->pkt.u.request.stub_and_verifier);
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static const struct dcesrv_interface $name\_interface = {
|
||||
.name = \"$name\",
|
||||
.uuid = $uuid,
|
||||
.if_version = $if_version,
|
||||
.bind = $name\__op_bind,
|
||||
.unbind = $name\__op_unbind,
|
||||
.ndr_pull = $name\__op_ndr_pull,
|
||||
.dispatch = $name\__op_dispatch,
|
||||
.reply = $name\__op_reply,
|
||||
.ndr_push = $name\__op_ndr_push
|
||||
};
|
||||
|
||||
";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# produce boilerplate code for an endpoint server
|
||||
sub Boilerplate_Ep_Server($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my $name = $interface->{NAME};
|
||||
my $uname = uc $name;
|
||||
|
||||
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<dcerpc_table_$name.endpoints->count;i++) {
|
||||
NTSTATUS ret;
|
||||
const char *name = dcerpc_table_$name.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_t if_version)
|
||||
{
|
||||
if (dcerpc_table_$name.if_version == if_version &&
|
||||
strcmp(dcerpc_table_$name.uuid, uuid)==0) {
|
||||
memcpy(iface,&dcerpc_table_$name, sizeof(*iface));
|
||||
return True;
|
||||
}
|
||||
|
||||
return False;
|
||||
}
|
||||
|
||||
static BOOL $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
||||
{
|
||||
if (strcmp(dcerpc_table_$name.name, name)==0) {
|
||||
memcpy(iface,&dcerpc_table_$name, 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 = dcerpc_register_ep_server(&ep_server);
|
||||
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# dcom interface stub from a parsed IDL structure
|
||||
sub ParseInterface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
|
||||
return "" if has_property($interface, "local");
|
||||
|
||||
my($data) = $interface->{DATA};
|
||||
my $count = 0;
|
||||
|
||||
$res = "";
|
||||
|
||||
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
if (!defined $interface->{PROPERTIES}->{version}) {
|
||||
$interface->{PROPERTIES}->{version} = "0.0";
|
||||
}
|
||||
|
||||
foreach my $d (@{$data}) {
|
||||
if ($d->{TYPE} eq "FUNCTION") { $count++; }
|
||||
}
|
||||
|
||||
if ($count == 0) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
$res = "/* dcom interface stub generated by pidl */\n\n";
|
||||
Boilerplate_Iface($interface);
|
||||
Boilerplate_Ep_Server($interface);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,902 @@
|
||||
###################################################
|
||||
# EJS function wrapper generator
|
||||
# Copyright jelmer@samba.org 2005
|
||||
# Copyright Andrew Tridgell 2005
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::EJS;
|
||||
|
||||
use strict;
|
||||
use Parse::Pidl::Typelist;
|
||||
use Parse::Pidl::Util qw(has_property);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
my $res;
|
||||
my $res_hdr;
|
||||
|
||||
my %constants;
|
||||
|
||||
my $tabs = "";
|
||||
|
||||
sub pidl_hdr ($)
|
||||
{
|
||||
$res_hdr .= shift;
|
||||
}
|
||||
|
||||
sub pidl($)
|
||||
{
|
||||
my $d = shift;
|
||||
if ($d) {
|
||||
$res .= $tabs;
|
||||
$res .= $d;
|
||||
}
|
||||
$res .= "\n";
|
||||
}
|
||||
|
||||
sub indent()
|
||||
{
|
||||
$tabs .= "\t";
|
||||
}
|
||||
|
||||
sub deindent()
|
||||
{
|
||||
$tabs = substr($tabs, 0, -1);
|
||||
}
|
||||
|
||||
# this should probably be in ndr.pm
|
||||
sub GenerateStructEnv($)
|
||||
{
|
||||
my $x = shift;
|
||||
my %env;
|
||||
|
||||
foreach my $e (@{$x->{ELEMENTS}}) {
|
||||
if ($e->{NAME}) {
|
||||
$env{$e->{NAME}} = "r->$e->{NAME}";
|
||||
}
|
||||
}
|
||||
|
||||
$env{"this"} = "r";
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
sub GenerateFunctionInEnv($)
|
||||
{
|
||||
my $fn = shift;
|
||||
my %env;
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
if (grep (/in/, @{$e->{DIRECTION}})) {
|
||||
$env{$e->{NAME}} = "r->in.$e->{NAME}";
|
||||
}
|
||||
}
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
sub GenerateFunctionOutEnv($)
|
||||
{
|
||||
my $fn = shift;
|
||||
my %env;
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
if (grep (/out/, @{$e->{DIRECTION}})) {
|
||||
$env{$e->{NAME}} = "r->out.$e->{NAME}";
|
||||
} elsif (grep (/in/, @{$e->{DIRECTION}})) {
|
||||
$env{$e->{NAME}} = "r->in.$e->{NAME}";
|
||||
}
|
||||
}
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
sub get_pointer_to($)
|
||||
{
|
||||
my $var_name = shift;
|
||||
|
||||
if ($var_name =~ /^\*(.*)$/) {
|
||||
return $1;
|
||||
} elsif ($var_name =~ /^\&(.*)$/) {
|
||||
return "&($var_name)";
|
||||
} else {
|
||||
return "&$var_name";
|
||||
}
|
||||
}
|
||||
|
||||
sub get_value_of($)
|
||||
{
|
||||
my $var_name = shift;
|
||||
|
||||
if ($var_name =~ /^\&(.*)$/) {
|
||||
return $1;
|
||||
} else {
|
||||
return "*$var_name";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# check that a variable we get from ParseExpr isn't a null pointer
|
||||
sub check_null_pointer($)
|
||||
{
|
||||
my $size = shift;
|
||||
if ($size =~ /^\*/) {
|
||||
my $size2 = substr($size, 1);
|
||||
pidl "if ($size2 == NULL) return NT_STATUS_INVALID_PARAMETER_MIX;";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#####################################################################
|
||||
# work out is a parse function should be declared static or not
|
||||
sub fn_declare($$)
|
||||
{
|
||||
my ($fn,$decl) = @_;
|
||||
|
||||
if (has_property($fn, "public")) {
|
||||
pidl_hdr "$decl;\n";
|
||||
pidl "_PUBLIC_ $decl";
|
||||
} else {
|
||||
pidl "static $decl";
|
||||
}
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a scalar element
|
||||
sub EjsPullScalar($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
|
||||
return if (has_property($e, "value"));
|
||||
|
||||
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
|
||||
$var = get_pointer_to($var);
|
||||
# have to handle strings specially :(
|
||||
if ($e->{TYPE} eq "string" && $pl && $pl->{TYPE} eq "POINTER") {
|
||||
$var = get_pointer_to($var);
|
||||
}
|
||||
pidl "NDR_CHECK(ejs_pull_$e->{TYPE}(ejs, v, $name, $var));";
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a pointer element
|
||||
sub EjsPullPointer($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
pidl "if (ejs_pull_null(ejs, v, $name)) {";
|
||||
indent;
|
||||
if ($l->{POINTER_TYPE} eq "ref") {
|
||||
pidl "return NT_STATUS_INVALID_PARAMETER_MIX;";
|
||||
} else {
|
||||
pidl "$var = NULL;";
|
||||
}
|
||||
deindent;
|
||||
pidl "} else {";
|
||||
indent;
|
||||
pidl "EJS_ALLOC(ejs, $var);";
|
||||
$var = get_value_of($var);
|
||||
EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a string element
|
||||
sub EjsPullString($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
$var = get_pointer_to($var);
|
||||
pidl "NDR_CHECK(ejs_pull_string(ejs, v, $name, $var));";
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# pull an array element
|
||||
sub EjsPullArray($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
|
||||
my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
|
||||
my $size = Parse::Pidl::Util::ParseExpr($l->{SIZE_IS}, $env);
|
||||
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
|
||||
if ($pl && $pl->{TYPE} eq "POINTER") {
|
||||
$var = get_pointer_to($var);
|
||||
}
|
||||
# uint8 arrays are treated as data blobs
|
||||
if ($nl->{TYPE} eq 'DATA' && $e->{TYPE} eq 'uint8') {
|
||||
if (!$l->{IS_FIXED}) {
|
||||
check_null_pointer($size);
|
||||
pidl "EJS_ALLOC_N(ejs, $var, $size);";
|
||||
}
|
||||
check_null_pointer($length);
|
||||
pidl "ejs_pull_array_uint8(ejs, v, $name, $var, $length);";
|
||||
return;
|
||||
}
|
||||
my $avar = $var . "[i]";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "uint32_t i;";
|
||||
if (!$l->{IS_FIXED}) {
|
||||
pidl "EJS_ALLOC_N(ejs, $var, $size);";
|
||||
}
|
||||
pidl "for (i=0;i<$length;i++) {";
|
||||
indent;
|
||||
pidl "char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);";
|
||||
EjsPullElement($e, $nl, $avar, "id", $env);
|
||||
pidl "talloc_free(id);";
|
||||
deindent;
|
||||
pidl "}";
|
||||
pidl "ejs_push_uint32(ejs, v, $name \".length\", &i);";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a switch element
|
||||
sub EjsPullSwitch($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env);
|
||||
pidl "ejs_set_switch(ejs, $switch_var);";
|
||||
EjsPullElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a structure element
|
||||
sub EjsPullElement($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
if (has_property($e, "charset")) {
|
||||
EjsPullString($e, $l, $var, $name, $env);
|
||||
} elsif ($l->{TYPE} eq "ARRAY") {
|
||||
EjsPullArray($e, $l, $var, $name, $env);
|
||||
} elsif ($l->{TYPE} eq "DATA") {
|
||||
EjsPullScalar($e, $l, $var, $name, $env);
|
||||
} elsif (($l->{TYPE} eq "POINTER")) {
|
||||
EjsPullPointer($e, $l, $var, $name, $env);
|
||||
} elsif (($l->{TYPE} eq "SWITCH")) {
|
||||
EjsPullSwitch($e, $l, $var, $name, $env);
|
||||
} else {
|
||||
pidl "return ejs_panic(ejs, \"unhandled pull type $l->{TYPE}\");";
|
||||
}
|
||||
}
|
||||
|
||||
#############################################
|
||||
# pull a structure/union element at top level
|
||||
sub EjsPullElementTop($$)
|
||||
{
|
||||
my $e = shift;
|
||||
my $env = shift;
|
||||
my $l = $e->{LEVELS}[0];
|
||||
my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env);
|
||||
my $name = "\"$e->{NAME}\"";
|
||||
EjsPullElement($e, $l, $var, $name, $env);
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a struct
|
||||
sub EjsStructPull($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
my $env = GenerateStructEnv($d);
|
||||
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, struct $name *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, name));";
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
EjsPullElementTop($e, $env);
|
||||
}
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a union
|
||||
sub EjsUnionPull($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
my $have_default = 0;
|
||||
my $env = GenerateStructEnv($d);
|
||||
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, union $name *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, name));";
|
||||
pidl "switch (ejs->switch_var) {";
|
||||
indent;
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
if ($e->{CASE} eq "default") {
|
||||
$have_default = 1;
|
||||
}
|
||||
pidl "$e->{CASE}:";
|
||||
indent;
|
||||
if ($e->{TYPE} ne "EMPTY") {
|
||||
EjsPullElementTop($e, $env);
|
||||
}
|
||||
pidl "break;";
|
||||
deindent;
|
||||
}
|
||||
if (! $have_default) {
|
||||
pidl "default:";
|
||||
indent;
|
||||
pidl "return ejs_panic(ejs, \"Bad switch value\");";
|
||||
deindent;
|
||||
}
|
||||
deindent;
|
||||
pidl "}";
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
##############################################
|
||||
# put the enum elements in the constants array
|
||||
sub EjsEnumConstant($)
|
||||
{
|
||||
my $d = shift;
|
||||
my $v = 0;
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
my $el = $e;
|
||||
chomp $el;
|
||||
if ($el =~ /^(.*)=\s*(.*)\s*$/) {
|
||||
$el = $1;
|
||||
$v = $2;
|
||||
}
|
||||
$constants{$el} = $v;
|
||||
$v++;
|
||||
}
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a enum
|
||||
sub EjsEnumPull($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
EjsEnumConstant($d);
|
||||
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, enum $name *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "unsigned e;";
|
||||
pidl "NDR_CHECK(ejs_pull_enum(ejs, v, name, &e));";
|
||||
pidl "*r = e;";
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
###########################
|
||||
# pull a bitmap
|
||||
sub EjsBitmapPull($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
my $type_fn = $d->{BASE_TYPE};
|
||||
my($type_decl) = Parse::Pidl::Typelist::mapType($d->{BASE_TYPE});
|
||||
fn_declare($d, "NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, $type_decl *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "return ejs_pull_$type_fn(ejs, v, name, r);";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# generate a structure pull
|
||||
sub EjsTypedefPull($)
|
||||
{
|
||||
my $d = shift;
|
||||
return if (has_property($d, "noejs"));
|
||||
if ($d->{DATA}->{TYPE} eq 'STRUCT') {
|
||||
EjsStructPull($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'UNION') {
|
||||
EjsUnionPull($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'ENUM') {
|
||||
EjsEnumPull($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'BITMAP') {
|
||||
EjsBitmapPull($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'DECORATED') {
|
||||
} else {
|
||||
warn "Unhandled pull typedef $d->{NAME} of type $d->{DATA}->{TYPE}";
|
||||
}
|
||||
}
|
||||
|
||||
#####################
|
||||
# generate a function
|
||||
sub EjsPullFunction($)
|
||||
{
|
||||
my $d = shift;
|
||||
my $env = GenerateFunctionInEnv($d);
|
||||
my $name = $d->{NAME};
|
||||
|
||||
pidl "\nstatic NTSTATUS ejs_pull_$name(struct ejs_rpc *ejs, struct MprVar *v, struct $name *r)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "NDR_CHECK(ejs_pull_struct_start(ejs, &v, \"input\"));";
|
||||
|
||||
# we pull non-array elements before array elements as arrays
|
||||
# may have length_is() or size_is() properties that depend
|
||||
# on the non-array elements
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
||||
next if (has_property($e, "length_is") || has_property($e, "size_is"));
|
||||
EjsPullElementTop($e, $env);
|
||||
}
|
||||
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
||||
next unless (has_property($e, "length_is") || has_property($e, "size_is"));
|
||||
EjsPullElementTop($e, $env);
|
||||
}
|
||||
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# push a scalar element
|
||||
sub EjsPushScalar($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
# have to handle strings specially :(
|
||||
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
|
||||
if ($e->{TYPE} ne "string" || ($pl && $pl->{TYPE} eq "POINTER")) {
|
||||
$var = get_pointer_to($var);
|
||||
}
|
||||
pidl "NDR_CHECK(ejs_push_$e->{TYPE}(ejs, v, $name, $var));";
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a string element
|
||||
sub EjsPushString($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
pidl "NDR_CHECK(ejs_push_string(ejs, v, $name, $var));";
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a pointer element
|
||||
sub EjsPushPointer($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
pidl "if (NULL == $var) {";
|
||||
indent;
|
||||
if ($l->{POINTER_TYPE} eq "ref") {
|
||||
pidl "return NT_STATUS_INVALID_PARAMETER_MIX;";
|
||||
} else {
|
||||
pidl "NDR_CHECK(ejs_push_null(ejs, v, $name));";
|
||||
}
|
||||
deindent;
|
||||
pidl "} else {";
|
||||
indent;
|
||||
$var = get_value_of($var);
|
||||
EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a switch element
|
||||
sub EjsPushSwitch($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
my $switch_var = Parse::Pidl::Util::ParseExpr($l->{SWITCH_IS}, $env);
|
||||
pidl "ejs_set_switch(ejs, $switch_var);";
|
||||
EjsPushElement($e, Parse::Pidl::NDR::GetNextLevel($e, $l), $var, $name, $env);
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# push an array element
|
||||
sub EjsPushArray($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
my $nl = Parse::Pidl::NDR::GetNextLevel($e, $l);
|
||||
my $length = Parse::Pidl::Util::ParseExpr($l->{LENGTH_IS}, $env);
|
||||
my $pl = Parse::Pidl::NDR::GetPrevLevel($e, $l);
|
||||
if ($pl && $pl->{TYPE} eq "POINTER") {
|
||||
$var = get_pointer_to($var);
|
||||
}
|
||||
# uint8 arrays are treated as data blobs
|
||||
if ($nl->{TYPE} eq 'DATA' && $e->{TYPE} eq 'uint8') {
|
||||
check_null_pointer($length);
|
||||
pidl "ejs_push_array_uint8(ejs, v, $name, $var, $length);";
|
||||
return;
|
||||
}
|
||||
my $avar = $var . "[i]";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "uint32_t i;";
|
||||
pidl "for (i=0;i<$length;i++) {";
|
||||
indent;
|
||||
pidl "const char *id = talloc_asprintf(ejs, \"%s.%u\", $name, i);";
|
||||
EjsPushElement($e, $nl, $avar, "id", $env);
|
||||
deindent;
|
||||
pidl "}";
|
||||
pidl "ejs_push_uint32(ejs, v, $name \".length\", &i);";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
################################
|
||||
# push a structure/union element
|
||||
sub EjsPushElement($$$$$)
|
||||
{
|
||||
my ($e, $l, $var, $name, $env) = @_;
|
||||
if (has_property($e, "charset")) {
|
||||
EjsPushString($e, $l, $var, $name, $env);
|
||||
} elsif ($l->{TYPE} eq "ARRAY") {
|
||||
EjsPushArray($e, $l, $var, $name, $env);
|
||||
} elsif ($l->{TYPE} eq "DATA") {
|
||||
EjsPushScalar($e, $l, $var, $name, $env);
|
||||
} elsif (($l->{TYPE} eq "POINTER")) {
|
||||
EjsPushPointer($e, $l, $var, $name, $env);
|
||||
} elsif (($l->{TYPE} eq "SWITCH")) {
|
||||
EjsPushSwitch($e, $l, $var, $name, $env);
|
||||
} else {
|
||||
pidl "return ejs_panic(ejs, \"unhandled push type $l->{TYPE}\");";
|
||||
}
|
||||
}
|
||||
|
||||
#############################################
|
||||
# push a structure/union element at top level
|
||||
sub EjsPushElementTop($$)
|
||||
{
|
||||
my $e = shift;
|
||||
my $env = shift;
|
||||
my $l = $e->{LEVELS}[0];
|
||||
my $var = Parse::Pidl::Util::ParseExpr($e->{NAME}, $env);
|
||||
my $name = "\"$e->{NAME}\"";
|
||||
EjsPushElement($e, $l, $var, $name, $env);
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a struct
|
||||
sub EjsStructPush($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
my $env = GenerateStructEnv($d);
|
||||
fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const struct $name *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, name));";
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
EjsPushElementTop($e, $env);
|
||||
}
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a union
|
||||
sub EjsUnionPush($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
my $have_default = 0;
|
||||
my $env = GenerateStructEnv($d);
|
||||
fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const union $name *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, name));";
|
||||
pidl "switch (ejs->switch_var) {";
|
||||
indent;
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
if ($e->{CASE} eq "default") {
|
||||
$have_default = 1;
|
||||
}
|
||||
pidl "$e->{CASE}:";
|
||||
indent;
|
||||
if ($e->{TYPE} ne "EMPTY") {
|
||||
EjsPushElementTop($e, $env);
|
||||
}
|
||||
pidl "break;";
|
||||
deindent;
|
||||
}
|
||||
if (! $have_default) {
|
||||
pidl "default:";
|
||||
indent;
|
||||
pidl "return ejs_panic(ejs, \"Bad switch value\");";
|
||||
deindent;
|
||||
}
|
||||
deindent;
|
||||
pidl "}";
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a enum
|
||||
sub EjsEnumPush($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
EjsEnumConstant($d);
|
||||
fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const enum $name *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "unsigned e = *r;";
|
||||
pidl "NDR_CHECK(ejs_push_enum(ejs, v, name, &e));";
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
###########################
|
||||
# push a bitmap
|
||||
sub EjsBitmapPush($$)
|
||||
{
|
||||
my $name = shift;
|
||||
my $d = shift;
|
||||
my $type_fn = $d->{BASE_TYPE};
|
||||
my($type_decl) = Parse::Pidl::Typelist::mapType($d->{BASE_TYPE});
|
||||
# put the bitmap elements in the constants array
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
if ($e =~ /^(\w*)\s*(.*)\s*$/) {
|
||||
my $bname = $1;
|
||||
my $v = $2;
|
||||
$constants{$bname} = $v;
|
||||
}
|
||||
}
|
||||
fn_declare($d, "NTSTATUS ejs_push_$name(struct ejs_rpc *ejs, struct MprVar *v, const char *name, const $type_decl *r)");
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "return ejs_push_$type_fn(ejs, v, name, r);";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
|
||||
###########################
|
||||
# generate a structure push
|
||||
sub EjsTypedefPush($)
|
||||
{
|
||||
my $d = shift;
|
||||
return if (has_property($d, "noejs"));
|
||||
|
||||
if ($d->{DATA}->{TYPE} eq 'STRUCT') {
|
||||
EjsStructPush($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'UNION') {
|
||||
EjsUnionPush($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'ENUM') {
|
||||
EjsEnumPush($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'BITMAP') {
|
||||
EjsBitmapPush($d->{NAME}, $d->{DATA});
|
||||
} elsif ($d->{DATA}->{TYPE} eq 'DECORATED') {
|
||||
} else {
|
||||
warn "Unhandled push typedef $d->{NAME} of type $d->{DATA}->{TYPE}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#####################
|
||||
# generate a function
|
||||
sub EjsPushFunction($)
|
||||
{
|
||||
my $d = shift;
|
||||
my $env = GenerateFunctionOutEnv($d);
|
||||
|
||||
pidl "\nstatic NTSTATUS ejs_push_$d->{NAME}(struct ejs_rpc *ejs, struct MprVar *v, const struct $d->{NAME} *r)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "NDR_CHECK(ejs_push_struct_start(ejs, &v, \"output\"));";
|
||||
|
||||
foreach my $e (@{$d->{ELEMENTS}}) {
|
||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||
EjsPushElementTop($e, $env);
|
||||
}
|
||||
|
||||
if ($d->{RETURN_TYPE}) {
|
||||
my $t = $d->{RETURN_TYPE};
|
||||
pidl "NDR_CHECK(ejs_push_$t(ejs, v, \"result\", &r->out.result));";
|
||||
}
|
||||
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
|
||||
#################################
|
||||
# generate a ejs mapping function
|
||||
sub EjsFunction($$)
|
||||
{
|
||||
my $d = shift;
|
||||
my $iface = shift;
|
||||
my $name = $d->{NAME};
|
||||
my $callnum = uc("DCERPC_$name");
|
||||
my $table = "&dcerpc_table_$iface";
|
||||
|
||||
pidl "static int ejs_$name(int eid, int argc, struct MprVar **argv)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "return ejs_rpc_call(eid, argc, argv, $table, $callnum, (ejs_pull_function_t)ejs_pull_$name, (ejs_push_function_t)ejs_push_$name);";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
}
|
||||
|
||||
###################
|
||||
# handle a constant
|
||||
sub EjsConst($)
|
||||
{
|
||||
my $const = shift;
|
||||
$constants{$const->{NAME}} = $const->{VALUE};
|
||||
}
|
||||
|
||||
sub EjsImport
|
||||
{
|
||||
my @imports = @_;
|
||||
foreach (@imports) {
|
||||
s/\.idl\"$//;
|
||||
s/^\"//;
|
||||
pidl_hdr "#include \"librpc/gen_ndr/ndr_$_\_ejs\.h\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse the interface definitions
|
||||
sub EjsInterface($$)
|
||||
{
|
||||
my($interface,$needed) = @_;
|
||||
my @fns = ();
|
||||
my $name = $interface->{NAME};
|
||||
|
||||
%constants = ();
|
||||
|
||||
pidl_hdr "#ifndef _HEADER_EJS_$interface->{NAME}\n";
|
||||
pidl_hdr "#define _HEADER_EJS_$interface->{NAME}\n\n";
|
||||
|
||||
pidl_hdr "\n";
|
||||
|
||||
foreach my $d (@{$interface->{TYPES}}) {
|
||||
($needed->{"push_$d->{NAME}"}) && EjsTypedefPush($d);
|
||||
($needed->{"pull_$d->{NAME}"}) && EjsTypedefPull($d);
|
||||
}
|
||||
|
||||
foreach my $d (@{$interface->{FUNCTIONS}}) {
|
||||
next if not defined($d->{OPNUM});
|
||||
next if has_property($d, "noejs");
|
||||
|
||||
EjsPullFunction($d);
|
||||
EjsPushFunction($d);
|
||||
EjsFunction($d, $name);
|
||||
|
||||
push (@fns, $d->{NAME});
|
||||
}
|
||||
|
||||
foreach my $d (@{$interface->{CONSTS}}) {
|
||||
EjsConst($d);
|
||||
}
|
||||
|
||||
pidl "static int ejs_$name\_init(int eid, int argc, struct MprVar **argv)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "struct MprVar *obj = mprInitObject(eid, \"$name\", argc, argv);";
|
||||
foreach (@fns) {
|
||||
pidl "mprSetCFunction(obj, \"$_\", ejs_$_);";
|
||||
}
|
||||
foreach my $v (keys %constants) {
|
||||
my $value = $constants{$v};
|
||||
if (substr($value, 0, 1) eq "\"") {
|
||||
pidl "mprSetVar(obj, \"$v\", mprString($value));";
|
||||
} else {
|
||||
pidl "mprSetVar(obj, \"$v\", mprCreateNumberVar($value));";
|
||||
}
|
||||
}
|
||||
pidl "return ejs_rpc_init(obj, \"$name\");";
|
||||
deindent;
|
||||
pidl "}\n";
|
||||
|
||||
pidl "NTSTATUS ejs_init_$name(void)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "ejsDefineCFunction(-1, \"$name\_init\", ejs_$name\_init, NULL, MPR_VAR_SCRIPT_HANDLE);";
|
||||
pidl "return NT_STATUS_OK;";
|
||||
deindent;
|
||||
pidl "}";
|
||||
|
||||
pidl_hdr "\n";
|
||||
pidl_hdr "#endif /* _HEADER_EJS_$interface->{NAME} */\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a parsed IDL into a C header
|
||||
sub Parse($$)
|
||||
{
|
||||
my($ndr,$hdr) = @_;
|
||||
|
||||
my $ejs_hdr = $hdr;
|
||||
$ejs_hdr =~ s/.h$/_ejs.h/;
|
||||
$res = "";
|
||||
$res_hdr = "";
|
||||
|
||||
pidl_hdr "/* header auto-generated by pidl */\n\n";
|
||||
|
||||
pidl "
|
||||
/* EJS wrapper functions auto-generated by pidl */
|
||||
#include \"includes.h\"
|
||||
#include \"librpc/rpc/dcerpc.h\"
|
||||
#include \"lib/appweb/ejs/ejs.h\"
|
||||
#include \"scripting/ejs/ejsrpc.h\"
|
||||
#include \"scripting/ejs/smbcalls.h\"
|
||||
#include \"librpc/gen_ndr/ndr_misc_ejs.h\"
|
||||
#include \"$hdr\"
|
||||
#include \"$ejs_hdr\"
|
||||
|
||||
";
|
||||
|
||||
my %needed = ();
|
||||
|
||||
foreach my $x (@{$ndr}) {
|
||||
($x->{TYPE} eq "INTERFACE") && NeededInterface($x, \%needed);
|
||||
}
|
||||
|
||||
foreach my $x (@$ndr) {
|
||||
($x->{TYPE} eq "INTERFACE") && EjsInterface($x, \%needed);
|
||||
($x->{TYPE} eq "IMPORT") && EjsImport(@{$x->{PATHS}});
|
||||
}
|
||||
|
||||
return ($res_hdr, $res);
|
||||
}
|
||||
|
||||
sub NeededFunction($$)
|
||||
{
|
||||
my ($fn,$needed) = @_;
|
||||
|
||||
$needed->{"pull_$fn->{NAME}"} = 1;
|
||||
$needed->{"push_$fn->{NAME}"} = 1;
|
||||
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
next if (has_property($_, "subcontext")); #FIXME: Support subcontexts
|
||||
if (grep(/in/, @{$_->{DIRECTION}})) {
|
||||
$needed->{"pull_$_->{TYPE}"} = 1;
|
||||
}
|
||||
if (grep(/out/, @{$_->{DIRECTION}})) {
|
||||
$needed->{"push_$_->{TYPE}"} = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub NeededTypedef($$)
|
||||
{
|
||||
my ($t,$needed) = @_;
|
||||
|
||||
if (has_property($t, "public")) {
|
||||
$needed->{"pull_$t->{NAME}"} = not has_property($t, "noejs");
|
||||
$needed->{"push_$t->{NAME}"} = not has_property($t, "noejs");
|
||||
}
|
||||
|
||||
return if (($t->{DATA}->{TYPE} ne "STRUCT") and
|
||||
($t->{DATA}->{TYPE} ne "UNION"));
|
||||
|
||||
foreach (@{$t->{DATA}->{ELEMENTS}}) {
|
||||
next if (has_property($_, "subcontext")); #FIXME: Support subcontexts
|
||||
unless (defined($needed->{"pull_$_->{TYPE}"})) {
|
||||
$needed->{"pull_$_->{TYPE}"} = $needed->{"pull_$t->{NAME}"};
|
||||
}
|
||||
unless (defined($needed->{"push_$_->{TYPE}"})) {
|
||||
$needed->{"push_$_->{TYPE}"} = $needed->{"push_$t->{NAME}"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# work out what parse functions are needed
|
||||
sub NeededInterface($$)
|
||||
{
|
||||
my ($interface,$needed) = @_;
|
||||
|
||||
NeededFunction($_, $needed) foreach (@{$interface->{FUNCTIONS}});
|
||||
NeededTypedef($_, $needed) foreach (reverse @{$interface->{TYPES}});
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,407 @@
|
||||
###################################################
|
||||
# create C header files for an IDL structure
|
||||
# Copyright tridge@samba.org 2000
|
||||
# Copyright jelmer@samba.org 2005
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::Header;
|
||||
|
||||
use strict;
|
||||
use Parse::Pidl::Typelist qw(mapType);
|
||||
use Parse::Pidl::Util qw(has_property is_constant);
|
||||
use Parse::Pidl::NDR qw(GetNextLevel GetPrevLevel);
|
||||
use Parse::Pidl::Samba4 qw(is_intree);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
my($res);
|
||||
my($tab_depth);
|
||||
|
||||
sub pidl($) { $res .= shift; }
|
||||
|
||||
sub tabs()
|
||||
{
|
||||
my $res = "";
|
||||
$res .="\t" foreach (1..$tab_depth);
|
||||
return $res;
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a properties list
|
||||
sub HeaderProperties($$)
|
||||
{
|
||||
my($props,$ignores) = @_;
|
||||
my $ret = "";
|
||||
|
||||
foreach my $d (keys %{$props}) {
|
||||
next if (grep(/^$d$/, @$ignores));
|
||||
if($props->{$d} ne "1") {
|
||||
$ret.= "$d($props->{$d}),";
|
||||
} else {
|
||||
$ret.="$d,";
|
||||
}
|
||||
}
|
||||
|
||||
if ($ret) {
|
||||
pidl "/* [" . substr($ret, 0, -1) . "] */";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a structure element
|
||||
sub HeaderElement($)
|
||||
{
|
||||
my($element) = shift;
|
||||
|
||||
pidl tabs();
|
||||
if (has_property($element, "represent_as")) {
|
||||
pidl mapType($element->{PROPERTIES}->{represent_as})." ";
|
||||
} else {
|
||||
HeaderType($element, $element->{TYPE}, "");
|
||||
pidl " ";
|
||||
my $numstar = $element->{POINTERS};
|
||||
if ($numstar >= 1) {
|
||||
$numstar-- if Parse::Pidl::Typelist::scalar_is_reference($element->{TYPE});
|
||||
}
|
||||
foreach (@{$element->{ARRAY_LEN}})
|
||||
{
|
||||
next if is_constant($_) and
|
||||
not has_property($element, "charset");
|
||||
$numstar++;
|
||||
}
|
||||
pidl "*" foreach (1..$numstar);
|
||||
}
|
||||
pidl $element->{NAME};
|
||||
foreach (@{$element->{ARRAY_LEN}}) {
|
||||
next unless (is_constant($_) and
|
||||
not has_property($element, "charset"));
|
||||
pidl "[$_]";
|
||||
}
|
||||
|
||||
pidl ";";
|
||||
if (defined $element->{PROPERTIES}) {
|
||||
HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
|
||||
}
|
||||
pidl "\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a struct
|
||||
sub HeaderStruct($$)
|
||||
{
|
||||
my($struct,$name) = @_;
|
||||
pidl "struct $name {\n";
|
||||
$tab_depth++;
|
||||
my $el_count=0;
|
||||
if (defined $struct->{ELEMENTS}) {
|
||||
foreach (@{$struct->{ELEMENTS}}) {
|
||||
HeaderElement($_);
|
||||
$el_count++;
|
||||
}
|
||||
}
|
||||
if ($el_count == 0) {
|
||||
# some compilers can't handle empty structures
|
||||
pidl tabs()."char _empty_;\n";
|
||||
}
|
||||
$tab_depth--;
|
||||
pidl tabs()."}";
|
||||
if (defined $struct->{PROPERTIES}) {
|
||||
HeaderProperties($struct->{PROPERTIES}, []);
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a enum
|
||||
sub HeaderEnum($$)
|
||||
{
|
||||
my($enum,$name) = @_;
|
||||
my $first = 1;
|
||||
|
||||
if (not Parse::Pidl::Util::useUintEnums()) {
|
||||
pidl "enum $name {\n";
|
||||
$tab_depth++;
|
||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
||||
unless ($first) { pidl ",\n"; }
|
||||
$first = 0;
|
||||
pidl tabs();
|
||||
pidl $e;
|
||||
}
|
||||
pidl "\n";
|
||||
$tab_depth--;
|
||||
pidl "}";
|
||||
} else {
|
||||
my $count = 0;
|
||||
pidl "enum $name { __donnot_use_enum_$name=0x7FFFFFFF};\n";
|
||||
my $with_val = 0;
|
||||
my $without_val = 0;
|
||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
||||
my $t = "$e";
|
||||
my $name;
|
||||
my $value;
|
||||
if ($t =~ /(.*)=(.*)/) {
|
||||
$name = $1;
|
||||
$value = $2;
|
||||
$with_val = 1;
|
||||
die ("you can't mix enum member with values and without values when using --uint-enums!")
|
||||
unless ($without_val == 0);
|
||||
} else {
|
||||
$name = $t;
|
||||
$value = $count++;
|
||||
$without_val = 1;
|
||||
die ("you can't mix enum member with values and without values when using --uint-enums!")
|
||||
unless ($with_val == 0);
|
||||
}
|
||||
pidl "#define $name ( $value )\n";
|
||||
}
|
||||
pidl "\n";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a bitmap
|
||||
sub HeaderBitmap($$)
|
||||
{
|
||||
my($bitmap,$name) = @_;
|
||||
|
||||
pidl "/* bitmap $name */\n";
|
||||
pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
|
||||
pidl "\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a union
|
||||
sub HeaderUnion($$)
|
||||
{
|
||||
my($union,$name) = @_;
|
||||
my %done = ();
|
||||
|
||||
pidl "union $name {\n";
|
||||
$tab_depth++;
|
||||
foreach my $e (@{$union->{ELEMENTS}}) {
|
||||
if ($e->{TYPE} ne "EMPTY") {
|
||||
if (! defined $done{$e->{NAME}}) {
|
||||
HeaderElement($e);
|
||||
}
|
||||
$done{$e->{NAME}} = 1;
|
||||
}
|
||||
}
|
||||
$tab_depth--;
|
||||
pidl "}";
|
||||
|
||||
if (defined $union->{PROPERTIES}) {
|
||||
HeaderProperties($union->{PROPERTIES}, []);
|
||||
}
|
||||
}
|
||||
|
||||
sub decorate($$)
|
||||
{
|
||||
my($name,$levels) = @_;
|
||||
my $prev_ptr = 0;
|
||||
foreach my $i (0..$#{$levels}) {
|
||||
if ($levels->[$i]{TYPE} eq "POINTER") {
|
||||
$name = "*$name";
|
||||
$prev_ptr = 1;
|
||||
} elsif ($levels->[$i]{TYPE} eq "ARRAY") {
|
||||
$name = ($prev_ptr ? "($name)" : $name) . "[$levels->[$i]{SIZE_IS}]";
|
||||
}
|
||||
}
|
||||
$name
|
||||
}
|
||||
|
||||
sub HeaderDecorated($$)
|
||||
{
|
||||
my($e,$name) = @_;
|
||||
$name = $e->{NAME} unless defined($name);
|
||||
pidl "typedef ";
|
||||
if (has_property($e, "charset")) {
|
||||
pidl "const char";
|
||||
} else {
|
||||
pidl mapType($e->{DATA}{DATA_TYPE});
|
||||
}
|
||||
pidl " " . decorate($name, $e->{DATA}{LEVELS});
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a type
|
||||
sub HeaderType($$$)
|
||||
{
|
||||
my($e,$data,$name) = @_;
|
||||
if (ref($data) eq "HASH") {
|
||||
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name);
|
||||
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
|
||||
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name);
|
||||
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name);
|
||||
($data->{TYPE} eq "DECORATED") && HeaderDecorated($e, $name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_property($e, "charset") and $e->{TYPEREF}{DATA}{TYPE} ne "DECORATED") {
|
||||
pidl "const char";
|
||||
} else {
|
||||
pidl mapType($e->{TYPE});
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a typedef
|
||||
sub HeaderTypedef($)
|
||||
{
|
||||
my($typedef) = shift;
|
||||
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME});
|
||||
pidl ";\n\n" unless ($typedef->{DATA}->{TYPE} eq "BITMAP");
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a const
|
||||
sub HeaderConst($)
|
||||
{
|
||||
my($const) = shift;
|
||||
if (!defined($const->{ARRAY_LEN}[0])) {
|
||||
pidl "#define $const->{NAME}\t( $const->{VALUE} )\n";
|
||||
} else {
|
||||
pidl "#define $const->{NAME}\t $const->{VALUE}\n";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub HeaderFunctionInOut($$)
|
||||
{
|
||||
my($fn,$prop) = @_;
|
||||
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
HeaderElement($_) if (has_property($_, $prop));
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# determine if we need an "in" or "out" section
|
||||
sub HeaderFunctionInOut_needed($$)
|
||||
{
|
||||
my($fn,$prop) = @_;
|
||||
|
||||
return 1 if ($prop eq "out" && $fn->{RETURN_TYPE} ne "void");
|
||||
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
return 1 if (has_property($_, $prop));
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
my %headerstructs;
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub HeaderFunction($)
|
||||
{
|
||||
my($fn) = shift;
|
||||
|
||||
return if ($headerstructs{$fn->{NAME}});
|
||||
|
||||
$headerstructs{$fn->{NAME}} = 1;
|
||||
|
||||
pidl "\nstruct $fn->{NAME} {\n";
|
||||
$tab_depth++;
|
||||
my $needed = 0;
|
||||
|
||||
if (HeaderFunctionInOut_needed($fn, "in")) {
|
||||
pidl tabs()."struct {\n";
|
||||
$tab_depth++;
|
||||
HeaderFunctionInOut($fn, "in");
|
||||
$tab_depth--;
|
||||
pidl tabs()."} in;\n\n";
|
||||
$needed++;
|
||||
}
|
||||
|
||||
if (HeaderFunctionInOut_needed($fn, "out")) {
|
||||
pidl tabs()."struct {\n";
|
||||
$tab_depth++;
|
||||
HeaderFunctionInOut($fn, "out");
|
||||
if ($fn->{RETURN_TYPE} ne "void") {
|
||||
pidl tabs().mapType($fn->{RETURN_TYPE}) . " result;\n";
|
||||
}
|
||||
$tab_depth--;
|
||||
pidl tabs()."} out;\n\n";
|
||||
$needed++;
|
||||
}
|
||||
|
||||
if (! $needed) {
|
||||
# sigh - some compilers don't like empty structures
|
||||
pidl tabs()."int _dummy_element;\n";
|
||||
}
|
||||
|
||||
$tab_depth--;
|
||||
pidl "};\n\n";
|
||||
}
|
||||
|
||||
sub HeaderImport
|
||||
{
|
||||
my @imports = @_;
|
||||
foreach (@imports) {
|
||||
s/\.idl\"$//;
|
||||
s/^\"//;
|
||||
pidl "#include \"librpc/gen_ndr/$_\.h\"\n";
|
||||
}
|
||||
}
|
||||
|
||||
sub HeaderInclude
|
||||
{
|
||||
my @includes = @_;
|
||||
foreach (@includes) {
|
||||
pidl "#include $_\n";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse the interface definitions
|
||||
sub HeaderInterface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
|
||||
pidl "#ifndef _HEADER_$interface->{NAME}\n";
|
||||
pidl "#define _HEADER_$interface->{NAME}\n\n";
|
||||
|
||||
foreach my $d (@{$interface->{DATA}}) {
|
||||
next if ($d->{TYPE} ne "CONST");
|
||||
HeaderConst($d);
|
||||
}
|
||||
|
||||
foreach my $d (@{$interface->{DATA}}) {
|
||||
next if ($d->{TYPE} ne "TYPEDEF");
|
||||
HeaderTypedef($d);
|
||||
}
|
||||
|
||||
foreach my $d (@{$interface->{DATA}}) {
|
||||
next if ($d->{TYPE} ne "FUNCTION");
|
||||
|
||||
HeaderFunction($d);
|
||||
}
|
||||
|
||||
pidl "#endif /* _HEADER_$interface->{NAME} */\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a parsed IDL into a C header
|
||||
sub Parse($)
|
||||
{
|
||||
my($idl) = shift;
|
||||
$tab_depth = 0;
|
||||
|
||||
$res = "";
|
||||
%headerstructs = ();
|
||||
pidl "/* header auto-generated by pidl */\n\n";
|
||||
if (!is_intree()) {
|
||||
pidl "#include <core.h>\n\n";
|
||||
}
|
||||
|
||||
foreach (@{$idl}) {
|
||||
($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
|
||||
($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
|
||||
($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,128 @@
|
||||
###################################################
|
||||
# client calls generator
|
||||
# Copyright tridge@samba.org 2003
|
||||
# Copyright jelmer@samba.org 2005-2006
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::NDR::Client;
|
||||
|
||||
use Parse::Pidl::Samba4 qw(choose_header is_intree);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my($res,$res_hdr);
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseFunction($$)
|
||||
{
|
||||
my ($interface, $fn) = @_;
|
||||
my $name = $fn->{NAME};
|
||||
my $uname = uc $name;
|
||||
|
||||
$res_hdr .= "\nstruct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);
|
||||
NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r);
|
||||
";
|
||||
|
||||
$res .= "
|
||||
struct rpc_request *dcerpc_$name\_send(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)
|
||||
{
|
||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
|
||||
NDR_PRINT_IN_DEBUG($name, r);
|
||||
}
|
||||
|
||||
return dcerpc_ndr_request_send(p, NULL, &dcerpc_table_$interface->{NAME}, DCERPC_$uname, mem_ctx, r);
|
||||
}
|
||||
|
||||
NTSTATUS dcerpc_$name(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct $name *r)
|
||||
{
|
||||
struct rpc_request *req;
|
||||
NTSTATUS status;
|
||||
|
||||
req = dcerpc_$name\_send(p, 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);
|
||||
}
|
||||
";
|
||||
|
||||
if (defined($fn->{RETURN_TYPE}) and $fn->{RETURN_TYPE} eq "NTSTATUS") {
|
||||
$res .= "\tif (NT_STATUS_IS_OK(status)) status = r->out.result;\n";
|
||||
}
|
||||
$res .=
|
||||
"
|
||||
return status;
|
||||
}
|
||||
";
|
||||
}
|
||||
|
||||
my %done;
|
||||
|
||||
#####################################################################
|
||||
# parse the interface definitions
|
||||
sub ParseInterface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
|
||||
$res_hdr .= "#ifndef _HEADER_RPC_$interface->{NAME}\n";
|
||||
$res_hdr .= "#define _HEADER_RPC_$interface->{NAME}\n\n";
|
||||
|
||||
if (defined $interface->{PROPERTIES}->{uuid}) {
|
||||
$res_hdr .= "extern const struct dcerpc_interface_table dcerpc_table_$interface->{NAME};\n";
|
||||
}
|
||||
|
||||
$res .= "/* $interface->{NAME} - client functions generated by pidl */\n\n";
|
||||
|
||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||
next if not defined($fn->{OPNUM});
|
||||
next if defined($done{$fn->{NAME}});
|
||||
ParseFunction($interface, $fn);
|
||||
$done{$fn->{NAME}} = 1;
|
||||
}
|
||||
|
||||
$res_hdr .= "#endif /* _HEADER_RPC_$interface->{NAME} */\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub Parse($$$$)
|
||||
{
|
||||
my($ndr,$header,$ndr_header,$client_header) = @_;
|
||||
|
||||
$res = "";
|
||||
$res_hdr = "";
|
||||
|
||||
$res .= "/* client functions auto-generated by pidl */\n";
|
||||
$res .= "\n";
|
||||
if (is_intree()) {
|
||||
$res .= "#include \"includes.h\"\n";
|
||||
} else {
|
||||
$res .= "#define _GNU_SOURCE\n";
|
||||
$res .= "#include <stdio.h>\n";
|
||||
$res .= "#include <stdbool.h>\n";
|
||||
$res .= "#include <stdlib.h>\n";
|
||||
$res .= "#include <stdint.h>\n";
|
||||
$res .= "#include <stdarg.h>\n";
|
||||
$res .= "#include <core/nterr.h>\n";
|
||||
}
|
||||
$res .= "#include \"$ndr_header\"\n";
|
||||
$res .= "#include \"$client_header\"\n";
|
||||
$res .= "\n";
|
||||
|
||||
$res_hdr .= choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."\n";
|
||||
$res_hdr .= "#include \"$header\"\n";
|
||||
|
||||
foreach my $x (@{$ndr}) {
|
||||
($x->{TYPE} eq "INTERFACE") && ParseInterface($x);
|
||||
}
|
||||
|
||||
return ($res,$res_hdr);
|
||||
}
|
||||
|
||||
1;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,325 @@
|
||||
###################################################
|
||||
# server boilerplate generator
|
||||
# Copyright tridge@samba.org 2003
|
||||
# Copyright metze@samba.org 2004
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::NDR::Server;
|
||||
|
||||
use strict;
|
||||
use Parse::Pidl::Util;
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
my($res);
|
||||
|
||||
sub pidl($)
|
||||
{
|
||||
$res .= shift;
|
||||
}
|
||||
|
||||
|
||||
#####################################################
|
||||
# generate the switch statement for function dispatch
|
||||
sub gen_dispatch_switch($)
|
||||
{
|
||||
my $interface = shift;
|
||||
|
||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||
next if not defined($fn->{OPNUM});
|
||||
|
||||
pidl "\tcase $fn->{OPNUM}: {\n";
|
||||
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
||||
pidl "\t\tif (DEBUGLEVEL >= 10) {\n";
|
||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{NAME}, NDR_IN, r2);\n";
|
||||
pidl "\t\t}\n";
|
||||
if ($fn->{RETURN_TYPE} && $fn->{RETURN_TYPE} ne "void") {
|
||||
pidl "\t\tr2->out.result = $fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
||||
} else {
|
||||
pidl "\t\t$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
||||
}
|
||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} will reply async\\n\"));\n";
|
||||
pidl "\t\t}\n";
|
||||
pidl "\t\tbreak;\n\t}\n";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################
|
||||
# generate the switch statement for function reply
|
||||
sub gen_reply_switch($)
|
||||
{
|
||||
my $interface = shift;
|
||||
|
||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||
next if not defined($fn->{OPNUM});
|
||||
|
||||
pidl "\tcase $fn->{OPNUM}: {\n";
|
||||
pidl "\t\tstruct $fn->{NAME} *r2 = (struct $fn->{NAME} *)r;\n";
|
||||
pidl "\t\tif (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {\n";
|
||||
pidl "\t\t\tDEBUG(5,(\"function $fn->{NAME} replied async\\n\"));\n";
|
||||
pidl "\t\t}\n";
|
||||
pidl "\t\tif (DEBUGLEVEL >= 10 && dce_call->fault_code == 0) {\n";
|
||||
pidl "\t\t\tNDR_PRINT_FUNCTION_DEBUG($fn->{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 %s in $fn->{NAME}\\n\", dcerpc_errstr(mem_ctx, dce_call->fault_code)));\n";
|
||||
pidl "\t\t}\n";
|
||||
pidl "\t\tbreak;\n\t}\n";
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# produce boilerplate code for a interface
|
||||
sub Boilerplate_Iface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my $name = $interface->{NAME};
|
||||
my $uname = uc $name;
|
||||
my $uuid = lc($interface->{PROPERTIES}->{uuid});
|
||||
my $if_version = $interface->{PROPERTIES}->{version};
|
||||
|
||||
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_context *context, const struct dcesrv_interface *iface)
|
||||
{
|
||||
#ifdef DCESRV_INTERFACE_$uname\_UNBIND
|
||||
DCESRV_INTERFACE_$uname\_UNBIND(context, iface);
|
||||
#else
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_ndr_pull(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_pull *pull, void **r)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
dce_call->fault_code = 0;
|
||||
|
||||
if (opnum >= dcerpc_table_$name.num_calls) {
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
*r = talloc_size(mem_ctx, dcerpc_table_$name.calls[opnum].struct_size);
|
||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
||||
|
||||
/* unravel the NDR for the packet */
|
||||
status = dcerpc_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||
&dce_call->pkt.u.request.stub_and_verifier);
|
||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_dispatch(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||
{
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
switch (opnum) {
|
||||
";
|
||||
gen_dispatch_switch($interface);
|
||||
|
||||
pidl "
|
||||
default:
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dce_call->fault_code != 0) {
|
||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||
&dce_call->pkt.u.request.stub_and_verifier);
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_reply(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, void *r)
|
||||
{
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
switch (opnum) {
|
||||
";
|
||||
gen_reply_switch($interface);
|
||||
|
||||
pidl "
|
||||
default:
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (dce_call->fault_code != 0) {
|
||||
dcerpc_log_packet(&dcerpc_table_$name, opnum, NDR_IN,
|
||||
&dce_call->pkt.u.request.stub_and_verifier);
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static NTSTATUS $name\__op_ndr_push(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct ndr_push *push, const void *r)
|
||||
{
|
||||
NTSTATUS status;
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
status = dcerpc_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
||||
if (!NT_STATUS_IS_OK(status)) {
|
||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
static const struct dcesrv_interface $name\_interface = {
|
||||
.name = \"$name\",
|
||||
.syntax_id = {".print_uuid($uuid).",$if_version},
|
||||
.bind = $name\__op_bind,
|
||||
.unbind = $name\__op_unbind,
|
||||
.ndr_pull = $name\__op_ndr_pull,
|
||||
.dispatch = $name\__op_dispatch,
|
||||
.reply = $name\__op_reply,
|
||||
.ndr_push = $name\__op_ndr_push
|
||||
};
|
||||
|
||||
";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# produce boilerplate code for an endpoint server
|
||||
sub Boilerplate_Ep_Server($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my $name = $interface->{NAME};
|
||||
my $uname = uc $name;
|
||||
|
||||
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<dcerpc_table_$name.endpoints->count;i++) {
|
||||
NTSTATUS ret;
|
||||
const char *name = dcerpc_table_$name.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 struct GUID *uuid, uint32_t if_version)
|
||||
{
|
||||
if ($name\_interface.syntax_id.if_version == if_version &&
|
||||
GUID_equal(\&$name\_interface.syntax_id.uuid, uuid)) {
|
||||
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.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 = dcerpc_register_ep_server(&ep_server);
|
||||
|
||||
if (!NT_STATUS_IS_OK(ret)) {
|
||||
DEBUG(0,(\"Failed to register \'$name\' endpoint server!\\n\"));
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# dcerpc server boilerplate from a parsed IDL structure
|
||||
sub ParseInterface($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my $count = 0;
|
||||
|
||||
if (!defined $interface->{PROPERTIES}->{uuid}) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
if (!defined $interface->{PROPERTIES}->{version}) {
|
||||
$interface->{PROPERTIES}->{version} = "0.0";
|
||||
}
|
||||
|
||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||
if (defined($fn->{OPNUM})) { $count++; }
|
||||
}
|
||||
|
||||
if ($count == 0) {
|
||||
return $res;
|
||||
}
|
||||
|
||||
$res .= "/* $interface->{NAME} - dcerpc server boilerplate generated by pidl */\n\n";
|
||||
Boilerplate_Iface($interface);
|
||||
Boilerplate_Ep_Server($interface);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub Parse($$)
|
||||
{
|
||||
my($ndr,$header) = @_;
|
||||
|
||||
$res = "";
|
||||
$res .= "/* server functions auto-generated by pidl */\n";
|
||||
$res .= "#include \"$header\"\n";
|
||||
$res .= "\n";
|
||||
|
||||
foreach my $x (@{$ndr}) {
|
||||
ParseInterface($x) if ($x->{TYPE} eq "INTERFACE" and not defined($x->{PROPERTIES}{object}));
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,176 @@
|
||||
###################################################
|
||||
# Samba4 parser generator for swig wrappers
|
||||
# Copyright tpot@samba.org 2004,2005
|
||||
# Copyright jelmer@samba.org 2006
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::SWIG;
|
||||
|
||||
use vars qw($VERSION);
|
||||
use Parse::Pidl::Samba4 qw(DeclLong);
|
||||
use Parse::Pidl::Typelist qw(mapType);
|
||||
use Parse::Pidl::Util qw(has_property);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my $ret = "";
|
||||
my $tabs = "";
|
||||
|
||||
sub pidl($)
|
||||
{
|
||||
my $p = shift;
|
||||
$ret .= $tabs. $p . "\n";
|
||||
}
|
||||
|
||||
sub indent() { $tabs.="\t"; }
|
||||
sub deindent() { $tabs = substr($tabs,0,-1); }
|
||||
|
||||
sub IgnoreInterface($$)
|
||||
{
|
||||
my ($basename,$if) = @_;
|
||||
|
||||
foreach (@{$if->{TYPES}}) {
|
||||
next unless (has_property($_, "public"));
|
||||
pidl "\%types($_->{NAME});";
|
||||
}
|
||||
}
|
||||
|
||||
sub ParseInterface($$)
|
||||
{
|
||||
my ($basename,$if) = @_;
|
||||
|
||||
pidl "\%inline {";
|
||||
pidl "struct $if->{NAME} { struct dcerpc_pipe *pipe; };";
|
||||
pidl "}";
|
||||
pidl "";
|
||||
pidl "\%extend $if->{NAME} {";
|
||||
indent();
|
||||
pidl "$if->{NAME} (const char *binding, struct cli_credentials *cred = NULL, TALLOC_CTX *mem_ctx = NULL, struct event_context *event = NULL)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "struct $if->{NAME} *ret = talloc(mem_ctx, struct $if->{NAME});";
|
||||
pidl "NTSTATUS status;";
|
||||
pidl "";
|
||||
pidl "status = dcerpc_pipe_connect(mem_ctx, &ret->pipe, binding, &dcerpc_table_$if->{NAME}, cred, event);";
|
||||
pidl "if (NT_STATUS_IS_ERR(status)) {";
|
||||
pidl "\tntstatus_exception(status);";
|
||||
pidl "\treturn NULL;";
|
||||
pidl "}";
|
||||
pidl "";
|
||||
pidl "return ret;";
|
||||
deindent;
|
||||
pidl "}";
|
||||
pidl "";
|
||||
pidl "~$if->{NAME}() {";
|
||||
pidl "\ttalloc_free(self);";
|
||||
pidl "}";
|
||||
pidl "";
|
||||
|
||||
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
||||
pidl "/* $fn->{NAME} */";
|
||||
my $args = "";
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
$args .= DeclLong($_) . ", ";
|
||||
}
|
||||
my $name = $fn->{NAME};
|
||||
$name =~ s/^$if->{NAME}_//g;
|
||||
$name =~ s/^$basename\_//g;
|
||||
$args .= "TALLOC_CTX *mem_ctx = NULL";
|
||||
pidl mapType($fn->{RETURN_TYPE}) . " $name($args)";
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "struct $fn->{NAME} r;";
|
||||
pidl "NTSTATUS status;";
|
||||
pidl "";
|
||||
pidl "/* Fill r structure */";
|
||||
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
if (grep(/in/, @{$_->{DIRECTION}})) {
|
||||
pidl "r.in.$_->{NAME} = $_->{NAME};";
|
||||
}
|
||||
}
|
||||
|
||||
pidl "";
|
||||
pidl "status = dcerpc_$fn->{NAME}(self->pipe, mem_ctx, &r);";
|
||||
pidl "if (NT_STATUS_IS_ERR(status)) {";
|
||||
pidl "\tntstatus_exception(status);";
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
pidl "\treturn r.out.result;";
|
||||
} else {
|
||||
pidl "\treturn;";
|
||||
}
|
||||
pidl "}";
|
||||
pidl "";
|
||||
pidl "/* Set out arguments */";
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
next unless (grep(/out/, @{$_->{DIRECTION}}));
|
||||
|
||||
pidl ("/* FIXME: $_->{NAME} [out] argument is not a pointer */") if ($_->{LEVELS}[0]->{TYPE} ne "POINTER");
|
||||
|
||||
pidl "*$_->{NAME} = *r.out.$_->{NAME};";
|
||||
}
|
||||
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
pidl "return r.out.result;";
|
||||
}
|
||||
deindent;
|
||||
pidl "}";
|
||||
pidl "";
|
||||
}
|
||||
|
||||
deindent();
|
||||
pidl "};";
|
||||
pidl "";
|
||||
|
||||
foreach (@{$if->{TYPES}}) {
|
||||
pidl "/* $_->{NAME} */";
|
||||
}
|
||||
|
||||
pidl "";
|
||||
}
|
||||
|
||||
sub Parse($$$$)
|
||||
{
|
||||
my($ndr,$basename,$header,$gen_header) = @_;
|
||||
|
||||
$ret = "";
|
||||
|
||||
pidl "/* This file is autogenerated by pidl. DO NOT EDIT */";
|
||||
|
||||
pidl "\%module $basename";
|
||||
|
||||
pidl "";
|
||||
|
||||
pidl "\%{";
|
||||
pidl "#include \"includes.h\"";
|
||||
pidl "#include \"auth/credentials/credentials.h\"";
|
||||
pidl "#include \"$header\"";
|
||||
pidl "#include \"$gen_header\"";
|
||||
pidl "%}";
|
||||
pidl "\%import \"samba.i\"";
|
||||
pidl "";
|
||||
pidl "\%inline {";
|
||||
pidl "void ntstatus_exception(NTSTATUS status)";
|
||||
pidl "{";
|
||||
pidl "\t/* FIXME */";
|
||||
pidl "}";
|
||||
pidl "}";
|
||||
pidl "";
|
||||
foreach (@$ndr) {
|
||||
IgnoreInterface($basename, $_) if ($_->{TYPE} eq "INTERFACE");
|
||||
}
|
||||
pidl "";
|
||||
|
||||
pidl "";
|
||||
|
||||
foreach (@$ndr) {
|
||||
ParseInterface($basename, $_) if ($_->{TYPE} eq "INTERFACE");
|
||||
}
|
||||
#FIXME: Foreach ref pointer, set NONNULL
|
||||
#FIXME: Foreach unique/full pointer, set MAYBENULL
|
||||
#FIXME: Foreach [out] parameter, set OUTPARAM
|
||||
return $ret;
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,263 @@
|
||||
###################################################
|
||||
# Trivial Parser Generator
|
||||
# Copyright jelmer@samba.org 2005
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::TDR;
|
||||
use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
|
||||
use Parse::Pidl::Samba4 qw(is_intree choose_header);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my $ret;
|
||||
my $ret_hdr;
|
||||
my $tabs = "";
|
||||
|
||||
sub indent() { $tabs.="\t"; }
|
||||
sub deindent() { $tabs = substr($tabs, 1); }
|
||||
sub pidl($) { $ret .= $tabs.(shift)."\n"; }
|
||||
sub pidl_hdr($) { $ret_hdr .= (shift)."\n"; }
|
||||
sub fatal($$) { my ($e,$s) = @_; die("$e->{FILE}:$e->{LINE}: $s\n"); }
|
||||
sub typearg($) {
|
||||
my $t = shift;
|
||||
return(", const char *name") if ($t eq "print");
|
||||
return(", TALLOC_CTX *mem_ctx") if ($t eq "pull");
|
||||
return("");
|
||||
}
|
||||
|
||||
sub fn_declare($$)
|
||||
{
|
||||
my ($p, $d) = @_;
|
||||
if ($p) { pidl $d; pidl_hdr "$d;"; } else { pidl "static $d"; }
|
||||
}
|
||||
|
||||
sub ContainsArray($)
|
||||
{
|
||||
my $e = shift;
|
||||
foreach (@{$e->{ELEMENTS}}) {
|
||||
next if (has_property($_, "charset") and
|
||||
scalar(@{$_->{ARRAY_LEN}}) == 1);
|
||||
return 1 if (defined($_->{ARRAY_LEN}) and
|
||||
scalar(@{$_->{ARRAY_LEN}}) > 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub ParserElement($$$)
|
||||
{
|
||||
my ($e,$t,$env) = @_;
|
||||
my $switch = "";
|
||||
my $array = "";
|
||||
my $name = "";
|
||||
my $mem_ctx = "mem_ctx";
|
||||
|
||||
fatal($e,"Pointers not supported in TDR") if ($e->{POINTERS} > 0);
|
||||
fatal($e,"size_is() not supported in TDR") if (has_property($e, "size_is"));
|
||||
fatal($e,"length_is() not supported in TDR") if (has_property($e, "length_is"));
|
||||
|
||||
if ($t eq "print") {
|
||||
$name = ", \"$e->{NAME}\"$array";
|
||||
}
|
||||
|
||||
if (has_property($e, "flag")) {
|
||||
pidl "{";
|
||||
indent;
|
||||
pidl "uint32_t saved_flags = tdr->flags;";
|
||||
pidl "tdr->flags |= $e->{PROPERTIES}->{flag};";
|
||||
}
|
||||
|
||||
if (has_property($e, "charset")) {
|
||||
fatal($e,"charset() on non-array element") unless (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0);
|
||||
|
||||
my $len = ParseExpr(@{$e->{ARRAY_LEN}}[0], $env);
|
||||
if ($len eq "*") { $len = "-1"; }
|
||||
$name = ", mem_ctx" if ($t eq "pull");
|
||||
pidl "TDR_CHECK(tdr_$t\_charset(tdr$name, &v->$e->{NAME}, $len, sizeof($e->{TYPE}_t), CH_$e->{PROPERTIES}->{charset}));";
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_property($e, "switch_is")) {
|
||||
$switch = ", " . ParseExpr($e->{PROPERTIES}->{switch_is}, $env);
|
||||
}
|
||||
|
||||
if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
|
||||
my $len = ParseExpr($e->{ARRAY_LEN}[0], $env);
|
||||
|
||||
if ($t eq "pull" and not is_constant($len)) {
|
||||
pidl "TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);";
|
||||
$mem_ctx = "v->$e->{NAME}";
|
||||
}
|
||||
|
||||
pidl "for (i = 0; i < $len; i++) {";
|
||||
indent;
|
||||
$array = "[i]";
|
||||
}
|
||||
|
||||
if ($t eq "pull") {
|
||||
$name = ", $mem_ctx";
|
||||
}
|
||||
|
||||
if (has_property($e, "value") && $t eq "push") {
|
||||
pidl "v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env).";";
|
||||
}
|
||||
|
||||
pidl "TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));";
|
||||
|
||||
if ($array) { deindent; pidl "}"; }
|
||||
|
||||
if (has_property($e, "flag")) {
|
||||
pidl "tdr->flags = saved_flags;";
|
||||
deindent;
|
||||
pidl "}";
|
||||
}
|
||||
}
|
||||
|
||||
sub ParserStruct($$$$)
|
||||
{
|
||||
my ($e,$n,$t,$p) = @_;
|
||||
|
||||
fn_declare($p,,"NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".typearg($t).", struct $n *v)");
|
||||
pidl "{"; indent;
|
||||
pidl "int i;" if (ContainsArray($e));
|
||||
|
||||
if ($t eq "print") {
|
||||
pidl "tdr->print(tdr, \"\%-25s: struct $n\", name);";
|
||||
pidl "tdr->level++;";
|
||||
}
|
||||
|
||||
my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
|
||||
$env{"this"} = "v";
|
||||
ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
|
||||
|
||||
if ($t eq "print") {
|
||||
pidl "tdr->level--;";
|
||||
}
|
||||
|
||||
pidl "return NT_STATUS_OK;";
|
||||
|
||||
deindent; pidl "}";
|
||||
}
|
||||
|
||||
sub ParserUnion($$$$)
|
||||
{
|
||||
my ($e,$n,$t,$p) = @_;
|
||||
|
||||
fn_declare($p,"NTSTATUS tdr_$t\_$n(struct tdr_$t *tdr".typearg($t).", int level, union $n *v)");
|
||||
pidl "{"; indent;
|
||||
pidl "int i;" if (ContainsArray($e));
|
||||
|
||||
if ($t eq "print") {
|
||||
pidl "tdr->print(tdr, \"\%-25s: union $n\", name);";
|
||||
pidl "tdr->level++;";
|
||||
}
|
||||
|
||||
pidl "switch (level) {"; indent;
|
||||
foreach (@{$e->{ELEMENTS}}) {
|
||||
if (has_property($_, "case")) {
|
||||
pidl "case " . $_->{PROPERTIES}->{case} . ":";
|
||||
} elsif (has_property($_, "default")) {
|
||||
pidl "default:";
|
||||
}
|
||||
indent; ParserElement($_, $t, {}); deindent;
|
||||
pidl "break;";
|
||||
}
|
||||
deindent; pidl "}";
|
||||
|
||||
if ($t eq "print") {
|
||||
pidl "tdr->level--;";
|
||||
}
|
||||
|
||||
pidl "return NT_STATUS_OK;\n";
|
||||
deindent; pidl "}";
|
||||
}
|
||||
|
||||
sub ParserBitmap($$$$)
|
||||
{
|
||||
my ($e,$n,$t,$p) = @_;
|
||||
return if ($p);
|
||||
pidl "#define tdr_$t\_$n tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e);
|
||||
}
|
||||
|
||||
sub ParserEnum($$$$)
|
||||
{
|
||||
my ($e,$n,$t,$p) = @_;
|
||||
my $bt = ($e->{PROPERTIES}->{base_type} or "uint8");
|
||||
|
||||
fn_declare($p, "NTSTATUS tdr_$t\_$n (struct tdr_$t *tdr".typearg($t).", enum $n *v)");
|
||||
pidl "{";
|
||||
if ($t eq "pull") {
|
||||
pidl "\t$bt\_t r;";
|
||||
pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));";
|
||||
pidl "\t*v = r;";
|
||||
} elsif ($t eq "push") {
|
||||
pidl "\tTDR_CHECK(tdr_$t\_$bt(tdr, ($bt\_t *)v));";
|
||||
} elsif ($t eq "print") {
|
||||
pidl "\t/* FIXME */";
|
||||
}
|
||||
pidl "\treturn NT_STATUS_OK;";
|
||||
pidl "}";
|
||||
}
|
||||
|
||||
sub ParserTypedef($$)
|
||||
{
|
||||
my ($e,$t) = @_;
|
||||
|
||||
return if (has_property($e, "no$t"));
|
||||
|
||||
$e->{DATA}->{PROPERTIES} = $e->{PROPERTIES};
|
||||
|
||||
{ STRUCT => \&ParserStruct, UNION => \&ParserUnion,
|
||||
ENUM => \&ParserEnum, BITMAP => \&ParserBitmap
|
||||
}->{$e->{DATA}->{TYPE}}->($e->{DATA}, $e->{NAME}, $t, has_property($e, "public"));
|
||||
|
||||
pidl "";
|
||||
}
|
||||
|
||||
sub ParserInterface($)
|
||||
{
|
||||
my $x = shift;
|
||||
|
||||
pidl_hdr "#ifndef __TDR_$x->{NAME}_HEADER__";
|
||||
pidl_hdr "#define __TDR_$x->{NAME}_HEADER__";
|
||||
|
||||
foreach (@{$x->{DATA}}) {
|
||||
next if ($_->{TYPE} ne "TYPEDEF");
|
||||
ParserTypedef($_, "pull");
|
||||
ParserTypedef($_, "push");
|
||||
ParserTypedef($_, "print");
|
||||
}
|
||||
|
||||
pidl_hdr "#endif /* __TDR_$x->{NAME}_HEADER__ */";
|
||||
}
|
||||
|
||||
sub Parser($$$)
|
||||
{
|
||||
my ($idl,$hdrname,$baseheader) = @_;
|
||||
$ret = ""; $ret_hdr = "";
|
||||
pidl "/* autogenerated by pidl */";
|
||||
if (is_intree()) {
|
||||
pidl "#include \"includes.h\"";
|
||||
} else {
|
||||
pidl "#include <stdio.h>";
|
||||
pidl "#include <stdbool.h>";
|
||||
pidl "#include <stdlib.h>";
|
||||
pidl "#include <stdint.h>";
|
||||
pidl "#include <stdarg.h>";
|
||||
pidl "#include <string.h>";
|
||||
pidl "#include <core/nterr.h>";
|
||||
}
|
||||
pidl "#include \"$hdrname\"";
|
||||
pidl "";
|
||||
pidl_hdr "/* autogenerated by pidl */";
|
||||
pidl_hdr "#include \"$baseheader\"";
|
||||
pidl_hdr choose_header("tdr/tdr.h", "tdr.h");
|
||||
pidl_hdr "";
|
||||
|
||||
foreach (@$idl) { ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
|
||||
return ($ret_hdr, $ret);
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,99 @@
|
||||
###################################################
|
||||
# server template function generator
|
||||
# Copyright tridge@samba.org 2003
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::Template;
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my($res);
|
||||
|
||||
#####################################################################
|
||||
# produce boilerplate code for a interface
|
||||
sub Template($)
|
||||
{
|
||||
my($interface) = shift;
|
||||
my($data) = $interface->{DATA};
|
||||
my $name = $interface->{NAME};
|
||||
|
||||
$res .=
|
||||
"/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
endpoint server for the $name pipe
|
||||
|
||||
Copyright (C) YOUR NAME HERE YEAR
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include \"includes.h\"
|
||||
#include \"rpc_server/dcerpc_server.h\"
|
||||
#include \"librpc/gen_ndr/ndr_$name.h\"
|
||||
#include \"rpc_server/common/common.h\"
|
||||
|
||||
";
|
||||
|
||||
foreach my $d (@{$data}) {
|
||||
if ($d->{TYPE} eq "FUNCTION") {
|
||||
my $fname = $d->{NAME};
|
||||
$res .=
|
||||
"
|
||||
/*
|
||||
$fname
|
||||
*/
|
||||
static $d->{RETURN_TYPE} $fname(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
|
||||
struct $fname *r)
|
||||
{
|
||||
";
|
||||
|
||||
if ($d->{RETURN_TYPE} eq "void") {
|
||||
$res .= "\tDCESRV_FAULT_VOID(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
||||
} else {
|
||||
$res .= "\tDCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);\n";
|
||||
}
|
||||
|
||||
$res .= "}
|
||||
|
||||
";
|
||||
}
|
||||
}
|
||||
|
||||
$res .=
|
||||
"
|
||||
/* include the generated boilerplate */
|
||||
#include \"librpc/gen_ndr/ndr_$name\_s.c\"
|
||||
"
|
||||
}
|
||||
|
||||
|
||||
#####################################################################
|
||||
# parse a parsed IDL structure back into an IDL file
|
||||
sub Parse($)
|
||||
{
|
||||
my($idl) = shift;
|
||||
$res = "";
|
||||
foreach my $x (@{$idl}) {
|
||||
($x->{TYPE} eq "INTERFACE") &&
|
||||
Template($x);
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
||||
Reference in New Issue
Block a user