mirror of
https://github.com/samba-team/samba.git
synced 2025-01-11 05:18:09 +03:00
Reimport pidl support for COM.
This commit is contained in:
parent
952be0f104
commit
7b88d09d8d
@ -18,8 +18,7 @@
|
||||
object,
|
||||
uuid("00000000-0000-0000-C000-000000000046"),
|
||||
pointer_default(unique),
|
||||
helpstring("Base interface for all COM interfaces"),
|
||||
keepref
|
||||
helpstring("Base interface for all COM interfaces")
|
||||
]
|
||||
interface IUnknown
|
||||
{
|
||||
@ -43,8 +42,7 @@ interface IUnknown
|
||||
[
|
||||
object,
|
||||
uuid("00000001-0000-0000-C000-000000000046"),
|
||||
pointer_default(unique),
|
||||
keepref
|
||||
pointer_default(unique)
|
||||
] interface IClassFactory : IUnknown
|
||||
{
|
||||
[local] WERROR CreateInstance([in,unique] MInterfacePointer *pUnknown,
|
||||
@ -71,8 +69,7 @@ interface IUnknown
|
||||
uuid("00000131-0000-0000-C000-000000000046"),
|
||||
object,
|
||||
pointer_default(unique),
|
||||
helpstring("Remote version of IUnknown"),
|
||||
keepref
|
||||
helpstring("Remote version of IUnknown")
|
||||
]
|
||||
interface IRemUnknown : IUnknown
|
||||
{
|
||||
@ -172,8 +169,7 @@ interface IRemUnknown : IUnknown
|
||||
[
|
||||
object,
|
||||
pointer_default(unique),
|
||||
uuid("00000143-0000-0000-C000-000000000046"),
|
||||
keepref
|
||||
uuid("00000143-0000-0000-C000-000000000046")
|
||||
]
|
||||
|
||||
interface IRemUnknown2 : IRemUnknown
|
||||
@ -190,8 +186,7 @@ interface IRemUnknown2 : IRemUnknown
|
||||
[
|
||||
object,
|
||||
pointer_default(unique),
|
||||
uuid("00020400-0000-0000-C000-000000000046"),
|
||||
keepref
|
||||
uuid("00020400-0000-0000-C000-000000000046")
|
||||
] interface IDispatch : IUnknown
|
||||
{
|
||||
/*****************/
|
||||
@ -259,8 +254,7 @@ interface IRemUnknown2 : IRemUnknown
|
||||
uuid(DA23F6DB-6F45-466C-9EED-0B65286F2D78),
|
||||
helpstring("ICoffeeMachine Interface"),
|
||||
pointer_default(unique),
|
||||
object,
|
||||
keepref
|
||||
object
|
||||
] interface ICoffeeMachine : IUnknown
|
||||
{
|
||||
WERROR MakeCoffee([in,string,charset(UTF16)] uint16 *flavor);
|
||||
@ -278,8 +272,7 @@ interface IRemUnknown2 : IRemUnknown
|
||||
object,
|
||||
pointer_default(unique),
|
||||
uuid("0000000C-0000-0000-C000-000000000046"),
|
||||
helpstring("Stream"),
|
||||
keepref
|
||||
helpstring("Stream")
|
||||
]
|
||||
interface IStream : IUnknown
|
||||
{
|
||||
|
@ -207,8 +207,6 @@ interface IWbemClassObject : IUnknown
|
||||
WBEM_INFINITE = 0xFFFFFFFF
|
||||
} WBEM_TIMEOUT_TYPE;
|
||||
|
||||
typedef [public,nopull,nopush,noprint,string,charset(UTF16)] uint16 *CIMSTRING;
|
||||
|
||||
typedef [public,v1_enum] enum
|
||||
{
|
||||
CIM_EMPTY = 0,
|
||||
@ -295,7 +293,7 @@ interface IWbemClassObject : IUnknown
|
||||
|
||||
typedef [public] struct {
|
||||
uint32 count;
|
||||
[relative] CIMSTRING item[count];
|
||||
[relative,charset(UTF16)] uint16 *item[count];
|
||||
} arr_CIMSTRING;
|
||||
|
||||
typedef [public] struct {
|
||||
@ -317,9 +315,9 @@ interface IWbemClassObject : IUnknown
|
||||
[case(CIM_REAL32)] uint32 v_real32;
|
||||
[case(CIM_REAL64)] udlong v_real64;
|
||||
[case(CIM_BOOLEAN)] uint16 v_boolean;
|
||||
[case(CIM_STRING),relative] CIMSTRING v_string;
|
||||
[case(CIM_DATETIME),relative] CIMSTRING v_datetime;
|
||||
[case(CIM_REFERENCE),relative] CIMSTRING v_reference;
|
||||
[case(CIM_STRING),relative,charset(UTF16)] uint16 *v_string;
|
||||
[case(CIM_DATETIME),relative,charset(UTF16)] uint16 *v_datetime;
|
||||
[case(CIM_REFERENCE),relative,charset(UTF16)] uint16 *v_reference;
|
||||
[case(CIM_OBJECT),subcontext(4),relative] WbemClassObject *v_object;
|
||||
|
||||
[case(CIM_ARR_SINT8),relative] arr_int8 *a_sint8;
|
||||
@ -368,7 +366,7 @@ interface IWbemClassObject : IUnknown
|
||||
|
||||
typedef [public,nopush,nopull] struct
|
||||
{
|
||||
[relative] CIMSTRING name;
|
||||
[relative,charset(UTF16)] uint16 *name;
|
||||
WBEM_FLAVOR_TYPE flavors;
|
||||
CIMTYPE_ENUMERATION cimtype;
|
||||
[switch_is(cimtype)] CIMVAR value;
|
||||
@ -391,14 +389,14 @@ interface IWbemClassObject : IUnknown
|
||||
|
||||
typedef [public] struct
|
||||
{
|
||||
[relative] CIMSTRING name;
|
||||
[relative,charset(UTF16)] uint16 *name;
|
||||
[relative] WbemPropertyDesc *desc;
|
||||
} WbemProperty;
|
||||
|
||||
typedef [public,nopull,nopush] struct
|
||||
{
|
||||
uint32 count;
|
||||
[ref] CIMSTRING item[count];
|
||||
[ref,charset(UTF16)] uint16 *item[count];
|
||||
} CIMSTRINGS;
|
||||
|
||||
typedef [public,bitmap8bit] bitmap {
|
||||
@ -409,7 +407,7 @@ interface IWbemClassObject : IUnknown
|
||||
typedef [public,nopush,nopull,noprint,flag(NDR_NOALIGN)] struct
|
||||
{
|
||||
uint8 u_0;
|
||||
[relative, null_is_ffffffff] CIMSTRING __CLASS;
|
||||
[relative, null_is_ffffffff,charset(UTF16)] uint16 *__CLASS;
|
||||
uint32 data_size;
|
||||
CIMSTRINGS __DERIVATION;
|
||||
WbemQualifiers qualifiers;
|
||||
@ -421,7 +419,7 @@ interface IWbemClassObject : IUnknown
|
||||
|
||||
typedef [public] struct
|
||||
{
|
||||
[relative,null_is_ffffffff] CIMSTRING name;
|
||||
[relative,null_is_ffffffff,charset(UTF16)] uint16 *name;
|
||||
uint32 u0;
|
||||
uint32 u1;
|
||||
[relative] WbemQualifiers *qualifiers;
|
||||
@ -439,7 +437,7 @@ interface IWbemClassObject : IUnknown
|
||||
typedef [public,flag(NDR_NOALIGN),nopush,nopull,noprint] struct
|
||||
{
|
||||
uint8 u1_0;
|
||||
[relative] CIMSTRING __CLASS;
|
||||
[relative,charset(UTF16)] uint16 *__CLASS;
|
||||
uint8 *default_flags;
|
||||
CIMVAR *data;
|
||||
uint32 u2_4;
|
||||
@ -449,8 +447,8 @@ interface IWbemClassObject : IUnknown
|
||||
typedef [public,nopush,nopull,noprint,flag(NDR_NOALIGN)] struct
|
||||
{
|
||||
WCO_FLAGS flags;
|
||||
[ref] CIMSTRING __SERVER;
|
||||
[ref] CIMSTRING __NAMESPACE;
|
||||
[ref,charset(UTF16)] uint16 *__SERVER;
|
||||
[ref,charset(UTF16)] uint16 *__NAMESPACE;
|
||||
WbemClass *sup_class;
|
||||
WbemMethods *sup_methods;
|
||||
WbemClass *obj_class;
|
||||
@ -465,7 +463,7 @@ interface IWbemClassObject : IUnknown
|
||||
// [value(clSize)] uint32 _wsize;
|
||||
// [flag(NDR_NOALIGN)] uint16 asData[clSize];
|
||||
// } BSTR1;
|
||||
typedef [public,nopush,nopull,noprint,string,charset(UTF16)] uint16 *BSTR;
|
||||
//typedef [public,nopush,nopull,noprint,string,charset(UTF16)] uint16 *BSTR;
|
||||
|
||||
WERROR OpenNamespace(
|
||||
// [in] BSTR *strNamespace,
|
||||
|
@ -67,17 +67,24 @@ interface_names:
|
||||
| interface_names 'interface' identifier ';' { push(@{$_[1]}, $_[2]); $_[1] }
|
||||
;
|
||||
|
||||
interface: property_list 'interface' identifier '{' definitions '}' optional_semicolon
|
||||
interface: property_list 'interface' identifier base_interface '{' definitions '}' optional_semicolon
|
||||
{{
|
||||
"TYPE" => "INTERFACE",
|
||||
"PROPERTIES" => $_[1],
|
||||
"NAME" => $_[3],
|
||||
"DATA" => $_[5],
|
||||
"BASE" => $_[4],
|
||||
"DATA" => $_[6],
|
||||
"FILE" => $_[0]->YYData->{FILE},
|
||||
"LINE" => $_[0]->YYData->{LINE},
|
||||
}}
|
||||
;
|
||||
|
||||
base_interface:
|
||||
#empty
|
||||
| ':' identifier { $_[2] }
|
||||
;
|
||||
|
||||
|
||||
cpp_quote: 'cpp_quote' '(' text ')'
|
||||
{{
|
||||
"TYPE" => "CPP_QUOTE",
|
||||
|
File diff suppressed because it is too large
Load Diff
142
source4/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
142
source4/pidl/lib/Parse/Pidl/Samba4/COM/Header.pm
Normal file
@ -0,0 +1,142 @@
|
||||
# COM Header generation
|
||||
# (C) 2005 Jelmer Vernooij <jelmer@samba.org>
|
||||
|
||||
package Parse::Pidl::Samba4::COM::Header;
|
||||
|
||||
use Parse::Pidl::Typelist qw(mapType);
|
||||
use Parse::Pidl::Util qw(has_property is_constant);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
sub GetArgumentProtoList($)
|
||||
{
|
||||
my $f = shift;
|
||||
my $res = "";
|
||||
|
||||
foreach my $a (@{$f->{ELEMENTS}}) {
|
||||
|
||||
$res .= ", " . mapType($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" . mapType($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\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 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";
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub ParseCoClass($)
|
||||
{
|
||||
my $c = shift;
|
||||
my $res = "";
|
||||
$res .= "#define CLSID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{uuid}\n";
|
||||
if (has_property($c, "progid")) {
|
||||
$res .= "#define PROGID_" . uc($c->{NAME}) . " $c->{PROPERTIES}->{progid}\n";
|
||||
}
|
||||
$res .= "\n";
|
||||
return $res;
|
||||
}
|
||||
|
||||
sub Parse($$)
|
||||
{
|
||||
my ($idl,$ndr_header) = @_;
|
||||
my $res = "";
|
||||
|
||||
$res .= "#include \"librpc/gen_ndr/orpc.h\"\n" .
|
||||
"#include \"$ndr_header\"\n\n";
|
||||
|
||||
foreach (@{$idl})
|
||||
{
|
||||
if ($_->{TYPE} eq "INTERFACE" && has_property($_, "object")) {
|
||||
$res.=ParseInterface($_);
|
||||
}
|
||||
|
||||
if ($_->{TYPE} eq "COCLASS") {
|
||||
$res.=ParseCoClass($_);
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
219
source4/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
219
source4/pidl/lib/Parse/Pidl/Samba4/COM/Proxy.pm
Normal file
@ -0,0 +1,219 @@
|
||||
###################################################
|
||||
# DCOM parser for Samba
|
||||
# Basically the glue between COM and DCE/RPC with NDR
|
||||
# Copyright jelmer@samba.org 2003-2005
|
||||
# released under the GNU GPL
|
||||
|
||||
package Parse::Pidl::Samba4::COM::Proxy;
|
||||
|
||||
use Parse::Pidl::Samba4::COM::Header;
|
||||
use Parse::Pidl::Util qw(has_property);
|
||||
|
||||
use vars qw($VERSION);
|
||||
$VERSION = '0.01';
|
||||
|
||||
use strict;
|
||||
|
||||
my($res);
|
||||
|
||||
sub ParseVTable($$)
|
||||
{
|
||||
my $interface = shift;
|
||||
my $name = shift;
|
||||
|
||||
# Generate the vtable
|
||||
$res .="\tstruct $interface->{NAME}_vtable $name = {";
|
||||
|
||||
if (defined($interface->{BASE})) {
|
||||
$res .= "\n\t\t{},";
|
||||
}
|
||||
|
||||
my $data = $interface->{DATA};
|
||||
|
||||
foreach my $d (@{$data}) {
|
||||
if ($d->{TYPE} eq "FUNCTION") {
|
||||
$res .= "\n\t\tdcom_proxy_$interface->{NAME}_$d->{NAME}";
|
||||
$res .= ",";
|
||||
}
|
||||
}
|
||||
|
||||
$res .= "\n\t};\n\n";
|
||||
}
|
||||
|
||||
sub ParseRegFunc($)
|
||||
{
|
||||
my $interface = shift;
|
||||
|
||||
$res .= "static NTSTATUS dcom_proxy_$interface->{NAME}_init(void)
|
||||
{
|
||||
struct GUID base_iid;
|
||||
struct $interface->{NAME}_vtable *proxy_vtable = talloc(talloc_autofree_context(), struct $interface->{NAME}_vtable);
|
||||
";
|
||||
|
||||
if (defined($interface->{BASE})) {
|
||||
$res.= "
|
||||
const void *base_vtable;
|
||||
|
||||
base_iid = dcerpc_table_$interface->{BASE}.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 = dcerpc_table_$interface->{NAME}.uuid;
|
||||
|
||||
return dcom_register_proxy(&proxy_vtable);
|
||||
}\n\n";
|
||||
}
|
||||
|
||||
#####################################################################
|
||||
# parse a function
|
||||
sub ParseFunction($$)
|
||||
{
|
||||
my $interface = shift;
|
||||
my $fn = shift;
|
||||
my $name = $fn->{NAME};
|
||||
my $uname = uc $name;
|
||||
|
||||
$res.="
|
||||
static $fn->{RETURN_TYPE} 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(&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, &dcerpc_table_$interface->{NAME}, DCERPC_$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 = "";
|
||||
|
||||
$res .= "#include \"includes.h\"\n" .
|
||||
"#include \"lib/com/dcom/dcom.h\"\n" .
|
||||
"#include \"$comh_filename\"\n";
|
||||
|
||||
foreach (@{$pidl}) {
|
||||
next if ($_->{TYPE} ne "INTERFACE");
|
||||
next if has_property($_, "local");
|
||||
next unless has_property($_, "object");
|
||||
|
||||
$res .= ParseInterface($_);
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
1;
|
327
source4/pidl/lib/Parse/Pidl/Samba4/COM/Stub.pm
Normal file
327
source4/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)
|
||||
{
|
||||
#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;
|
@ -1025,7 +1025,7 @@ sub ConvertObjectToPythonData($$$$$)
|
||||
return $self->ConvertScalarToPython(Parse::Pidl::Typelist::bitmap_type_fn($actual_ctype), $cvar);
|
||||
} elsif ($actual_ctype->{TYPE} eq "SCALAR") {
|
||||
return $self->ConvertScalarToPython($actual_ctype->{NAME}, $cvar);
|
||||
} elsif ($actual_ctype->{TYPE} eq "STRUCT") {
|
||||
} elsif ($actual_ctype->{TYPE} eq "STRUCT" or $actual_ctype->{TYPE} eq "INTERFACE") {
|
||||
return "py_talloc_import_ex(&$ctype->{NAME}_Type, $mem_ctx, $cvar)";
|
||||
}
|
||||
|
||||
|
@ -245,7 +245,7 @@ sub mapType($$)
|
||||
return mapType($t->{DATA}, $n) if ($t->{TYPE} eq "TYPEDEF");
|
||||
return mapScalarType($n) if ($t->{TYPE} eq "SCALAR");
|
||||
return "enum $n" if ($t->{TYPE} eq "ENUM");
|
||||
return "struct $n" if ($t->{TYPE} eq "STRUCT");
|
||||
return "struct $n" if ($t->{TYPE} eq "STRUCT" or $t->{TYPE} eq "INTERFACE");
|
||||
return "union $n" if ($t->{TYPE} eq "UNION");
|
||||
return mapScalarType(bitmap_type_fn($t)) if ($t->{TYPE} eq "BITMAP");
|
||||
die("Unknown type $t->{TYPE}");
|
||||
@ -273,6 +273,13 @@ sub LoadIdl($)
|
||||
foreach my $x (@{$idl}) {
|
||||
next if $x->{TYPE} ne "INTERFACE";
|
||||
|
||||
# DCOM interfaces can be types as well
|
||||
addType({
|
||||
NAME => $x->{NAME},
|
||||
TYPE => "TYPEDEF",
|
||||
DATA => $x
|
||||
}) if (has_property($x, "object"));
|
||||
|
||||
foreach my $y (@{$x->{DATA}}) {
|
||||
addType($y) if (
|
||||
$y->{TYPE} eq "TYPEDEF"
|
||||
|
Loading…
Reference in New Issue
Block a user