libsmb: Convert cli_list_recv() to single-recv
[samba.git] / source3 / libsmb / pylibsmb.c
index c09df91725118bd7fb49d08793562be0cfdefb70..a1d48fe863e62b77b483332169b18f2b0e200550 100644 (file)
@@ -440,18 +440,18 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
        PyObject *py_lp = Py_None;
        PyObject *py_multi_threaded = Py_False;
        bool multi_threaded = false;
-       PyObject *py_sign = Py_False;
-       bool sign = false;
-       int signing_state = SMB_SIGNING_DEFAULT;
        PyObject *py_force_smb1 = Py_False;
        bool force_smb1 = false;
+       PyObject *py_ipc = Py_False;
+       bool use_ipc = false;
        struct tevent_req *req;
        bool ret;
        int flags = 0;
 
        static const char *kwlist[] = {
                "host", "share", "lp", "creds",
-               "multi_threaded", "sign", "force_smb1",
+               "multi_threaded", "force_smb1",
+               "ipc",
                NULL
        };
 
@@ -466,8 +466,8 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
                &host, &share, &py_lp,
                py_type_Credentials, &creds,
                &py_multi_threaded,
-               &py_sign,
-               &py_force_smb1);
+               &py_force_smb1,
+               &py_ipc);
 
        Py_DECREF(py_type_Credentials);
 
@@ -476,13 +476,8 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
        }
 
        multi_threaded = PyObject_IsTrue(py_multi_threaded);
-       sign = PyObject_IsTrue(py_sign);
        force_smb1 = PyObject_IsTrue(py_force_smb1);
 
