summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/librpc/rpc/dcerpc.h1
-rw-r--r--source4/librpc/rpc/pyrpc.c101
-rw-r--r--source4/librpc/rpc/pyrpc.h16
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba4/Python.pm83
4 files changed, 141 insertions, 60 deletions
diff --git a/source4/librpc/rpc/dcerpc.h b/source4/librpc/rpc/dcerpc.h
index ca6311a4fc..487f9f2eda 100644
--- a/source4/librpc/rpc/dcerpc.h
+++ b/source4/librpc/rpc/dcerpc.h
@@ -370,5 +370,6 @@ NTSTATUS dcerpc_request(struct dcerpc_pipe *p,
DATA_BLOB *stub_data_in,
DATA_BLOB *stub_data_out);
+typedef NTSTATUS (*dcerpc_call_fn) (struct dcerpc_pipe *, TALLOC_CTX *, void *);
#endif /* __DCERPC_H__ */
diff --git a/source4/librpc/rpc/pyrpc.c b/source4/librpc/rpc/pyrpc.c
index 26242e8235..b04ca0be30 100644
--- a/source4/librpc/rpc/pyrpc.c
+++ b/source4/librpc/rpc/pyrpc.c
@@ -24,6 +24,103 @@
#include "librpc/rpc/dcerpc.h"
#include "lib/events/events.h"
+typedef struct dcerpc_FunctionObject {
+ PyObject_HEAD
+ struct PyNdrRpcMethodDef *method_def;
+} dcerpc_FunctionObject;
+
+static PyMemberDef dcerpc_function_members[] = {
+ { discard_const_p(char, "__opnum__"), T_LONG,
+ offsetof(struct dcerpc_FunctionObject, method_def), 0,
+ discard_const_p(char, "opnum") },
+ { NULL }
+};
+
+
+static PyObject * dcerpc_function_ndr_pack_in(PyObject *self, PyObject *args, PyObject *kwargs)
+{
+ /* FIXME */
+ return Py_None;
+}
+
+static PyMethodDef dcerpc_function_methods[] = {
+ { "__ndr_pack_in__", (PyCFunction)dcerpc_function_ndr_pack_in, METH_VARARGS|METH_KEYWORDS, NULL },
+ { NULL, NULL, 0, NULL },
+};
+
+PyTypeObject dcerpc_FunctionType = {
+ PyObject_HEAD_INIT(NULL) 0,
+ .tp_name = "dcerpc.Function",
+ .tp_basicsize = sizeof(dcerpc_FunctionObject),
+ .tp_members = dcerpc_function_members,
+ .tp_methods = dcerpc_function_methods,
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+};
+
+PyObject *py_dcerpc_call_wrapper(PyObject *self, PyObject *args, void *wrapped, PyObject *kwargs)
+{
+ dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self;
+ struct PyNdrRpcMethodDef *md = wrapped;
+ TALLOC_CTX *mem_ctx;
+ NTSTATUS status;
+ void *r;
+ PyObject *result = Py_None;
+
+ if (md->pack_in_data == NULL || md->unpack_out_data == NULL) {
+ PyErr_SetString(PyExc_NotImplementedError, "No marshalling code available yet");
+ return NULL;
+ }
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL)
+ return NULL;
+
+ r = talloc_zero_size(mem_ctx, md->table->calls[md->opnum].struct_size);
+ if (r == NULL)
+ return NULL;
+
+ if (!md->pack_in_data(args, kwargs, r)) {
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ status = md->call(iface->pipe, mem_ctx, r);
+ if (NT_STATUS_IS_ERR(status)) {
+ PyErr_SetDCERPCStatus(iface->pipe, status);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ result = md->unpack_out_data(r);
+
+ talloc_free(mem_ctx);
+ return result;
+}
+
+
+PyObject *PyDescr_NewNdrRpcMethod(PyTypeObject *ifacetype, struct PyNdrRpcMethodDef *md)
+{
+ struct wrapperbase *wb = calloc(sizeof(struct wrapperbase), 1);
+
+ wb->name = md->name;
+ wb->flags = PyWrapperFlag_KEYWORDS;
+ wb->wrapper = py_dcerpc_call_wrapper;
+ wb->doc = md->doc;
+
+ return PyDescr_NewWrapper(ifacetype, wb, md);
+}
+
+bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, struct PyNdrRpcMethodDef *mds)
+{
+ int i;
+ for (i = 0; mds[i].name; i++) {
+ PyDict_SetItemString(ifacetype->tp_dict, mds[i].name,
+ PyDescr_NewNdrRpcMethod(ifacetype, &mds[i]));
+ }
+
+ return true;
+}
+
static bool PyString_AsGUID(PyObject *object, struct GUID *uuid)
{
NTSTATUS status;
@@ -311,7 +408,6 @@ static PyObject *dcerpc_interface_new(PyTypeObject *self, PyObject *args, PyObje
talloc_free(mem_ctx);
return NULL;
}
-
ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
return (PyObject *)ret;
}
@@ -341,6 +437,9 @@ void initbase(void)
if (PyType_Ready(&dcerpc_InterfaceType) < 0)
return;
+ if (PyType_Ready(&dcerpc_FunctionType) < 0)
+ return;
+
m = Py_InitModule3("base", NULL, "DCE/RPC protocol implementation");
if (m == NULL)
return;
diff --git a/source4/librpc/rpc/pyrpc.h b/source4/librpc/rpc/pyrpc.h
index 209d7d3f1f..5ec9c6ed83 100644
--- a/source4/librpc/rpc/pyrpc.h
+++ b/source4/librpc/rpc/pyrpc.h
@@ -52,4 +52,20 @@ PyAPI_DATA(PyTypeObject) dcerpc_InterfaceType;
void PyErr_SetDCERPCStatus(struct dcerpc_pipe *pipe, NTSTATUS status);
+typedef bool (*py_data_pack_fn) (PyObject *args, PyObject *kwargs, void *r);
+typedef PyObject *(*py_data_unpack_fn) (void *r);
+
+struct PyNdrRpcMethodDef {
+ const char *name;
+ const char *doc;
+ dcerpc_call_fn call;
+ py_data_pack_fn pack_in_data;
+ py_data_unpack_fn unpack_out_data;
+ uint32_t opnum;
+ const struct ndr_interface_table *table;
+};
+
+bool PyInterface_AddNdrRpcMethods(PyTypeObject *object, struct PyNdrRpcMethodDef *mds);
+PyObject *PyDescr_NewNdrRpcMethod(PyTypeObject *type, struct PyNdrRpcMethodDef *md);
+
#endif /* _PYRPC_H_ */
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/Python.pm b/source4/pidl/lib/Parse/Pidl/Samba4/Python.pm
index 720d066360..0832401d7d 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba4/Python.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba4/Python.pm
@@ -21,7 +21,8 @@ $VERSION = '0.01';
sub new($) {
my ($class) = @_;
my $self = { res => "", res_hdr => "", tabs => "", constants => {},
- module_methods => [], module_objects => [], module_types => []};
+ module_methods => [], module_objects => [], module_types => [],
+ readycode => [] };
bless($self, $class);
}
@@ -341,41 +342,6 @@ sub find_metadata_args($)
return $metadata_args;
}
-sub PythonFunctionBody($$$$$)
-{
- my ($self, $fn, $iface, $prettyname, $infn, $outfn) = @_;
-
- $self->pidl("dcerpc_InterfaceObject *iface = (dcerpc_InterfaceObject *)self;");
- $self->pidl("NTSTATUS status;");
- $self->pidl("TALLOC_CTX *mem_ctx = talloc_new(NULL);");
- $self->pidl("struct $fn->{NAME} *r = talloc_zero(mem_ctx, struct $fn->{NAME});");
- $self->pidl("PyObject *result = Py_None;");
-
- $self->pidl("if (!$infn(args, kwargs, r)) {");
- $self->indent;
- $self->pidl("talloc_free(mem_ctx);");
- $self->pidl("return NULL;");
- $self->deindent;
- $self->pidl("}");
- $self->pidl("");
-
- $self->pidl("status = dcerpc_$fn->{NAME}(iface->pipe, mem_ctx, r);");
- $self->pidl("if (NT_STATUS_IS_ERR(status)) {");
- $self->indent;
- $self->pidl("PyErr_SetDCERPCStatus(iface->pipe, status);");
- $self->pidl("talloc_free(mem_ctx);");
- $self->pidl("return NULL;");
- $self->deindent;
- $self->pidl("}");
- $self->pidl("");
-
- $self->pidl("result = $outfn(r);");
- $self->pidl("");
- $self->pidl("talloc_free(mem_ctx);");
- $self->pidl("return result;");
-
-}
-
sub PythonFunctionUnpackOut($$$)
{
my ($self, $fn, $fnname) = @_;
@@ -453,6 +419,7 @@ sub PythonFunctionUnpackOut($$$)
$self->pidl("return result;");
$self->deindent;
$self->pidl("}");
+ $self->pidl("");
return ($outfnname, $signature);
}
@@ -535,20 +502,13 @@ sub PythonFunction($$$)
my ($insignature, $outsignature);
my ($infn, $outfn);
- if (not has_property($fn, "todo")) {
- ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname);
- ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname);
- }
-
- $self->pidl("static PyObject *$fnname(PyObject *self, PyObject *args, PyObject *kwargs)");
- $self->pidl("{");
- $self->indent;
if (has_property($fn, "todo")) {
- $self->pidl("PyErr_SetString(PyExc_NotImplementedError, \"No marshalling code available yet for $prettyname\");");
- $self->pidl("return NULL;");
unless ($docstring) { $docstring = "NULL"; }
+ $infn = "NULL";
+ $outfn = "NULL";
} else {
- $self->PythonFunctionBody($fn, $iface, $prettyname, $infn, $outfn);
+ ($infn, $insignature) = $self->PythonFunctionPackIn($fn, $fnname);
+ ($outfn, $outsignature) = $self->PythonFunctionUnpackOut($fn, $fnname);
my $signature = "S.$prettyname($insignature) -> $outsignature";
if ($docstring) {
$docstring = "\"$signature\\n\\n\"$docstring";
@@ -557,11 +517,7 @@ sub PythonFunction($$$)
}
}
- $self->deindent;
- $self->pidl("}");
- $self->pidl("");
-
- return ($fnname, $docstring);
+ return ($infn, $outfn, $docstring);
}
sub handle_werror($$$$)
@@ -689,18 +645,18 @@ sub Interface($$$)
$prettyname =~ s/^$interface->{NAME}_//;
$prettyname =~ s/^$basename\_//;
- my ($fnname, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname);
+ my ($infn, $outfn, $fndocstring) = $self->PythonFunction($d, $interface->{NAME}, $prettyname);
- push (@fns, [$fnname, $prettyname, $fndocstring]);
+ push (@fns, [$infn, $outfn, "dcerpc_$d->{NAME}", $prettyname, $fndocstring, $d->{OPNUM}]);
}
- $self->pidl("static PyMethodDef interface_$interface->{NAME}\_methods[] = {");
+ $self->pidl("static struct PyNdrRpcMethodDef interface_$interface->{NAME}\_methods[] = {");
$self->indent;
foreach my $d (@fns) {
- my ($c_fn, $prettyname, $docstring) = @$d;
- $self->pidl("{ \"$prettyname\", (PyCFunction)$c_fn, METH_VARARGS|METH_KEYWORDS, $docstring },");
+ my ($infn, $outfn, $callfn, $prettyname, $docstring, $opnum) = @$d;
+ $self->pidl("{ \"$prettyname\", $docstring, (dcerpc_call_fn)$callfn, (py_data_pack_fn)$infn, (py_data_unpack_fn)$outfn, $opnum, &ndr_table_$interface->{NAME} },");
}
- $self->pidl("{ NULL, NULL, 0, NULL }");
+ $self->pidl("{ NULL }");
$self->deindent;
$self->pidl("};");
$self->pidl("");
@@ -806,7 +762,6 @@ sub Interface($$$)
$self->pidl(".tp_name = \"$basename.$interface->{NAME}\",");
$self->pidl(".tp_basicsize = sizeof(dcerpc_InterfaceObject),");
$self->pidl(".tp_base = &dcerpc_InterfaceType,");
- $self->pidl(".tp_methods = interface_$interface->{NAME}_methods,");
$self->pidl(".tp_doc = $docstring,");
$self->pidl(".tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,");
$self->pidl(".tp_new = interface_$interface->{NAME}_new,");
@@ -816,6 +771,7 @@ sub Interface($$$)
$self->pidl("");
$self->register_module_typeobject($interface->{NAME}, "&$interface->{NAME}_InterfaceType");
+ $self->register_module_readycode(["if (!PyInterface_AddNdrRpcMethods(&$interface->{NAME}_InterfaceType, interface_$interface->{NAME}_methods))", "\treturn;", ""]);
}
$self->pidl_hdr("\n");
@@ -838,6 +794,13 @@ sub register_module_typeobject($$$)
push (@{$self->{module_types}}, [$name, $py_name])
}
+sub register_module_readycode($$)
+{
+ my ($self, $code) = @_;
+
+ push (@{$self->{readycode}}, @$code);
+}
+
sub register_module_object($$$)
{
my ($self, $name, $py_name) = @_;
@@ -1195,6 +1158,8 @@ sub Parse($$$$$)
$self->pidl("\treturn;");
}
+ $self->pidl($_) foreach (@{$self->{readycode}});
+
$self->pidl("");
$self->pidl("m = Py_InitModule3(\"$basename\", $basename\_methods, \"$basename DCE/RPC\");");