s4:pyrpc: add pyrpc_PyStr_AsString() helper function
[metze/samba/wip.git] / source4 / librpc / rpc / pyrpc_util.c
index 95443f7772ce00fa1489bb65f250e058c56f8e01..aa996c032b397e8cdb75408b8d599d2c126de697 100644 (file)
@@ -21,6 +21,7 @@
 */
 
 #include <Python.h>
+#include "python/py3compat.h"
 #include "includes.h"
 #include "librpc/rpc/pyrpc_util.h"
 #include "librpc/rpc/dcerpc.h"
@@ -115,6 +116,11 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
        }
 
        ret = PyObject_New(dcerpc_InterfaceObject, type);
+       if (ret == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
        ret->pipe = NULL;
        ret->binding_handle = NULL;
        ret->mem_ctx = talloc_new(NULL);
@@ -131,6 +137,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (event_ctx == NULL) {
                        PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
 
@@ -138,6 +145,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (lp_ctx == NULL) {
                        PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
 
@@ -146,6 +154,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (!NT_STATUS_IS_OK(status)) {
                        PyErr_SetNTSTATUS(status);
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
        } else if (py_basis != Py_None) {
@@ -156,6 +165,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                py_base = PyImport_ImportModule("samba.dcerpc.base");
                if (py_base == NULL) {
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
 
@@ -163,12 +173,17 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (ClientConnection_Type == NULL) {
                        PyErr_SetNone(PyExc_TypeError);
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
+                       Py_DECREF(py_base);
                        return NULL;
                }
 
                if (!PyObject_TypeCheck(py_basis, ClientConnection_Type)) {
                        PyErr_SetString(PyExc_TypeError, "basis_connection must be a DCE/RPC connection");
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
+                       Py_DECREF(py_base);
+                       Py_DECREF(ClientConnection_Type);
                        return NULL;
                }
 
@@ -177,6 +192,9 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (base_pipe == NULL) {
                        PyErr_NoMemory();
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
+                       Py_DECREF(py_base);
+                       Py_DECREF(ClientConnection_Type);
                        return NULL;
                }
 
@@ -184,10 +202,15 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (!NT_STATUS_IS_OK(status)) {
                        PyErr_SetNTSTATUS(status);
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
+                       Py_DECREF(py_base);
+                       Py_DECREF(ClientConnection_Type);
                        return NULL;
                }
 
                ret->pipe = talloc_steal(ret->mem_ctx, ret->pipe);
+               Py_XDECREF(ClientConnection_Type);
+               Py_XDECREF(py_base);
        } else {
                struct tevent_context *event_ctx;
                struct loadparm_context *lp_ctx;
@@ -197,6 +220,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (event_ctx == NULL) {
                        PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
 
@@ -204,6 +228,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (lp_ctx == NULL) {
                        PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
 
@@ -211,6 +236,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (credentials == NULL) {
                        PyErr_SetString(PyExc_TypeError, "Expected credentials");
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
                status = dcerpc_pipe_connect(ret->mem_ctx, &ret->pipe, binding_string,
@@ -218,6 +244,7 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
                if (!NT_STATUS_IS_OK(status)) {
                        PyErr_SetNTSTATUS(status);
                        TALLOC_FREE(ret->mem_ctx);
+                       Py_DECREF(ret);
                        return NULL;
                }
 
@@ -312,6 +339,7 @@ bool PyInterface_AddNdrRpcMethods(PyTypeObject *ifacetype, const struct PyNdrRpc
 
                PyDict_SetItemString(ifacetype->tp_dict, mds[i].name, 
                                     (PyObject *)ret);
+               Py_CLEAR(ret);
        }
 
        return true;
@@ -333,7 +361,7 @@ PyObject *py_dcerpc_syntax_init_helper(PyTypeObject *type, PyObject *args, PyObj
                return NULL;
        }
 
-       obj = (struct ndr_syntax_id *)pytalloc_get_ptr(ret);
+       obj = pytalloc_get_type(ret, struct ndr_syntax_id);
        *obj = *syntax;
 
        return ret;
@@ -365,6 +393,7 @@ PyObject *py_return_ndr_struct(const char *module_name, const char *type_name,
 {
        PyTypeObject *py_type;
        PyObject *module;
+       PyObject *result = NULL;
 
        if (r == NULL) {
                Py_RETURN_NONE;
@@ -377,10 +406,14 @@ PyObject *py_return_ndr_struct(const char *module_name, const char *type_name,
 
        py_type = (PyTypeObject *)PyObject_GetAttrString(module, type_name);
        if (py_type == NULL) {
+               Py_DECREF(module);
                return NULL;
        }
 
-       return pytalloc_reference_ex(py_type, r_ctx, r);
+       result = pytalloc_reference_ex(py_type, r_ctx, r);
+       Py_CLEAR(module);
+       Py_CLEAR(py_type);
+       return result;
 }
 
 PyObject *PyString_FromStringOrNULL(const char *str)
@@ -388,5 +421,125 @@ PyObject *PyString_FromStringOrNULL(const char *str)
        if (str == NULL) {
                Py_RETURN_NONE;
        }
-       return PyString_FromString(str);
+       return PyStr_FromString(str);
+}
+
+const char *pyrpc_PyStr_AsString(TALLOC_CTX *mem_ctx, PyObject *value)
+{
+       const char *test_str = NULL;
+       const char *talloc_str = NULL;
+       PyObject *unicode = NULL;
+
+       if (PyUnicode_Check(value)) {
+               unicode = PyUnicode_AsEncodedString(value, "utf-8", "ignore");
+               if (unicode == NULL) {
+                       PyErr_NoMemory();
+                       return NULL;
+               }
+               test_str = PyBytes_AS_STRING(unicode);
+       } else if (PyBytes_Check(value)) {
+               test_str = PyBytes_AS_STRING(value);
+       } else {
+               PyErr_Format(PyExc_TypeError,
+                            "Expected string or unicode object, got %s",
+                            Py_TYPE(value)->tp_name);
+               return NULL;
+       }
+
+       talloc_str = talloc_strdup(mem_ctx, test_str);
+       if (unicode != NULL) {
+               Py_DECREF(unicode);
+       }
+       if (talloc_str == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       return talloc_str;
+}
+
+PyObject *pyrpc_import_union(PyTypeObject *type, TALLOC_CTX *mem_ctx, int level,
+                            const void *in, const char *typename)
+{
+       PyObject *mem_ctx_obj = NULL;
+       PyObject *in_obj = NULL;
+       PyObject *ret = NULL;
+
+       mem_ctx_obj = pytalloc_GenericObject_reference(mem_ctx);
+       if (mem_ctx_obj == NULL) {
+               return NULL;
+       }
+
+       in_obj = pytalloc_GenericObject_reference_ex(mem_ctx, discard_const(in));
+       if (in_obj == NULL) {
+               Py_XDECREF(mem_ctx_obj);
+               return NULL;
+       }
+
+       ret = PyObject_CallMethod((PyObject *)type,
+                                 discard_const_p(char, "__import__"),
+                                 discard_const_p(char, "OiO"),
+                                 mem_ctx_obj, level, in_obj);
+       Py_XDECREF(mem_ctx_obj);
+       Py_XDECREF(in_obj);
+       if (ret == NULL) {
+               return NULL;
+       }
+
+       return ret;
+}
+
+void *pyrpc_export_union(PyTypeObject *type, TALLOC_CTX *mem_ctx, int level,
+                        PyObject *in, const char *typename)
+{
+       PyObject *mem_ctx_obj = NULL;
+       PyObject *ret_obj = NULL;
+       void *ret = NULL;
+
+       mem_ctx_obj = pytalloc_GenericObject_reference(mem_ctx);
+       if (mem_ctx_obj == NULL) {
+               return NULL;
+       }
+
+       ret_obj = PyObject_CallMethod((PyObject *)type,
+                                     discard_const_p(char, "__export__"),
+                                     discard_const_p(char, "OiO"),
+                                     mem_ctx_obj, level, in);
+       Py_XDECREF(mem_ctx_obj);
+       if (ret_obj == NULL) {
+               return NULL;
+       }
+
+       ret = _pytalloc_get_type(ret_obj, typename);
+       Py_XDECREF(ret_obj);
+       return ret;
+}
+
+PyObject *py_dcerpc_ndr_pointer_deref(PyTypeObject *type, PyObject *obj)
+{
+       if (!PyObject_TypeCheck(obj, type)) {
+               PyErr_Format(PyExc_TypeError,
+                            "Expected type '%s' but got type '%s'",
+                            (type)->tp_name, Py_TYPE(obj)->tp_name);
+               return NULL;
+       }
+
+       return PyObject_GetAttrString(obj, discard_const_p(char, "value"));
+}
+
+PyObject *py_dcerpc_ndr_pointer_wrap(PyTypeObject *type, PyObject *obj)
+{
+       PyObject *args = NULL;
+       PyObject *ret_obj = NULL;
+
+       args = PyTuple_New(1);
+       if (args == NULL) {
+               return NULL;
+       }
+       Py_XINCREF(obj);
+       PyTuple_SetItem(args, 0, obj);
+
+       ret_obj = PyObject_Call((PyObject *)type, args, NULL);
+       Py_XDECREF(args);
+       return ret_obj;
 }