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;
|
||||
Reference in New Issue
Block a user