Add pidl. Add preliminary work on SecIP.
Please note that the Alphatronics implementation does not follow the Vebon specification. An extra padding byte had to be added to the idl..
This commit is contained in:
parent
1972b32b60
commit
ad758df90b
67 changed files with 24048 additions and 1 deletions
160
pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
160
pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
|
@ -0,0 +1,160 @@
|
|||
# COM Header generation
|
||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
package Parse::Pidl::Samba4::COM::Header;
|
||||
|
||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||
use Parse::Pidl::Util qw(has_property is_constant);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
sub GetArgumentProtoList($)
|
||||
{
|
||||
my $f = shift;
|
||||
my $res = "";
|
||||
|
||||
foreach my $a (@{$f->{ELEMENTS}}) {
|
||||
|
||||
$res .= ", " . mapTypeName($a->{TYPE}) . " ";
|
||||
|
||||
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 GetArgumentList($)
|
||||
{
|
||||
my $f = shift;
|
||||
my $res = "";
|
||||
|
||||
foreach (@{$f->{ELEMENTS}}) { $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}) {
|
||||
$res .= "\t" . mapTypeName($d->{RETURN_TYPE}) . " (*$d->{NAME}) (struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . GetArgumentProtoList($d) . ");\\\n" if ($d->{TYPE} eq "FUNCTION");
|
||||
}
|
||||
$res .= "\n";
|
||||
$res .= "struct $interface->{NAME}_vtable {\n";
|
||||
$res .= "\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#ifndef _$if->{NAME}_\n";
|
||||
$res .= "#define _$if->{NAME}_\n";
|
||||
|
||||
$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");
|
||||
|
||||
$res .= "#define $if->{NAME}_$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . ") ";
|
||||
|
||||
$res .= "((interface)->vtable->$d->{NAME}(interface, mem_ctx" . GetArgumentList($d) . "))";
|
||||
|
||||
$res .="\n";
|
||||
}
|
||||
|
||||
$res .= "#endif\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub ParseCoClass($)
|
||||
{
|
||||
my ($c) = @_;
|
||||
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 = "";
|
||||
my $has_obj = 0;
|
||||
|
||||
$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";
|
||||
$has_obj = 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (@{$idl})
|
||||
{
|
||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
||||
$res.=ParseInterface($_);
|
||||
$has_obj = 1;
|
||||
}
|
||||
|
||||
if ($_->{TYPE} eq "COCLASS") {
|
||||
$res.=ParseCoClass($_);
|
||||
$has_obj = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return $res if ($has_obj);
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
225
pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
225
pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
|
@ -0,0 +1,225 @@
|
|||
###################################################
|
||||
# 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::Typelist qw(mapTypeName);
|
||||
use Parse::Pidl::Util qw(has_property);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my($res);
|
||||
|
||||
sub ParseVTable($$)
|
||||
{
|
||||
my ($interface, $name) = @_;
|
||||
|
||||
# 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 .= "static NTSTATUS 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 = ndr_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.= "
|
||||
proxy_vtable->iid = ndr_table_$interface->{NAME}.syntax_id.uuid;
|
||||
|
||||
return dcom_register_proxy((struct IUnknown_vtable *)proxy_vtable);
|
||||
}\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseFunction($$)
|
||||
{
|
||||
my ($interface, $fn) = @_;
|
||||
my $name = $fn->{NAME};
|
||||
my $uname = uc $name;
|
||||
|
||||
my $tn = mapTypeName($fn->{RETURN_TYPE});
|
||||
|
||||
$res.="
|
||||
static $tn dcom_proxy_$interface->{NAME}_$name(struct $interface->{NAME} *d, TALLOC_CTX *mem_ctx" . Parse::Pidl::Samba4::COM::Header::GetArgumentProtoList($fn) . ")
|
||||
{
|
||||
struct dcerpc_pipe *p;
|
||||
NTSTATUS status = dcom_get_pipe(d, &p);
|
||||
struct $name r;
|
||||
struct rpc_request *req;
|
||||
|
||||
if (NT_STATUS_IS_ERR(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
ZERO_STRUCT(r.in.ORPCthis);
|
||||
r.in.ORPCthis.version.MajorVersion = COM_MAJOR_VERSION;
|
||||
r.in.ORPCthis.version.MinorVersion = COM_MINOR_VERSION;
|
||||
";
|
||||
|
||||
# Put arguments into r
|
||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "in"));
|
||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||
$res .="\tNDR_CHECK(dcom_OBJREF_from_IUnknown(mem_ctx, &r.in.$a->{NAME}.obj, $a->{NAME}));\n";
|
||||
} else {
|
||||
$res .= "\tr.in.$a->{NAME} = $a->{NAME};\n";
|
||||
}
|
||||
}
|
||||
|
||||
$res .="
|
||||
if (p->conn->flags & DCERPC_DEBUG_PRINT_IN) {
|
||||
NDR_PRINT_IN_DEBUG($name, &r);
|
||||
}
|
||||
|
||||
status = dcerpc_ndr_request(p, &d->ipid, &ndr_table_$interface->{NAME}, NDR_$uname, mem_ctx, &r);
|
||||
|
||||
if (NT_STATUS_IS_OK(status) && (p->conn->flags & DCERPC_DEBUG_PRINT_OUT)) {
|
||||
NDR_PRINT_OUT_DEBUG($name, r);
|
||||
}
|
||||
|
||||
";
|
||||
|
||||
# Put r info back into arguments
|
||||
foreach my $a (@{$fn->{ELEMENTS}}) {
|
||||
next unless (has_property($a, "out"));
|
||||
|
||||
if (Parse::Pidl::Typelist::typeIs($a->{TYPE}, "INTERFACE")) {
|
||||
$res .="\tNDR_CHECK(dcom_IUnknown_from_OBJREF(d->ctx, &$a->{NAME}, r.out.$a->{NAME}.obj));\n";
|
||||
} else {
|
||||
$res .= "\t*$a->{NAME} = r.out.$a->{NAME};\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($fn->{RETURN_TYPE} eq "NTSTATUS") {
|
||||
$res .= "\tif (NT_STATUS_IS_OK(status)) status = r.out.result;\n";
|
||||
}
|
||||
|
||||
$res .=
|
||||
"
|
||||
return r.out.result;
|
||||
}\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# 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 = "";
|
||||
my $has_obj = 0;
|
||||
|
||||
$res .= "#include \"includes.h\"\n" .
|
||||
"#include \"lib/com/dcom/dcom.h\"\n" .
|
||||
"#include \"$comh_filename\"\n" .
|
||||
"#include \"librpc/rpc/dcerpc.h\"\n";
|
||||
|
||||
foreach (@{$pidl}) {
|
||||
next if ($_->{TYPE} ne "INTERFACE");
|
||||
next if has_property($_, "local");
|
||||
next unless has_property($_, "object");
|
||||
|
||||
$res .= ParseInterface($_);
|
||||
|
||||
$has_obj = 1;
|
||||
}
|
||||
|
||||
return $res if ($has_obj);
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
327
pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm
Normal file
327
pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm
Normal file
|
@ -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, uint32_t if_version)
|
||||
{
|
||||
#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;
|
537
pidl/lib/Parse/Pidl/Samba4/Header.pm
Normal file
537
pidl/lib/Parse/Pidl/Samba4/Header.pm
Normal file
|
@ -0,0 +1,537 @@
|
|||
###################################################
|
||||
# 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;
|
||||
require Exporter;
|
||||
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT_OK = qw(GenerateFunctionInEnv GenerateFunctionOutEnv EnvSubstituteValue GenerateStructEnv);
|
||||
|
||||
use strict;
|
||||
use Parse::Pidl qw(fatal);
|
||||
use Parse::Pidl::Typelist qw(mapTypeName scalar_is_reference);
|
||||
use Parse::Pidl::Util qw(has_property is_constant unmake_str ParseExpr);
|
||||
use Parse::Pidl::Samba4 qw(is_intree ElementStars ArrayBrackets choose_header);
|
||||
|
||||
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 mapTypeName($element->{PROPERTIES}->{represent_as})." ";
|
||||
} else {
|
||||
if (ref($element->{TYPE}) eq "HASH") {
|
||||
HeaderType($element, $element->{TYPE}, $element->{TYPE}->{NAME});
|
||||
} else {
|
||||
HeaderType($element, $element->{TYPE}, "");
|
||||
}
|
||||
pidl " ".ElementStars($element);
|
||||
}
|
||||
pidl $element->{NAME};
|
||||
pidl ArrayBrackets($element);
|
||||
|
||||
pidl ";";
|
||||
if (defined $element->{PROPERTIES}) {
|
||||
HeaderProperties($element->{PROPERTIES}, ["in", "out"]);
|
||||
}
|
||||
pidl "\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a struct
|
||||
sub HeaderStruct($$;$)
|
||||
{
|
||||
my($struct,$name,$tail) = @_;
|
||||
pidl "struct $name";
|
||||
pidl $tail if defined($tail) and not defined($struct->{ELEMENTS});
|
||||
return if (not defined($struct->{ELEMENTS}));
|
||||
pidl " {\n";
|
||||
$tab_depth++;
|
||||
my $el_count=0;
|
||||
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}, []);
|
||||
}
|
||||
pidl $tail if defined($tail);
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a enum
|
||||
sub HeaderEnum($$;$)
|
||||
{
|
||||
my($enum,$name,$tail) = @_;
|
||||
my $first = 1;
|
||||
|
||||
pidl "enum $name";
|
||||
if (defined($enum->{ELEMENTS})) {
|
||||
pidl "\n#ifndef USE_UINT_ENUMS\n";
|
||||
pidl " {\n";
|
||||
$tab_depth++;
|
||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
||||
my @enum_els = ();
|
||||
unless ($first) { pidl ",\n"; }
|
||||
$first = 0;
|
||||
pidl tabs();
|
||||
@enum_els = split(/=/, $e);
|
||||
if (@enum_els == 2) {
|
||||
pidl $enum_els[0];
|
||||
pidl "=(int)";
|
||||
pidl "(";
|
||||
pidl $enum_els[1];
|
||||
pidl ")";
|
||||
} else {
|
||||
pidl $e;
|
||||
}
|
||||
}
|
||||
pidl "\n";
|
||||
$tab_depth--;
|
||||
pidl "}";
|
||||
pidl "\n";
|
||||
pidl "#else\n";
|
||||
my $count = 0;
|
||||
my $with_val = 0;
|
||||
my $without_val = 0;
|
||||
pidl " { __donnot_use_enum_$name=0x7FFFFFFF}\n";
|
||||
foreach my $e (@{$enum->{ELEMENTS}}) {
|
||||
my $t = "$e";
|
||||
my $name;
|
||||
my $value;
|
||||
if ($t =~ /(.*)=(.*)/) {
|
||||
$name = $1;
|
||||
$value = $2;
|
||||
$with_val = 1;
|
||||
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
||||
unless ($without_val == 0);
|
||||
} else {
|
||||
$name = $t;
|
||||
$value = $count++;
|
||||
$without_val = 1;
|
||||
fatal($e->{ORIGINAL}, "you can't mix enum member with values and without values!")
|
||||
unless ($with_val == 0);
|
||||
}
|
||||
pidl "#define $name ( $value )\n";
|
||||
}
|
||||
pidl "#endif\n";
|
||||
}
|
||||
pidl $tail if defined($tail);
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a bitmap
|
||||
sub HeaderBitmap($$)
|
||||
{
|
||||
my($bitmap,$name) = @_;
|
||||
|
||||
return unless defined($bitmap->{ELEMENTS});
|
||||
|
||||
pidl "/* bitmap $name */\n";
|
||||
pidl "#define $_\n" foreach (@{$bitmap->{ELEMENTS}});
|
||||
pidl "\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a union
|
||||
sub HeaderUnion($$;$)
|
||||
{
|
||||
my($union,$name,$tail) = @_;
|
||||
my %done = ();
|
||||
|
||||
pidl "union $name";
|
||||
pidl $tail if defined($tail) and not defined($union->{ELEMENTS});
|
||||
return if (not defined($union->{ELEMENTS}));
|
||||
pidl " {\n";
|
||||
$tab_depth++;
|
||||
my $needed = 0;
|
||||
foreach my $e (@{$union->{ELEMENTS}}) {
|
||||
if ($e->{TYPE} ne "EMPTY") {
|
||||
if (! defined $done{$e->{NAME}}) {
|
||||
HeaderElement($e);
|
||||
}
|
||||
$done{$e->{NAME}} = 1;
|
||||
$needed++;
|
||||
}
|
||||
}
|
||||
if (!$needed) {
|
||||
# sigh - some compilers don't like empty structures
|
||||
pidl tabs()."int _dummy_element;\n";
|
||||
}
|
||||
$tab_depth--;
|
||||
pidl "}";
|
||||
|
||||
if (defined $union->{PROPERTIES}) {
|
||||
HeaderProperties($union->{PROPERTIES}, []);
|
||||
}
|
||||
pidl $tail if defined($tail);
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a pipe
|
||||
sub HeaderPipe($$;$)
|
||||
{
|
||||
my($pipe,$name,$tail) = @_;
|
||||
|
||||
my $struct = $pipe->{DATA};
|
||||
my $e = $struct->{ELEMENTS}[1];
|
||||
|
||||
pidl "struct $name;\n";
|
||||
pidl "struct $struct->{NAME} {\n";
|
||||
$tab_depth++;
|
||||
pidl tabs()."uint32_t count;\n";
|
||||
pidl tabs().mapTypeName($e->{TYPE})." *array;\n";
|
||||
$tab_depth--;
|
||||
pidl "}";
|
||||
|
||||
if (defined $struct->{PROPERTIES}) {
|
||||
HeaderProperties($struct->{PROPERTIES}, []);
|
||||
}
|
||||
|
||||
pidl $tail if defined($tail);
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a type
|
||||
sub HeaderType($$$;$)
|
||||
{
|
||||
my($e,$data,$name,$tail) = @_;
|
||||
if (ref($data) eq "HASH") {
|
||||
($data->{TYPE} eq "ENUM") && HeaderEnum($data, $name, $tail);
|
||||
($data->{TYPE} eq "BITMAP") && HeaderBitmap($data, $name);
|
||||
($data->{TYPE} eq "STRUCT") && HeaderStruct($data, $name, $tail);
|
||||
($data->{TYPE} eq "UNION") && HeaderUnion($data, $name, $tail);
|
||||
($data->{TYPE} eq "PIPE") && HeaderPipe($data, $name, $tail);
|
||||
return;
|
||||
}
|
||||
|
||||
if (has_property($e, "charset")) {
|
||||
pidl "const char";
|
||||
} else {
|
||||
pidl mapTypeName($e->{TYPE});
|
||||
}
|
||||
pidl $tail if defined($tail);
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a typedef
|
||||
sub HeaderTypedef($;$)
|
||||
{
|
||||
my($typedef,$tail) = @_;
|
||||
# Don't print empty "enum foo;", since some compilers don't like it.
|
||||
return if ($typedef->{DATA}->{TYPE} eq "ENUM" and not defined($typedef->{DATA}->{ELEMENTS}));
|
||||
HeaderType($typedef, $typedef->{DATA}, $typedef->{NAME}, $tail) if defined ($typedef->{DATA});
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# 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";
|
||||
}
|
||||
}
|
||||
|
||||
sub ElementDirection($)
|
||||
{
|
||||
my ($e) = @_;
|
||||
|
||||
return "inout" if (has_property($e, "in") and has_property($e, "out"));
|
||||
return "in" if (has_property($e, "in"));
|
||||
return "out" if (has_property($e, "out"));
|
||||
return "inout";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub HeaderFunctionInOut($$)
|
||||
{
|
||||
my($fn,$prop) = @_;
|
||||
|
||||
return unless defined($fn->{ELEMENTS});
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
HeaderElement($e) if (ElementDirection($e) eq $prop);
|
||||
}
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# determine if we need an "in" or "out" section
|
||||
sub HeaderFunctionInOut_needed($$)
|
||||
{
|
||||
my($fn,$prop) = @_;
|
||||
|
||||
return 1 if ($prop eq "out" && defined($fn->{RETURN_TYPE}));
|
||||
|
||||
return undef unless defined($fn->{ELEMENTS});
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
return 1 if (ElementDirection($e) eq $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") or
|
||||
HeaderFunctionInOut_needed($fn, "inout")) {
|
||||
pidl tabs()."struct {\n";
|
||||
$tab_depth++;
|
||||
HeaderFunctionInOut($fn, "in");
|
||||
HeaderFunctionInOut($fn, "inout");
|
||||
$tab_depth--;
|
||||
pidl tabs()."} in;\n\n";
|
||||
$needed++;
|
||||
}
|
||||
|
||||
if (HeaderFunctionInOut_needed($fn, "out") or
|
||||
HeaderFunctionInOut_needed($fn, "inout")) {
|
||||
pidl tabs()."struct {\n";
|
||||
$tab_depth++;
|
||||
HeaderFunctionInOut($fn, "out");
|
||||
HeaderFunctionInOut($fn, "inout");
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
pidl tabs().mapTypeName($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 my $import (@imports) {
|
||||
$import = unmake_str($import);
|
||||
$import =~ s/\.idl$//;
|
||||
pidl choose_header("librpc/gen_ndr/$import\.h", "gen_ndr/$import.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 $c (@{$interface->{CONSTS}}) {
|
||||
HeaderConst($c);
|
||||
}
|
||||
|
||||
foreach my $t (@{$interface->{TYPES}}) {
|
||||
HeaderTypedef($t, ";\n\n") if ($t->{TYPE} eq "TYPEDEF");
|
||||
HeaderStruct($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "STRUCT");
|
||||
HeaderUnion($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "UNION");
|
||||
HeaderEnum($t, $t->{NAME}, ";\n\n") if ($t->{TYPE} eq "ENUM");
|
||||
HeaderBitmap($t, $t->{NAME}) if ($t->{TYPE} eq "BITMAP");
|
||||
HeaderPipe($t, $t->{NAME}, "\n\n") if ($t->{TYPE} eq "PIPE");
|
||||
}
|
||||
|
||||
foreach my $fn (@{$interface->{FUNCTIONS}}) {
|
||||
HeaderFunction($fn);
|
||||
}
|
||||
|
||||
pidl "#endif /* _HEADER_$interface->{NAME} */\n";
|
||||
}
|
||||
|
||||
sub HeaderQuote($)
|
||||
{
|
||||
my($quote) = shift;
|
||||
|
||||
pidl unmake_str($quote->{DATA}) . "\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a parsed IDL into a C header
|
||||
sub Parse($)
|
||||
{
|
||||
my($ndr) = shift;
|
||||
$tab_depth = 0;
|
||||
|
||||
$res = "";
|
||||
%headerstructs = ();
|
||||
pidl "/* header auto-generated by pidl */\n\n";
|
||||
|
||||
my $ifacename = "";
|
||||
|
||||
# work out a unique interface name
|
||||
foreach (@{$ndr}) {
|
||||
if ($_->{TYPE} eq "INTERFACE") {
|
||||
$ifacename = $_->{NAME};
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
pidl "#ifndef _PIDL_HEADER_$ifacename\n";
|
||||
pidl "#define _PIDL_HEADER_$ifacename\n\n";
|
||||
|
||||
if (!is_intree()) {
|
||||
pidl "#include <util/data_blob.h>\n";
|
||||
}
|
||||
pidl "#include <stdint.h>\n";
|
||||
pidl "\n";
|
||||
# FIXME: Include this only if NTSTATUS was actually used
|
||||
pidl choose_header("libcli/util/ntstatus.h", "core/ntstatus.h") . "\n";
|
||||
pidl "\n";
|
||||
|
||||
foreach (@{$ndr}) {
|
||||
($_->{TYPE} eq "CPP_QUOTE") && HeaderQuote($_);
|
||||
($_->{TYPE} eq "INTERFACE") && HeaderInterface($_);
|
||||
($_->{TYPE} eq "IMPORT") && HeaderImport(@{$_->{PATHS}});
|
||||
($_->{TYPE} eq "INCLUDE") && HeaderInclude(@{$_->{PATHS}});
|
||||
}
|
||||
|
||||
pidl "#endif /* _PIDL_HEADER_$ifacename */\n";
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub GenerateStructEnv($$)
|
||||
{
|
||||
my ($x, $v) = @_;
|
||||
my %env;
|
||||
|
||||
foreach my $e (@{$x->{ELEMENTS}}) {
|
||||
$env{$e->{NAME}} = "$v->$e->{NAME}";
|
||||
}
|
||||
|
||||
$env{"this"} = $v;
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
sub EnvSubstituteValue($$)
|
||||
{
|
||||
my ($env,$s) = @_;
|
||||
|
||||
# Substitute the value() values in the env
|
||||
foreach my $e (@{$s->{ELEMENTS}}) {
|
||||
next unless (defined(my $v = has_property($e, "value")));
|
||||
|
||||
$env->{$e->{NAME}} = ParseExpr($v, $env, $e);
|
||||
}
|
||||
|
||||
return $env;
|
||||
}
|
||||
|
||||
sub GenerateFunctionInEnv($;$)
|
||||
{
|
||||
my ($fn, $base) = @_;
|
||||
my %env;
|
||||
|
||||
$base = "r->" unless defined($base);
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
if (grep (/in/, @{$e->{DIRECTION}})) {
|
||||
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
||||
}
|
||||
}
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
sub GenerateFunctionOutEnv($;$)
|
||||
{
|
||||
my ($fn, $base) = @_;
|
||||
my %env;
|
||||
|
||||
$base = "r->" unless defined($base);
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
if (grep (/out/, @{$e->{DIRECTION}})) {
|
||||
$env{$e->{NAME}} = $base."out.$e->{NAME}";
|
||||
} elsif (grep (/in/, @{$e->{DIRECTION}})) {
|
||||
$env{$e->{NAME}} = $base."in.$e->{NAME}";
|
||||
}
|
||||
}
|
||||
|
||||
return \%env;
|
||||
}
|
||||
|
||||
1;
|
875
pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
Normal file
875
pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
Normal file
|
@ -0,0 +1,875 @@
|
|||
###################################################
|
||||
# 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 Exporter;
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT_OK = qw(Parse);
|
||||
|
||||
use Parse::Pidl qw(fatal warning error);
|
||||
use Parse::Pidl::Util qw(has_property ParseExpr);
|
||||
use Parse::Pidl::NDR qw(ContainsPipe);
|
||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||
use Parse::Pidl::Samba4 qw(choose_header is_intree DeclLong);
|
||||
use Parse::Pidl::Samba4::Header qw(GenerateFunctionInEnv GenerateFunctionOutEnv);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
sub indent($) { my ($self) = @_; $self->{tabs}.="\t"; }
|
||||
sub deindent($) { my ($self) = @_; $self->{tabs} = substr($self->{tabs}, 1); }
|
||||
sub pidl($$) { my ($self,$txt) = @_; $self->{res} .= $txt ? "$self->{tabs}$txt\n" : "\n"; }
|
||||
sub pidl_hdr($$) { my ($self, $txt) = @_; $self->{res_hdr} .= "$txt\n"; }
|
||||
sub pidl_both($$) { my ($self, $txt) = @_; $self->{hdr} .= "$txt\n"; $self->{res_hdr} .= "$txt\n"; }
|
||||
sub fn_declare($$) { my ($self,$n) = @_; $self->pidl($n); $self->pidl_hdr("$n;"); }
|
||||
|
||||
sub genpad($)
|
||||
{
|
||||
my ($s) = @_;
|
||||
my $nt = int((length($s)+1)/8);
|
||||
my $lt = ($nt*8)-1;
|
||||
my $ns = (length($s)-$lt);
|
||||
return "\t"x($nt)." "x($ns);
|
||||
}
|
||||
|
||||
sub new($)
|
||||
{
|
||||
my ($class) = shift;
|
||||
my $self = { res => "", res_hdr => "", tabs => "" };
|
||||
bless($self, $class);
|
||||
}
|
||||
|
||||
sub ParseFunctionHasPipes($$)
|
||||
{
|
||||
my ($self, $fn) = @_;
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
return 1 if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub ParseFunction_r_State($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
my $uname = uc $name;
|
||||
|
||||
$self->pidl("struct dcerpc_$name\_r_state {");
|
||||
$self->indent;
|
||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
||||
$self->deindent;
|
||||
$self->pidl("};");
|
||||
$self->pidl("");
|
||||
$self->pidl("static void dcerpc_$name\_r_done(struct tevent_req *subreq);");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_r_Send($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
my $uname = uc $name;
|
||||
|
||||
my $proto = "struct tevent_req *dcerpc_$name\_r_send(TALLOC_CTX *mem_ctx,\n";
|
||||
$proto .= "\tstruct tevent_context *ev,\n",
|
||||
$proto .= "\tstruct dcerpc_binding_handle *h,\n",
|
||||
$proto .= "\tstruct $name *r)";
|
||||
|
||||
$self->fn_declare($proto);
|
||||
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
|
||||
$self->pidl("struct tevent_req *req;");
|
||||
$self->pidl("struct dcerpc_$name\_r_state *state;");
|
||||
$self->pidl("struct tevent_req *subreq;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
||||
$self->pidl("\t\t\tstruct dcerpc_$name\_r_state);");
|
||||
$self->pidl("if (req == NULL) {");
|
||||
$self->indent;
|
||||
$self->pidl("return NULL;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
my $out_params = 0;
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||
$out_params++;
|
||||
|
||||
}
|
||||
|
||||
my $submem;
|
||||
if ($out_params > 0) {
|
||||
$self->pidl("state->out_mem_ctx = talloc_new(state);");
|
||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
||||
$self->indent;
|
||||
$self->pidl("return tevent_req_post(req, ev);");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$submem = "state->out_mem_ctx";
|
||||
} else {
|
||||
$self->pidl("state->out_mem_ctx = NULL;");
|
||||
$submem = "state";
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("subreq = dcerpc_binding_handle_call_send(state, ev, h,");
|
||||
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
||||
$self->pidl("\t\tNDR_$uname, $submem, r);");
|
||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
||||
$self->indent;
|
||||
$self->pidl("return tevent_req_post(req, ev);");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("tevent_req_set_callback(subreq, dcerpc_$name\_r_done, req);");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("return req;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_r_Done($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
my $uname = uc $name;
|
||||
|
||||
my $proto = "static void dcerpc_$name\_r_done(struct tevent_req *subreq)";
|
||||
|
||||
$self->pidl("$proto");
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
|
||||
$self->pidl("struct tevent_req *req =");
|
||||
$self->pidl("\ttevent_req_callback_data(subreq,");
|
||||
$self->pidl("\tstruct tevent_req);");
|
||||
$self->pidl("NTSTATUS status;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("status = dcerpc_binding_handle_call_recv(subreq);");
|
||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||
$self->indent;
|
||||
$self->pidl("tevent_req_nterror(req, status);");
|
||||
$self->pidl("return;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("tevent_req_done(req);");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_r_Recv($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
my $uname = uc $name;
|
||||
|
||||
my $proto = "NTSTATUS dcerpc_$name\_r_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx)";
|
||||
|
||||
$self->fn_declare($proto);
|
||||
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
|
||||
$self->pidl("struct dcerpc_$name\_r_state *state =");
|
||||
$self->pidl("\ttevent_req_data(req,");
|
||||
$self->pidl("\tstruct dcerpc_$name\_r_state);");
|
||||
$self->pidl("NTSTATUS status;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
||||
$self->indent;
|
||||
$self->pidl("tevent_req_received(req);");
|
||||
$self->pidl("return status;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("tevent_req_received(req);");
|
||||
$self->pidl("return NT_STATUS_OK;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_r_Sync($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
my $uname = uc $name;
|
||||
|
||||
if ($self->ParseFunctionHasPipes($fn)) {
|
||||
$self->pidl_both("/*");
|
||||
$self->pidl_both(" * The following function is skipped because");
|
||||
$self->pidl_both(" * it uses pipes:");
|
||||
$self->pidl_both(" *");
|
||||
$self->pidl_both(" * dcerpc_$name\_r()");
|
||||
$self->pidl_both(" */");
|
||||
$self->pidl_both("");
|
||||
return;
|
||||
}
|
||||
|
||||
my $proto = "NTSTATUS dcerpc_$name\_r(struct dcerpc_binding_handle *h, TALLOC_CTX *mem_ctx, struct $name *r)";
|
||||
|
||||
$self->fn_declare($proto);
|
||||
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
$self->pidl("NTSTATUS status;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("status = dcerpc_binding_handle_call(h,");
|
||||
$self->pidl("\t\tNULL, &ndr_table_$if->{NAME},");
|
||||
$self->pidl("\t\tNDR_$uname, mem_ctx, r);");
|
||||
$self->pidl("");
|
||||
$self->pidl("return status;");
|
||||
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ElementDirection($)
|
||||
{
|
||||
my ($e) = @_;
|
||||
|
||||
return "[in,out]" if (has_property($e, "in") and has_property($e, "out"));
|
||||
return "[in]" if (has_property($e, "in"));
|
||||
return "[out]" if (has_property($e, "out"));
|
||||
return "[in,out]";
|
||||
}
|
||||
|
||||
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) {
|
||||
return "[" . substr($ret, 0, -1) . "]";
|
||||
}
|
||||
}
|
||||
|
||||
sub ParseCopyArgument($$$$$)
|
||||
{
|
||||
my ($self, $fn, $e, $r, $i) = @_;
|
||||
my $l = $e->{LEVELS}[0];
|
||||
|
||||
if ($l->{TYPE} eq "ARRAY" and $l->{IS_FIXED} == 1) {
|
||||
$self->pidl("memcpy(${r}$e->{NAME}, ${i}$e->{NAME}, sizeof(${r}$e->{NAME}));");
|
||||
} else {
|
||||
$self->pidl("${r}$e->{NAME} = ${i}$e->{NAME};");
|
||||
}
|
||||
}
|
||||
|
||||
sub ParseInvalidResponse($$)
|
||||
{
|
||||
my ($self, $type) = @_;
|
||||
|
||||
if ($type eq "sync") {
|
||||
$self->pidl("return NT_STATUS_INVALID_NETWORK_RESPONSE;");
|
||||
} elsif ($type eq "async") {
|
||||
$self->pidl("tevent_req_nterror(req, NT_STATUS_INVALID_NETWORK_RESPONSE);");
|
||||
$self->pidl("return;");
|
||||
} else {
|
||||
die("ParseInvalidResponse($type)");
|
||||
}
|
||||
}
|
||||
|
||||
sub ParseOutputArgument($$$$$$)
|
||||
{
|
||||
my ($self, $fn, $e, $r, $o, $invalid_response_type) = @_;
|
||||
my $level = 0;
|
||||
|
||||
if ($e->{LEVELS}[0]->{TYPE} ne "POINTER" and $e->{LEVELS}[0]->{TYPE} ne "ARRAY") {
|
||||
fatal($e->{ORIGINAL}, "[out] argument is not a pointer or array");
|
||||
return;
|
||||
}
|
||||
|
||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
||||
$level = 1;
|
||||
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
||||
$self->pidl("if ($o$e->{NAME} && ${r}out.$e->{NAME}) {");
|
||||
$self->indent;
|
||||
}
|
||||
}
|
||||
|
||||
if ($e->{LEVELS}[$level]->{TYPE} eq "ARRAY") {
|
||||
# This is a call to GenerateFunctionInEnv intentionally.
|
||||
# Since the data is being copied into a user-provided data
|
||||
# structure, the user should be able to know the size beforehand
|
||||
# to allocate a structure of the right size.
|
||||
my $in_env = GenerateFunctionInEnv($fn, $r);
|
||||
my $out_env = GenerateFunctionOutEnv($fn, $r);
|
||||
my $l = $e->{LEVELS}[$level];
|
||||
|
||||
my $in_var = undef;
|
||||
if (grep(/in/, @{$e->{DIRECTION}})) {
|
||||
$in_var = ParseExpr($e->{NAME}, $in_env, $e->{ORIGINAL});
|
||||
}
|
||||
my $out_var = ParseExpr($e->{NAME}, $out_env, $e->{ORIGINAL});
|
||||
|
||||
my $in_size_is = undef;
|
||||
my $out_size_is = undef;
|
||||
my $out_length_is = undef;
|
||||
|
||||
my $avail_len = undef;
|
||||
my $needed_len = undef;
|
||||
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
my $copy_len_var = "_copy_len_$e->{NAME}";
|
||||
$self->pidl("size_t $copy_len_var;");
|
||||
|
||||
if (not defined($l->{SIZE_IS})) {
|
||||
if (not $l->{IS_ZERO_TERMINATED}) {
|
||||
fatal($e->{ORIGINAL}, "no size known for [out] array `$e->{NAME}'");
|
||||
}
|
||||
if (has_property($e, "charset")) {
|
||||
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
||||
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
||||
} else {
|
||||
$avail_len = "ndr_string_length($in_var, sizeof(*$in_var))";
|
||||
$needed_len = "ndr_string_length($out_var, sizeof(*$out_var))";
|
||||
}
|
||||
$in_size_is = "";
|
||||
$out_size_is = "";
|
||||
$out_length_is = "";
|
||||
} else {
|
||||
$in_size_is = ParseExpr($l->{SIZE_IS}, $in_env, $e->{ORIGINAL});
|
||||
$out_size_is = ParseExpr($l->{SIZE_IS}, $out_env, $e->{ORIGINAL});
|
||||
$out_length_is = $out_size_is;
|
||||
if (defined($l->{LENGTH_IS})) {
|
||||
$out_length_is = ParseExpr($l->{LENGTH_IS}, $out_env, $e->{ORIGINAL});
|
||||
}
|
||||
if (has_property($e, "charset")) {
|
||||
if (defined($in_var)) {
|
||||
$avail_len = "ndr_charset_length($in_var, CH_UNIX)";
|
||||
} else {
|
||||
$avail_len = $out_length_is;
|
||||
}
|
||||
$needed_len = "ndr_charset_length($out_var, CH_UNIX)";
|
||||
}
|
||||
}
|
||||
|
||||
if ($out_size_is ne $in_size_is) {
|
||||
$self->pidl("if (($out_size_is) > ($in_size_is)) {");
|
||||
$self->indent;
|
||||
$self->ParseInvalidResponse($invalid_response_type);
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
}
|
||||
if ($out_length_is ne $out_size_is) {
|
||||
$self->pidl("if (($out_length_is) > ($out_size_is)) {");
|
||||
$self->indent;
|
||||
$self->ParseInvalidResponse($invalid_response_type);
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
}
|
||||
if (defined($needed_len)) {
|
||||
$self->pidl("$copy_len_var = $needed_len;");
|
||||
$self->pidl("if ($copy_len_var > $avail_len) {");
|
||||
$self->indent;
|
||||
$self->ParseInvalidResponse($invalid_response_type);
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
} else {
|
||||
$self->pidl("$copy_len_var = $out_length_is;");
|
||||
}
|
||||
|
||||
if (has_property($e, "charset")) {
|
||||
$self->pidl("memcpy(discard_const_p(uint8_t *, $o$e->{NAME}), $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));");
|
||||
} else {
|
||||
$self->pidl("memcpy($o$e->{NAME}, $out_var, $copy_len_var * sizeof(*$o$e->{NAME}));");
|
||||
}
|
||||
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
} else {
|
||||
$self->pidl("*$o$e->{NAME} = *${r}out.$e->{NAME};");
|
||||
}
|
||||
|
||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
||||
if ($e->{LEVELS}[0]->{POINTER_TYPE} ne "ref") {
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub ParseFunction_State($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
|
||||
my $state_str = "struct dcerpc_$name\_state";
|
||||
my $done_fn = "dcerpc_$name\_done";
|
||||
|
||||
$self->pidl("$state_str {");
|
||||
$self->indent;
|
||||
$self->pidl("struct $name orig;");
|
||||
$self->pidl("struct $name tmp;");
|
||||
$self->pidl("TALLOC_CTX *out_mem_ctx;");
|
||||
$self->deindent;
|
||||
$self->pidl("};");
|
||||
$self->pidl("");
|
||||
$self->pidl("static void $done_fn(struct tevent_req *subreq);");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_Send($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
|
||||
my $fn_args = "";
|
||||
my $state_str = "struct dcerpc_$name\_state";
|
||||
my $done_fn = "dcerpc_$name\_done";
|
||||
my $out_mem_ctx = "dcerpc_$name\_out_memory";
|
||||
my $fn_str = "struct tevent_req *dcerpc_$name\_send";
|
||||
my $pad = genpad($fn_str);
|
||||
|
||||
$fn_args .= "TALLOC_CTX *mem_ctx";
|
||||
$fn_args .= ",\n" . $pad . "struct tevent_context *ev";
|
||||
$fn_args .= ",\n" . $pad . "struct dcerpc_binding_handle *h";
|
||||
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
my $dir = ElementDirection($_);
|
||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
||||
}
|
||||
|
||||
$self->fn_declare("$fn_str($fn_args)");
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
$self->pidl("struct tevent_req *req;");
|
||||
$self->pidl("$state_str *state;");
|
||||
$self->pidl("struct tevent_req *subreq;");
|
||||
$self->pidl("");
|
||||
$self->pidl("req = tevent_req_create(mem_ctx, &state,");
|
||||
$self->pidl("\t\t\t$state_str);");
|
||||
$self->pidl("if (req == NULL) {");
|
||||
$self->indent;
|
||||
$self->pidl("return NULL;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("state->out_mem_ctx = NULL;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("/* In parameters */");
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
||||
|
||||
$self->ParseCopyArgument($fn, $e, "state->orig.in.", "_");
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
my $out_params = 0;
|
||||
$self->pidl("/* Out parameters */");
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next unless grep(/out/, @{$e->{DIRECTION}});
|
||||
|
||||
$self->ParseCopyArgument($fn, $e, "state->orig.out.", "_");
|
||||
|
||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||
|
||||
$out_params++;
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
$self->pidl("/* Result */");
|
||||
$self->pidl("ZERO_STRUCT(state->orig.out.result);");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
if ($out_params > 0) {
|
||||
$self->pidl("state->out_mem_ctx = talloc_named_const(state, 0,");
|
||||
$self->pidl("\t\t \"$out_mem_ctx\");");
|
||||
$self->pidl("if (tevent_req_nomem(state->out_mem_ctx, req)) {");
|
||||
$self->indent;
|
||||
$self->pidl("return tevent_req_post(req, ev);");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
$self->pidl("/* make a temporary copy, that we pass to the dispatch function */");
|
||||
$self->pidl("state->tmp = state->orig;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("subreq = dcerpc_$name\_r_send(state, ev, h, &state->tmp);");
|
||||
$self->pidl("if (tevent_req_nomem(subreq, req)) {");
|
||||
$self->indent;
|
||||
$self->pidl("return tevent_req_post(req, ev);");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("tevent_req_set_callback(subreq, $done_fn, req);");
|
||||
$self->pidl("return req;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_Done($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
|
||||
my $state_str = "struct dcerpc_$name\_state";
|
||||
my $done_fn = "dcerpc_$name\_done";
|
||||
|
||||
$self->pidl("static void $done_fn(struct tevent_req *subreq)");
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
$self->pidl("struct tevent_req *req = tevent_req_callback_data(");
|
||||
$self->pidl("\tsubreq, struct tevent_req);");
|
||||
$self->pidl("$state_str *state = tevent_req_data(");
|
||||
$self->pidl("\treq, $state_str);");
|
||||
$self->pidl("NTSTATUS status;");
|
||||
$self->pidl("TALLOC_CTX *mem_ctx;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("if (state->out_mem_ctx) {");
|
||||
$self->indent;
|
||||
$self->pidl("mem_ctx = state->out_mem_ctx;");
|
||||
$self->deindent;
|
||||
$self->pidl("} else {");
|
||||
$self->indent;
|
||||
$self->pidl("mem_ctx = state;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("status = dcerpc_$name\_r_recv(subreq, mem_ctx);");
|
||||
$self->pidl("TALLOC_FREE(subreq);");
|
||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||
$self->indent;
|
||||
$self->pidl("tevent_req_nterror(req, status);");
|
||||
$self->pidl("return;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("/* Copy out parameters */");
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||
|
||||
$self->ParseOutputArgument($fn, $e,
|
||||
"state->tmp.",
|
||||
"state->orig.out.",
|
||||
"async");
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
$self->pidl("/* Copy result */");
|
||||
$self->pidl("state->orig.out.result = state->tmp.out.result;");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
$self->pidl("/* Reset temporary structure */");
|
||||
$self->pidl("ZERO_STRUCT(state->tmp);");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("tevent_req_done(req);");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_Recv($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
|
||||
my $fn_args = "";
|
||||
my $state_str = "struct dcerpc_$name\_state";
|
||||
my $fn_str = "NTSTATUS dcerpc_$name\_recv";
|
||||
my $pad = genpad($fn_str);
|
||||
|
||||
$fn_args .= "struct tevent_req *req,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
||||
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
||||
}
|
||||
|
||||
$self->fn_declare("$fn_str($fn_args)");
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
$self->pidl("$state_str *state = tevent_req_data(");
|
||||
$self->pidl("\treq, $state_str);");
|
||||
$self->pidl("NTSTATUS status;");
|
||||
$self->pidl("");
|
||||
$self->pidl("if (tevent_req_is_nterror(req, &status)) {");
|
||||
$self->indent;
|
||||
$self->pidl("tevent_req_received(req);");
|
||||
$self->pidl("return status;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("/* Steal possible out parameters to the callers context */");
|
||||
$self->pidl("talloc_steal(mem_ctx, state->out_mem_ctx);");
|
||||
$self->pidl("");
|
||||
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
$self->pidl("/* Return result */");
|
||||
$self->pidl("*result = state->orig.out.result;");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
$self->pidl("tevent_req_received(req);");
|
||||
$self->pidl("return NT_STATUS_OK;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParseFunction_Sync($$$$)
|
||||
{
|
||||
my ($self, $if, $fn, $name) = @_;
|
||||
|
||||
if ($self->ParseFunctionHasPipes($fn)) {
|
||||
$self->pidl_both("/*");
|
||||
$self->pidl_both(" * The following function is skipped because");
|
||||
$self->pidl_both(" * it uses pipes:");
|
||||
$self->pidl_both(" *");
|
||||
$self->pidl_both(" * dcerpc_$name()");
|
||||
$self->pidl_both(" */");
|
||||
$self->pidl_both("");
|
||||
return;
|
||||
}
|
||||
|
||||
my $uname = uc $name;
|
||||
my $fn_args = "";
|
||||
my $fn_str = "NTSTATUS dcerpc_$name";
|
||||
my $pad = genpad($fn_str);
|
||||
|
||||
$fn_args .= "struct dcerpc_binding_handle *h,\n" . $pad . "TALLOC_CTX *mem_ctx";
|
||||
|
||||
foreach (@{$fn->{ELEMENTS}}) {
|
||||
my $dir = ElementDirection($_);
|
||||
my $prop = HeaderProperties($_->{PROPERTIES}, ["in", "out"]);
|
||||
$fn_args .= ",\n" . $pad . DeclLong($_, "_") . " /* $dir $prop */";
|
||||
}
|
||||
|
||||
if (defined($fn->{RETURN_TYPE})) {
|
||||
$fn_args .= ",\n" . $pad . mapTypeName($fn->{RETURN_TYPE}). " *result";
|
||||
}
|
||||
|
||||
$self->fn_declare("$fn_str($fn_args)");
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
$self->pidl("struct $name r;");
|
||||
$self->pidl("NTSTATUS status;");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("/* In parameters */");
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next unless (grep(/in/, @{$e->{DIRECTION}}));
|
||||
|
||||
$self->ParseCopyArgument($fn, $e, "r.in.", "_");
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("status = dcerpc_$name\_r(h, mem_ctx, &r);");
|
||||
$self->pidl("if (!NT_STATUS_IS_OK(status)) {");
|
||||
$self->indent;
|
||||
$self->pidl("return status;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("/* Return variables */");
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next if ContainsPipe($e, $e->{LEVELS}[0]);
|
||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||
|
||||
$self->ParseOutputArgument($fn, $e, "r.", "_", "sync");
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("/* Return result */");
|
||||
if ($fn->{RETURN_TYPE}) {
|
||||
$self->pidl("*result = r.out.result;");
|
||||
}
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl("return NT_STATUS_OK;");
|
||||
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseFunction($$$)
|
||||
{
|
||||
my ($self, $if, $fn) = @_;
|
||||
|
||||
if ($self->ParseFunctionHasPipes($fn)) {
|
||||
$self->pidl_both("/*");
|
||||
$self->pidl_both(" * The following function is skipped because");
|
||||
$self->pidl_both(" * it uses pipes:");
|
||||
$self->pidl_both(" *");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_send()");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r_recv()");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_r()");
|
||||
$self->pidl_both(" *");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
||||
$self->pidl_both(" */");
|
||||
$self->pidl_both("");
|
||||
warning($fn->{ORIGINAL}, "$fn->{NAME}: dcerpc client does not support pipe yet");
|
||||
return;
|
||||
}
|
||||
|
||||
$self->ParseFunction_r_State($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_r_Send($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_r_Done($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_r_Recv($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_r_Sync($if, $fn, $fn->{NAME});
|
||||
|
||||
foreach my $e (@{$fn->{ELEMENTS}}) {
|
||||
next unless (grep(/out/, @{$e->{DIRECTION}}));
|
||||
|
||||
my $reason = "is not a pointer or array";
|
||||
|
||||
# TODO: make this fatal at NDR level
|
||||
if ($e->{LEVELS}[0]->{TYPE} eq "POINTER") {
|
||||
if ($e->{LEVELS}[1]->{TYPE} eq "DATA" and
|
||||
$e->{LEVELS}[1]->{DATA_TYPE} eq "string") {
|
||||
$reason = "is a pointer to type 'string'";
|
||||
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
||||
$e->{LEVELS}[1]->{IS_ZERO_TERMINATED}) {
|
||||
next;
|
||||
} elsif ($e->{LEVELS}[1]->{TYPE} eq "ARRAY" and
|
||||
not defined($e->{LEVELS}[1]->{SIZE_IS})) {
|
||||
$reason = "is a pointer to an unsized array";
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
}
|
||||
if ($e->{LEVELS}[0]->{TYPE} eq "ARRAY") {
|
||||
if (not defined($e->{LEVELS}[0]->{SIZE_IS})) {
|
||||
$reason = "is an unsized array";
|
||||
} else {
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
$self->pidl_both("/*");
|
||||
$self->pidl_both(" * The following functions are skipped because");
|
||||
$self->pidl_both(" * an [out] argument $e->{NAME} $reason:");
|
||||
$self->pidl_both(" *");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_send()");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}_recv()");
|
||||
$self->pidl_both(" * dcerpc_$fn->{NAME}()");
|
||||
$self->pidl_both(" */");
|
||||
$self->pidl_both("");
|
||||
|
||||
error($e->{ORIGINAL}, "$fn->{NAME}: [out] argument '$e->{NAME}' $reason, skip client functions");
|
||||
return;
|
||||
}
|
||||
|
||||
$self->ParseFunction_State($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_Send($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_Done($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_Recv($if, $fn, $fn->{NAME});
|
||||
$self->ParseFunction_Sync($if, $fn, $fn->{NAME});
|
||||
|
||||
$self->pidl_hdr("");
|
||||
}
|
||||
|
||||
my %done;
|
||||
|
||||
#####################################################################
|
||||
# parse the interface definitions
|
||||
sub ParseInterface($$)
|
||||
{
|
||||
my ($self, $if) = @_;
|
||||
my $ifu = uc($if->{NAME});
|
||||
|
||||
$self->pidl_hdr("#ifndef _HEADER_RPC_$if->{NAME}");
|
||||
$self->pidl_hdr("#define _HEADER_RPC_$if->{NAME}");
|
||||
$self->pidl_hdr("");
|
||||
|
||||
if (defined $if->{PROPERTIES}->{uuid}) {
|
||||
$self->pidl_hdr("extern const struct ndr_interface_table ndr_table_$if->{NAME};");
|
||||
$self->pidl_hdr("");
|
||||
}
|
||||
|
||||
$self->pidl("/* $if->{NAME} - client functions generated by pidl */");
|
||||
$self->pidl("");
|
||||
|
||||
foreach my $fn (@{$if->{FUNCTIONS}}) {
|
||||
next if defined($done{$fn->{NAME}});
|
||||
next if has_property($fn, "noopnum");
|
||||
next if has_property($fn, "todo");
|
||||
$self->ParseFunction($if, $fn);
|
||||
$done{$fn->{NAME}} = 1;
|
||||
}
|
||||
|
||||
$self->pidl_hdr("#endif /* _HEADER_RPC_$if->{NAME} */");
|
||||
}
|
||||
|
||||
sub Parse($$$$$$)
|
||||
{
|
||||
my($self,$ndr,$header,$ndr_header,$client_header) = @_;
|
||||
|
||||
$self->pidl("/* client functions auto-generated by pidl */");
|
||||
$self->pidl("");
|
||||
if (is_intree()) {
|
||||
$self->pidl("#include \"includes.h\"");
|
||||
} else {
|
||||
$self->pidl("#ifndef _GNU_SOURCE");
|
||||
$self->pidl("#define _GNU_SOURCE");
|
||||
$self->pidl("#endif");
|
||||
$self->pidl("#include <stdio.h>");
|
||||
$self->pidl("#include <stdbool.h>");
|
||||
$self->pidl("#include <stdlib.h>");
|
||||
$self->pidl("#include <stdint.h>");
|
||||
$self->pidl("#include <stdarg.h>");
|
||||
$self->pidl("#include <string.h>");
|
||||
$self->pidl("#include <core/ntstatus.h>");
|
||||
}
|
||||
$self->pidl("#include <tevent.h>");
|
||||
$self->pidl(choose_header("lib/util/tevent_ntstatus.h", "util/tevent_ntstatus.h")."");
|
||||
$self->pidl("#include \"$ndr_header\"");
|
||||
$self->pidl("#include \"$client_header\"");
|
||||
$self->pidl("");
|
||||
|
||||
$self->pidl_hdr(choose_header("librpc/rpc/dcerpc.h", "dcerpc.h")."");
|
||||
$self->pidl_hdr("#include \"$header\"");
|
||||
|
||||
foreach my $x (@{$ndr}) {
|
||||
($x->{TYPE} eq "INTERFACE") && $self->ParseInterface($x);
|
||||
}
|
||||
|
||||
return ($self->{res},$self->{res_hdr});
|
||||
}
|
||||
|
||||
1;
|
3081
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
Normal file
3081
pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
Normal file
File diff suppressed because it is too large
Load diff
334
pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
Normal file
334
pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
Normal file
|
@ -0,0 +1,334 @@
|
|||
###################################################
|
||||
# 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 = dcesrv_$fn->{NAME}(dce_call, mem_ctx, r2);\n";
|
||||
} else {
|
||||
pidl "\t\tdcesrv_$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->{UUID});
|
||||
my $if_version = $interface->{VERSION};
|
||||
|
||||
pidl "
|
||||
static NTSTATUS $name\__op_bind(struct dcesrv_call_state *dce_call, const struct dcesrv_interface *iface, uint32_t if_version)
|
||||
{
|
||||
#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)
|
||||
{
|
||||
enum ndr_err_code ndr_err;
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
dce_call->fault_code = 0;
|
||||
|
||||
if (opnum >= ndr_table_$name.num_calls) {
|
||||
dce_call->fault_code = DCERPC_FAULT_OP_RNG_ERROR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
*r = talloc_named(mem_ctx,
|
||||
ndr_table_$name.calls[opnum].struct_size,
|
||||
\"struct %s\",
|
||||
ndr_table_$name.calls[opnum].name);
|
||||
NT_STATUS_HAVE_NO_MEMORY(*r);
|
||||
|
||||
/* unravel the NDR for the packet */
|
||||
ndr_err = ndr_table_$name.calls[opnum].ndr_pull(pull, NDR_IN, *r);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
dcerpc_log_packet(dce_call->conn->packet_log_dir,
|
||||
&ndr_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(dce_call->conn->packet_log_dir,
|
||||
&ndr_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(dce_call->conn->packet_log_dir,
|
||||
&ndr_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)
|
||||
{
|
||||
enum ndr_err_code ndr_err;
|
||||
uint16_t opnum = dce_call->pkt.u.request.opnum;
|
||||
|
||||
ndr_err = ndr_table_$name.calls[opnum].ndr_push(push, NDR_OUT, r);
|
||||
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
|
||||
dce_call->fault_code = DCERPC_FAULT_NDR;
|
||||
return NT_STATUS_NET_WRITE_FAULT;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
const struct dcesrv_interface dcesrv\_$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<ndr_table_$name.endpoints->count;i++) {
|
||||
NTSTATUS ret;
|
||||
const char *name = ndr_table_$name.endpoints->names[i];
|
||||
|
||||
ret = dcesrv_interface_register(dce_ctx, name, &dcesrv_$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 (dcesrv_$name\_interface.syntax_id.if_version == if_version &&
|
||||
GUID_equal(\&dcesrv\_$name\_interface.syntax_id.uuid, uuid)) {
|
||||
memcpy(iface,&dcesrv\_$name\_interface, sizeof(*iface));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool $name\__op_interface_by_name(struct dcesrv_interface *iface, const char *name)
|
||||
{
|
||||
if (strcmp(dcesrv_$name\_interface.name, name)==0) {
|
||||
memcpy(iface, &dcesrv_$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;
|
||||
|
||||
$res .= "NTSTATUS dcerpc_server_$interface->{NAME}\_init(void);\n";
|
||||
$res .= "\n";
|
||||
|
||||
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;
|
1442
pidl/lib/Parse/Pidl/Samba4/Python.pm
Normal file
1442
pidl/lib/Parse/Pidl/Samba4/Python.pm
Normal file
File diff suppressed because it is too large
Load diff
283
pidl/lib/Parse/Pidl/Samba4/TDR.pm
Normal file
283
pidl/lib/Parse/Pidl/Samba4/TDR.pm
Normal file
|
@ -0,0 +1,283 @@
|
|||
###################################################
|
||||
# Trivial Parser Generator
|
||||
# Copyright jelmer@samba.org 2005-2007
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::TDR;
|
||||
use Parse::Pidl qw(fatal);
|
||||
use Parse::Pidl::Util qw(has_property ParseExpr is_constant);
|
||||
use Parse::Pidl::Samba4 qw(is_intree choose_header);
|
||||
use Parse::Pidl::Typelist qw(mapTypeName);
|
||||
|
||||
use Exporter;
|
||||
@ISA = qw(Exporter);
|
||||
@EXPORT_OK = qw(ParserType $ret $ret_hdr);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
sub new($) {
|
||||
my ($class) = shift;
|
||||
my $self = { ret => "", ret_hdr => "", tabs => "" };
|
||||
bless($self, $class);
|
||||
}
|
||||
|
||||
sub indent($) { my $self = shift; $self->{tabs}.="\t"; }
|
||||
sub deindent($) { my $self = shift; $self->{tabs} = substr($self->{tabs}, 1); }
|
||||
sub pidl($$) { my $self = shift; $self->{ret} .= $self->{tabs}.(shift)."\n"; }
|
||||
sub pidl_hdr($$) { my $self = shift; $self->{ret_hdr} .= (shift)."\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 ($self, $p, $d) = @_;
|
||||
if ($p) {
|
||||
$self->pidl($d); $self->pidl_hdr("$d;");
|
||||
} else {
|
||||
$self->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 ($self, $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")) {
|
||||
$self->pidl("{");
|
||||
$self->indent;
|
||||
$self->pidl("uint32_t saved_flags = tdr->flags;");
|
||||
$self->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, $e);
|
||||
if ($len eq "*") { $len = "-1"; }
|
||||
$name = ", mem_ctx" if ($t eq "pull");
|
||||
$self->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, $e);
|
||||
}
|
||||
|
||||
if (defined($e->{ARRAY_LEN}) and scalar(@{$e->{ARRAY_LEN}}) > 0) {
|
||||
my $len = ParseExpr($e->{ARRAY_LEN}[0], $env, $e);
|
||||
|
||||
if ($t eq "pull" and not is_constant($len)) {
|
||||
$self->pidl("TDR_ALLOC(mem_ctx, v->$e->{NAME}, $len);");
|
||||
$mem_ctx = "v->$e->{NAME}";
|
||||
}
|
||||
|
||||
$self->pidl("for (i = 0; i < $len; i++) {");
|
||||
$self->indent;
|
||||
$array = "[i]";
|
||||
}
|
||||
|
||||
if ($t eq "pull") {
|
||||
$name = ", $mem_ctx";
|
||||
}
|
||||
|
||||
if (has_property($e, "value") && $t eq "push") {
|
||||
$self->pidl("v->$e->{NAME} = ".ParseExpr($e->{PROPERTIES}->{value}, $env, $e).";");
|
||||
}
|
||||
|
||||
$self->pidl("TDR_CHECK(tdr_$t\_$e->{TYPE}(tdr$name$switch, &v->$e->{NAME}$array));");
|
||||
|
||||
if ($array) { $self->deindent; $self->pidl("}"); }
|
||||
|
||||
if (has_property($e, "flag")) {
|
||||
$self->pidl("tdr->flags = saved_flags;");
|
||||
$self->deindent;
|
||||
$self->pidl("}");
|
||||
}
|
||||
}
|
||||
|
||||
sub ParserStruct($$$$$)
|
||||
{
|
||||
my ($self, $e,$t,$p) = @_;
|
||||
|
||||
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", struct $e->{NAME} *v)");
|
||||
$self->pidl("{"); $self->indent;
|
||||
$self->pidl("int i;") if (ContainsArray($e));
|
||||
|
||||
if ($t eq "print") {
|
||||
$self->pidl("tdr->print(tdr, \"\%-25s: struct $e->{NAME}\", name);");
|
||||
$self->pidl("tdr->level++;");
|
||||
}
|
||||
|
||||
my %env = map { $_->{NAME} => "v->$_->{NAME}" } @{$e->{ELEMENTS}};
|
||||
$env{"this"} = "v";
|
||||
$self->ParserElement($_, $t, \%env) foreach (@{$e->{ELEMENTS}});
|
||||
|
||||
if ($t eq "print") {
|
||||
$self->pidl("tdr->level--;");
|
||||
}
|
||||
|
||||
$self->pidl("return NT_STATUS_OK;");
|
||||
|
||||
$self->deindent; $self->pidl("}");
|
||||
}
|
||||
|
||||
sub ParserUnion($$$$)
|
||||
{
|
||||
my ($self, $e,$t,$p) = @_;
|
||||
|
||||
$self->fn_declare($p,"NTSTATUS tdr_$t\_$e->{NAME}(struct tdr_$t *tdr".typearg($t).", int level, union $e->{NAME} *v)");
|
||||
$self->pidl("{"); $self->indent;
|
||||
$self->pidl("int i;") if (ContainsArray($e));
|
||||
|
||||
if ($t eq "print") {
|
||||
$self->pidl("tdr->print(tdr, \"\%-25s: union $e->{NAME}\", name);");
|
||||
$self->pidl("tdr->level++;");
|
||||
}
|
||||
|
||||
$self->pidl("switch (level) {"); $self->indent;
|
||||
foreach (@{$e->{ELEMENTS}}) {
|
||||
if (has_property($_, "case")) {
|
||||
$self->pidl("case " . $_->{PROPERTIES}->{case} . ":");
|
||||
} elsif (has_property($_, "default")) {
|
||||
$self->pidl("default:");
|
||||
}
|
||||
$self->indent; $self->ParserElement($_, $t, {}); $self->deindent;
|
||||
$self->pidl("break;");
|
||||
}
|
||||
$self->deindent; $self->pidl("}");
|
||||
|
||||
if ($t eq "print") {
|
||||
$self->pidl("tdr->level--;");
|
||||
}
|
||||
|
||||
$self->pidl("return NT_STATUS_OK;\n");
|
||||
$self->deindent; $self->pidl("}");
|
||||
}
|
||||
|
||||
sub ParserBitmap($$$$)
|
||||
{
|
||||
my ($self,$e,$t,$p) = @_;
|
||||
return if ($p);
|
||||
$self->pidl("#define tdr_$t\_$e->{NAME} tdr_$t\_" . Parse::Pidl::Typelist::bitmap_type_fn($e));
|
||||
}
|
||||
|
||||
sub ParserEnum($$$$)
|
||||
{
|
||||
my ($self,$e,$t,$p) = @_;
|
||||
my $bt = Parse::Pidl::Typelist::enum_type_fn($e);
|
||||
my $mt = mapTypeName($bt);
|
||||
|
||||
$self->fn_declare($p, "NTSTATUS tdr_$t\_$e->{NAME} (struct tdr_$t *tdr".typearg($t).", enum $e->{NAME} *v)");
|
||||
$self->pidl("{");
|
||||
if ($t eq "pull") {
|
||||
$self->pidl("\t$mt r;");
|
||||
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, mem_ctx, \&r));");
|
||||
$self->pidl("\t*v = r;");
|
||||
} elsif ($t eq "push") {
|
||||
$self->pidl("\tTDR_CHECK(tdr_$t\_$bt(tdr, ($mt *)v));");
|
||||
} elsif ($t eq "print") {
|
||||
$self->pidl("\t/* FIXME */");
|
||||
}
|
||||
$self->pidl("\treturn NT_STATUS_OK;");
|
||||
$self->pidl("}");
|
||||
}
|
||||
|
||||
sub ParserTypedef($$$$)
|
||||
{
|
||||
my ($self, $e,$t,$p) = @_;
|
||||
|
||||
$self->ParserType($e->{DATA},$t);
|
||||
}
|
||||
|
||||
sub ParserType($$$)
|
||||
{
|
||||
my ($self, $e,$t) = @_;
|
||||
|
||||
return if (has_property($e, "no$t"));
|
||||
|
||||
my $handlers = {
|
||||
STRUCT => \&ParserStruct, UNION => \&ParserUnion,
|
||||
ENUM => \&ParserEnum, BITMAP => \&ParserBitmap,
|
||||
TYPEDEF => \&ParserTypedef
|
||||
};
|
||||
|
||||
$handlers->{$e->{TYPE}}->($self, $e, $t, has_property($e, "public"))
|
||||
if (defined($handlers->{$e->{TYPE}}));
|
||||
|
||||
$self->pidl("");
|
||||
}
|
||||
|
||||
sub ParserInterface($$)
|
||||
{
|
||||
my ($self,$x) = @_;
|
||||
|
||||
$self->pidl_hdr("#ifndef __TDR_$x->{NAME}_HEADER__");
|
||||
$self->pidl_hdr("#define __TDR_$x->{NAME}_HEADER__");
|
||||
|
||||
foreach (@{$x->{DATA}}) {
|
||||
$self->ParserType($_, "pull");
|
||||
$self->ParserType($_, "push");
|
||||
$self->ParserType($_, "print");
|
||||
}
|
||||
|
||||
$self->pidl_hdr("#endif /* __TDR_$x->{NAME}_HEADER__ */");
|
||||
}
|
||||
|
||||
sub Parser($$$$)
|
||||
{
|
||||
my ($self,$idl,$hdrname,$baseheader) = @_;
|
||||
$self->pidl("/* autogenerated by pidl */");
|
||||
if (is_intree()) {
|
||||
$self->pidl("#include \"includes.h\"");
|
||||
} else {
|
||||
$self->pidl("#include <stdio.h>");
|
||||
$self->pidl("#include <stdbool.h>");
|
||||
$self->pidl("#include <stdlib.h>");
|
||||
$self->pidl("#include <stdint.h>");
|
||||
$self->pidl("#include <stdarg.h>");
|
||||
$self->pidl("#include <string.h>");
|
||||
$self->pidl("#include <core/ntstatus.h>");
|
||||
}
|
||||
$self->pidl("#include \"$hdrname\"");
|
||||
$self->pidl("");
|
||||
$self->pidl_hdr("/* autogenerated by pidl */");
|
||||
$self->pidl_hdr("#include \"$baseheader\"");
|
||||
$self->pidl_hdr(choose_header("lib/tdr/tdr.h", "tdr.h"));
|
||||
$self->pidl_hdr("");
|
||||
|
||||
foreach (@$idl) { $self->ParserInterface($_) if ($_->{TYPE} eq "INTERFACE"); }
|
||||
return ($self->{ret_hdr}, $self->{ret});
|
||||
}
|
||||
|
||||
1;
|
98
pidl/lib/Parse/Pidl/Samba4/Template.pm
Normal file
98
pidl/lib/Parse/Pidl/Samba4/Template.pm
Normal file
|
@ -0,0 +1,98 @@
|
|||
###################################################
|
||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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} dcesrv_$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;
|
Loading…
Add table
Add a link
Reference in a new issue