Refactor build system to use waf. Waf is better at handling dependency paths which I need for IDL support
This commit is contained in:
parent
df7f98bc6f
commit
9fd10dec9c
77 changed files with 312 additions and 86 deletions
160
bin/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
160
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
225
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm
Normal file
327
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/Header.pm
Normal file
537
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/NDR/Client.pm
Normal file
875
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
Normal file
3081
bin/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
Normal file
File diff suppressed because it is too large
Load diff
334
bin/pidl/lib/Parse/Pidl/Samba4/NDR/Server.pm
Normal file
334
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/Python.pm
Normal file
1442
bin/pidl/lib/Parse/Pidl/Samba4/Python.pm
Normal file
File diff suppressed because it is too large
Load diff
283
bin/pidl/lib/Parse/Pidl/Samba4/TDR.pm
Normal file
283
bin/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
bin/pidl/lib/Parse/Pidl/Samba4/Template.pm
Normal file
98
bin/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