diff options
-rw-r--r-- | source4/librpc/rpc/dcerpc.h | 1 | ||||
-rw-r--r-- | source4/librpc/rpc/pyrpc.c | 101 | ||||
-rw-r--r-- | source4/librpc/rpc/pyrpc.h | 16 | ||||
-rw-r--r-- | source4/pidl/lib/Parse/Pidl/Samba4/Python.pm | 83 |
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\");"); |