-       if (sign) {
-               signing_state = SMB_SIGNING_REQUIRED;
-       }
-
        if (force_smb1) {
                /*
                 * As most of the cli_*_send() function
@@ -493,6 +488,11 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
                flags = CLI_FULL_CONNECTION_FORCE_SMB1;
        }
 
+       use_ipc = PyObject_IsTrue(py_ipc);
+       if (use_ipc) {
+               flags |= CLI_FULL_CONNECTION_IPC;
+       }
+
        if (multi_threaded) {
 #ifdef HAVE_PTHREAD
                ret = py_cli_state_setup_mt_ev(self);
@@ -525,7 +525,7 @@ static int py_cli_state_init(struct py_cli_state *self, PyObject *args,
 
        req = cli_full_connection_creds_send(
                NULL, self->ev, "myname", host, NULL, 0, share, "?????",
-               cli_creds, flags, signing_state);
+               cli_creds, flags);
        if (!py_tevent_req_wait_exc(self, req)) {
                return -1;
        }
@@ -682,7 +682,7 @@ static PyObject *py_cli_settimeout(struct py_cli_state *self, PyObject *args)
 
        omsecs = cli_set_timeout(self->cli, nmsecs);
 
-       return PyInt_FromLong(omsecs);
+       return PyLong_FromLong(omsecs);
 }
 
 static PyObject *py_cli_create(struct py_cli_state *self, PyObject *args,
@@ -883,27 +883,15 @@ static NTSTATUS py_smb_filesize(struct py_cli_state *self, uint16_t fnum,
                                off_t *size)
 {
        NTSTATUS status;
+       struct tevent_req *req = NULL;
 
-       if (self->is_smb1) {
-               uint8_t *rdata = NULL;
-               struct tevent_req *req = NULL;
-
-               req = cli_qfileinfo_send(NULL, self->ev, self->cli, fnum,
-                                        SMB_QUERY_FILE_ALL_INFO, 68,
-                                        CLI_BUFFER_SIZE);
-               if (!py_tevent_req_wait_exc(self, req)) {
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-               status = cli_qfileinfo_recv(req, NULL, NULL, &rdata, NULL);
-               if (NT_STATUS_IS_OK(status)) {
-                       *size = IVAL2_TO_SMB_BIG_UINT(rdata, 48);
-               }
-               TALLOC_FREE(req);
-               TALLOC_FREE(rdata);
-       } else {
-               status = cli_qfileinfo_basic(self->cli, fnum, NULL, size,
-                                            NULL, NULL, NULL, NULL, NULL);
+       req = cli_qfileinfo_basic_send(NULL, self->ev, self->cli, fnum);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return NT_STATUS_INTERNAL_ERROR;
        }
+       status = cli_qfileinfo_basic_recv(
+               req, NULL, size, NULL, NULL, NULL, NULL, NULL);
+       TALLOC_FREE(req);
        return status;
 }
 
@@ -1118,7 +1106,7 @@ static PyObject *py_cli_delete_on_close(struct py_cli_state *self,
 /*
  * Helper to add directory listing entries to an overall Python list
  */
-static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo,
+static NTSTATUS list_helper(struct file_info *finfo,
                            const char *mask, void *state)
 {
        PyObject *result = (PyObject *)state;
@@ -1137,7 +1125,7 @@ static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo,
         */
        file = Py_BuildValue("{s:s,s:i,s:s,s:O,s:l}",
                             "name", finfo->name,
-                            "attrib", (int)finfo->mode,
+                            "attrib", (int)finfo->attr,
                             "short_name", finfo->short_name,
                             "size", size,
                             "mtime",
@@ -1158,19 +1146,38 @@ static NTSTATUS list_helper(const char *mntpoint, struct file_info *finfo,
        return NT_STATUS_OK;
 }
 
+struct do_listing_state {
+       const char *mask;
+       NTSTATUS (*callback_fn)(
+               struct file_info *finfo,
+               const char *mask,
+               void *private_data);
+       void *private_data;
+       NTSTATUS status;
+};
+
+static void do_listing_cb(struct tevent_req *subreq)
+{
+       struct do_listing_state *state = tevent_req_callback_data_void(subreq);
+       struct file_info *finfo = NULL;
+
+       state->status = cli_list_recv(subreq, NULL, &finfo);
+       if (!NT_STATUS_IS_OK(state->status)) {
+               return;
+       }
+       state->callback_fn(finfo, state->mask, state->private_data);
+       TALLOC_FREE(finfo);
+}
+
 static NTSTATUS do_listing(struct py_cli_state *self,
                           const char *base_dir, const char *user_mask,
                           uint16_t attribute,
-                          NTSTATUS (*callback_fn)(const char *,
-                                                  struct file_info *,
+                          NTSTATUS (*callback_fn)(struct file_info *,
                                                   const char *, void *),
                           void *priv)
 {
        char *mask = NULL;
        unsigned int info_level = SMB_FIND_FILE_BOTH_DIRECTORY_INFO;
-       struct file_info *finfos = NULL;
-       size_t i;
-       size_t num_finfos = 0;
        NTSTATUS status;
 
        if (user_mask == NULL) {
@@ -1185,36 +1192,37 @@ static NTSTATUS do_listing(struct py_cli_state *self,
        dos_format(mask);
 
        if (self->is_smb1) {
+               struct do_listing_state state = {
+                       .mask = mask,
+                       .callback_fn = callback_fn,
+                       .private_data = priv,
+               };
                struct tevent_req *req = NULL;
 
                req = cli_list_send(NULL, self->ev, self->cli, mask, attribute,
                                    info_level);
+               if (req == NULL) {
+                       status = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+               tevent_req_set_callback(req, do_listing_cb, &state);
+
                if (!py_tevent_req_wait_exc(self, req)) {
                        return NT_STATUS_INTERNAL_ERROR;
                }
-               status = cli_list_recv(req, NULL, &finfos, &num_finfos);
                TALLOC_FREE(req);
+
+               status = state.status;
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_FILES)) {
+                       status = NT_STATUS_OK;
+               }
        } else {
                status = cli_list(self->cli, mask, attribute, callback_fn,
                                  priv);
        }
-       TALLOC_FREE(mask);
-
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /* invoke the callback for the async results (SMBv1 connections) */
-       for (i = 0; i < num_finfos; i++) {
-               status = callback_fn(base_dir, &finfos[i], user_mask,
-                                    priv);
-               if (!NT_STATUS_IS_OK(status)) {
-                       TALLOC_FREE(finfos);
-                       return status;
-               }
-       }
 
-       TALLOC_FREE(finfos);
+done:
+       TALLOC_FREE(mask);
        return status;
 }
 
@@ -1251,78 +1259,44 @@ static PyObject *py_cli_list(struct py_cli_state *self,
        return result;
 }
 
-/*
- * Deletes a file
- */
-static NTSTATUS unlink_file(struct py_cli_state *self, const char *filename)
-{
-       NTSTATUS status;
-       uint16_t attrs = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
-
-       if (self->is_smb1) {
-               struct tevent_req *req = NULL;
-
-               req = cli_unlink_send(NULL, self->ev, self->cli, filename,
-                                     attrs);
-               if (!py_tevent_req_wait_exc(self, req)) {
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-               status = cli_unlink_recv(req);
-               TALLOC_FREE(req);
-       } else {
-               status = cli_unlink(self->cli, filename, attrs);
-       }
-
-       return status;
-}
-
 static PyObject *py_smb_unlink(struct py_cli_state *self, PyObject *args)
 {
        NTSTATUS status;
        const char *filename = NULL;
+       struct tevent_req *req = NULL;
+       const uint32_t attrs = (FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);
 
        if (!PyArg_ParseTuple(args, "s:unlink", &filename)) {
                return NULL;
        }
 
-       status = unlink_file(self, filename);
+       req = cli_unlink_send(NULL, self->ev, self->cli, filename, attrs);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return NULL;
+       }
+       status = cli_unlink_recv(req);
+       TALLOC_FREE(req);
        PyErr_NTSTATUS_NOT_OK_RAISE(status);
 
        Py_RETURN_NONE;
 }
 
-/*
- * Delete an empty directory
- */
-static NTSTATUS remove_dir(struct py_cli_state *self, const char *dirname)
-{
-       NTSTATUS status;
-
-       if (self->is_smb1) {
-               struct tevent_req *req = NULL;
-
-               req = cli_rmdir_send(NULL, self->ev, self->cli, dirname);
-               if (!py_tevent_req_wait_exc(self, req)) {
-                       return NT_STATUS_INTERNAL_ERROR;
-               }
-               status = cli_rmdir_recv(req);
-               TALLOC_FREE(req);
-       } else {
-               status = cli_rmdir(self->cli, dirname);
-       }
-       return status;
-}
-
 static PyObject *py_smb_rmdir(struct py_cli_state *self, PyObject *args)
 {
        NTSTATUS status;
+       struct tevent_req *req = NULL;
        const char *dirname = NULL;
 
        if (!PyArg_ParseTuple(args, "s:rmdir", &dirname)) {
                return NULL;
        }
 
-       status = remove_dir(self, dirname);
+       req = cli_rmdir_send(NULL, self->ev, self->cli, dirname);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return NULL;
+       }
+       status = cli_rmdir_recv(req);
+       TALLOC_FREE(req);
        PyErr_NTSTATUS_IS_ERR_RAISE(status);
 
        Py_RETURN_NONE;
@@ -1335,23 +1309,18 @@ static PyObject *py_smb_mkdir(struct py_cli_state *self, PyObject *args)
 {
        NTSTATUS status;
        const char *dirname = NULL;
+       struct tevent_req *req = NULL;
 
        if (!PyArg_ParseTuple(args, "s:mkdir", &dirname)) {
                return NULL;
        }
 
-       if (self->is_smb1) {
-               struct tevent_req *req = NULL;
-
-               req = cli_mkdir_send(NULL, self->ev, self->cli, dirname);
-               if (!py_tevent_req_wait_exc(self, req)) {
-                       return NULL;
-               }
-               status = cli_mkdir_recv(req);
-               TALLOC_FREE(req);
-       } else {
-               status = cli_mkdir(self->cli, dirname);
+       req = cli_mkdir_send(NULL, self->ev, self->cli, dirname);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return NULL;
        }
+       status = cli_mkdir_recv(req);
+       TALLOC_FREE(req);
        PyErr_NTSTATUS_IS_ERR_RAISE(status);
 
        Py_RETURN_NONE;
@@ -1363,19 +1332,14 @@ static PyObject *py_smb_mkdir(struct py_cli_state *self, PyObject *args)
 static bool check_dir_path(struct py_cli_state *self, const char *path)
 {
        NTSTATUS status;
+       struct tevent_req *req = NULL;
 
-       if (self->is_smb1) {
-               struct tevent_req *req = NULL;
-
-               req = cli_chkpath_send(NULL, self->ev, self->cli, path);
-               if (!py_tevent_req_wait_exc(self, req)) {
-                       return false;
-               }
-               status = cli_chkpath_recv(req);
-               TALLOC_FREE(req);
-       } else {
-               status = cli_chkpath(self->cli, path);
+       req = cli_chkpath_send(NULL, self->ev, self->cli, path);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return false;
        }
+       status = cli_chkpath_recv(req);
+       TALLOC_FREE(req);
 
        return NT_STATUS_IS_OK(status);
 }
@@ -1393,164 +1357,40 @@ static PyObject *py_smb_chkpath(struct py_cli_state *self, PyObject *args)
        return PyBool_FromLong(dir_exists);
 }
 
-struct deltree_state {
-       struct py_cli_state *self;
-       const char *full_dirpath;
-};
-
-static NTSTATUS delete_dir_tree(struct py_cli_state *self,
-                               const char *dirpath);
-
-/*
- * Deletes a single item in the directory tree. This could be either a file
- * or a directory. This function gets invoked as a callback for every item in
- * the given directory's listings.
- */
-static NTSTATUS delete_tree_callback(const char *mntpoint,
-                                    struct file_info *finfo,
-                                    const char *mask, void *priv)
-{
-       char *filepath = NULL;
-       struct deltree_state *state = priv;
-       NTSTATUS status;
-
-       /* skip '.' or '..' directory listings */
-       if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
-               return NT_STATUS_OK;
-       }
-
-       /* get the absolute filepath */
-       filepath = talloc_asprintf(NULL, "%s\\%s", state->full_dirpath,
-                                  finfo->name);
-       if (filepath == NULL) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       if (finfo->mode & FILE_ATTRIBUTE_DIRECTORY) {
-
-               /* recursively delete the sub-directory and its contents */
-               status = delete_dir_tree(state->self, filepath);
-       } else {
-               status = unlink_file(state->self, filepath);
-       }
-
-       TALLOC_FREE(filepath);
-       return status;
-}
-
-/*
- * Removes a directory and all its contents
- */
-static NTSTATUS delete_dir_tree(struct py_cli_state *self,
-                               const char *filepath)
-{
-       NTSTATUS status;
-       const char *mask = "*";
-       struct deltree_state state = { 0 };
-
-       /* go through the directory's contents, deleting each item */
-       state.self = self;
-       state.full_dirpath = filepath;
-       status = do_listing(self, filepath, mask, LIST_ATTRIBUTE_MASK,
-                           delete_tree_callback, &state);
-
-       /* remove the directory itself */
-       if (NT_STATUS_IS_OK(status)) {
-               status = remove_dir(self, filepath);
-       }
-       return status;
-}
-
-static PyObject *py_smb_deltree(struct py_cli_state *self, PyObject *args)
+static PyObject *py_smb_get_sd(struct py_cli_state *self, PyObject *args)
 {
-       NTSTATUS status;
-       const char *filepath = NULL;
-       bool dir_exists;
-
-       if (!PyArg_ParseTuple(args, "s:deltree", &filepath)) {
-               return NULL;
-       }
-
-       /* check whether we're removing a directory or a file */
-       dir_exists = check_dir_path(self, filepath);
-
-       if (dir_exists) {
-               status = delete_dir_tree(self, filepath);
-       } else {
-               status = unlink_file(self, filepath);
-       }
-
-       PyErr_NTSTATUS_IS_ERR_RAISE(status);
-
-       Py_RETURN_NONE;
-}
-
-/*
- * Read ACL on a given file/directory as a security descriptor object
- */
-static PyObject *py_smb_getacl(struct py_cli_state *self, PyObject *args)
-{
-       NTSTATUS status;
-       const char *filename = NULL;
-       unsigned int sinfo = SECINFO_DEFAULT_FLAGS;
-       unsigned int access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
-       uint16_t fnum;
+       int fnum;
+       unsigned sinfo;
+       struct tevent_req *req = NULL;
        struct security_descriptor *sd = NULL;
+       NTSTATUS status;
 
-       /* there's no async version of cli_query_security_descriptor() */
-       if (self->thread_state != NULL) {
-               PyErr_SetString(PyExc_RuntimeError,
-                               "get_acl() is not supported on "
-                               "a multi_threaded connection");
+       if (!PyArg_ParseTuple(args, "iI:get_acl", &fnum, &sinfo)) {
                return NULL;
        }
 
-       if (!PyArg_ParseTuple(args, "s|II:get_acl", &filename, &sinfo,
-                             &access_mask)) {
-               return NULL;
+       req = cli_query_security_descriptor_send(
+               NULL, self->ev, self->cli, fnum, sinfo);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return false;
        }
-
-       /* get a file handle with the desired access */
-       status = cli_ntcreate(self->cli, filename, 0, access_mask, 0,
-                             FILE_SHARE_READ|FILE_SHARE_WRITE,
-                             FILE_OPEN, 0x0, 0x0, &fnum, NULL);
-       PyErr_NTSTATUS_IS_ERR_RAISE(status);
-
-       /* query the security descriptor for this file */
-       status = cli_query_security_descriptor(self->cli, fnum, sinfo,
-                                              NULL, &sd);
-       PyErr_NTSTATUS_IS_ERR_RAISE(status);
-
-       /* close the file handle and convert the SD to a python struct */
-       status = cli_close(self->cli, fnum);
+       status = cli_query_security_descriptor_recv(req, NULL, &sd);
        PyErr_NTSTATUS_IS_ERR_RAISE(status);
 
-       return py_return_ndr_struct("samba.dcerpc.security", "descriptor",
-                                   sd, sd);
+       return py_return_ndr_struct(
+               "samba.dcerpc.security", "descriptor", sd, sd);
 }
 
-/*
- * Set ACL on file/directory using given security descriptor object
- */
-static PyObject *py_smb_setacl(struct py_cli_state *self, PyObject *args)
+static PyObject *py_smb_set_sd(struct py_cli_state *self, PyObject *args)
 {
-       NTSTATUS status;
-       char *filename = NULL;
        PyObject *py_sd = NULL;
+       struct tevent_req *req = NULL;
        struct security_descriptor *sd = NULL;
-       unsigned int sinfo = SECINFO_DEFAULT_FLAGS;
        uint16_t fnum;
+       unsigned int sinfo;
+       NTSTATUS status;
 
-       /* there's no async version of cli_set_security_descriptor() */
-       if (self->thread_state != NULL) {
-               PyErr_SetString(PyExc_RuntimeError,
-                               "set_acl() is not supported on "
-                               "a multi_threaded connection");
-               return NULL;
-       }
-
-       if (!PyArg_ParseTuple(args, "sO|I:set_acl", &filename, &py_sd,
-                             &sinfo)) {
+       if (!PyArg_ParseTuple(args, "iOI:set_sd", &fnum, &py_sd, &sinfo)) {
                return NULL;
        }
 
@@ -1562,16 +1402,13 @@ static PyObject *py_smb_setacl(struct py_cli_state *self, PyObject *args)
                return NULL;
        }
 
-       status = cli_ntcreate(self->cli, filename, 0,
-                             SEC_FLAG_MAXIMUM_ALLOWED, 0,
-                             FILE_SHARE_READ|FILE_SHARE_WRITE,
-                             FILE_OPEN, 0x0, 0x0, &fnum, NULL);
-       PyErr_NTSTATUS_IS_ERR_RAISE(status);
-
-       status = cli_set_security_descriptor(self->cli, fnum, sinfo, sd);
-       PyErr_NTSTATUS_IS_ERR_RAISE(status);
+       req = cli_set_security_descriptor_send(
+               NULL, self->ev, self->cli, fnum, sinfo, sd);
+       if (!py_tevent_req_wait_exc(self, req)) {
+               return false;
+       }
 
-       status = cli_close(self->cli, fnum);
+       status = cli_set_security_descriptor_recv(req);
        PyErr_NTSTATUS_IS_ERR_RAISE(status);
 
        Py_RETURN_NONE;
@@ -1629,24 +1466,21 @@ static PyMethodDef py_cli_state_methods[] = {
        { "loadfile", (PyCFunction)py_smb_loadfile, METH_VARARGS,
          "loadfile(path) -> file contents as a " PY_DESC_PY3_BYTES
          "\n\n\t\tRead contents of a file." },
-       { "deltree", (PyCFunction)py_smb_deltree, METH_VARARGS,
-         "deltree(path) -> None\n\n"
-         "\t\tDelete a directory and all its contents." },
-       { "get_acl", (PyCFunction)py_smb_getacl, METH_VARARGS,
-         "get_acl(path[, security_info=0]) -> security_descriptor object\n\n"
-         "\t\tGet security descriptor for file." },
-       { "set_acl", (PyCFunction)py_smb_setacl, METH_VARARGS,
-         "set_acl(path, security_descriptor[, security_info=0]) -> None\n\n"
-         "\t\tSet security descriptor for file." },
+       { "get_sd", (PyCFunction)py_smb_get_sd, METH_VARARGS,
+         "get_sd(fnum[, security_info=0]) -> security_descriptor object\n\n"
+         "\t\tGet security descriptor for opened file." },
+       { "set_sd", (PyCFunction)py_smb_set_sd, METH_VARARGS,
+         "set_sd(fnum, security_descriptor[, security_info=0]) -> None\n\n"
+         "\t\tSet security descriptor for opened file." },
        { NULL, NULL, 0, NULL }
 };
 
 static PyTypeObject py_cli_state_type = {
        PyVarObject_HEAD_INIT(NULL, 0)
-       .tp_name = "libsmb_samba_internal.Conn",
+       .tp_name = "libsmb_samba_cwrapper.LibsmbCConn",
        .tp_basicsize = sizeof(struct py_cli_state),
        .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
-       .tp_doc = "libsmb connection",
+       .tp_doc = "libsmb cwrapper connection",
        .tp_new = py_cli_state_new,
        .tp_init = (initproc)py_cli_state_init,
        .tp_dealloc = (destructor)py_cli_state_dealloc,
@@ -1654,20 +1488,20 @@ static PyTypeObject py_cli_state_type = {
 };
 
 static PyMethodDef py_libsmb_methods[] = {
-       { NULL },
+       {0},
 };
 
-void initlibsmb_samba_internal(void);
+void initlibsmb_samba_cwrapper(void);
 
 static struct PyModuleDef moduledef = {
     PyModuleDef_HEAD_INIT,
-    .m_name = "libsmb_samba_internal",
+    .m_name = "libsmb_samba_cwrapper",
     .m_doc = "libsmb wrapper",
     .m_size = -1,
     .m_methods = py_libsmb_methods,
 };
 
-MODULE_INIT_FUNC(libsmb_samba_internal)
+MODULE_INIT_FUNC(libsmb_samba_cwrapper)
 {
        PyObject *m = NULL;
 
@@ -1681,9 +1515,9 @@ MODULE_INIT_FUNC(libsmb_samba_internal)
                return NULL;
        }
        Py_INCREF(&py_cli_state_type);
-       PyModule_AddObject(m, "Conn", (PyObject *)&py_cli_state_type);
+       PyModule_AddObject(m, "LibsmbCConn", (PyObject *)&py_cli_state_type);
 
-#define ADD_FLAGS(val) PyModule_AddObject(m, #val, PyInt_FromLong(val))
+#define ADD_FLAGS(val) PyModule_AddObject(m, #val, PyLong_FromLong(val))
 
        ADD_FLAGS(FILE_ATTRIBUTE_READONLY);
        ADD_FLAGS(FILE_ATTRIBUTE_HIDDEN);
@@ -1702,5 +1536,9 @@ MODULE_INIT_FUNC(libsmb_samba_internal)
        ADD_FLAGS(FILE_ATTRIBUTE_ENCRYPTED);
        ADD_FLAGS(FILE_ATTRIBUTE_ALL_MASK);
 
+       ADD_FLAGS(FILE_SHARE_READ);
+       ADD_FLAGS(FILE_SHARE_WRITE);
+       ADD_FLAGS(FILE_SHARE_DELETE);
+
        return m;
 }