diff --git a/src/calibre/devices/mtp/windows/content_enumeration.cpp b/src/calibre/devices/mtp/windows/content_enumeration.cpp index b7ea6eaddf..286507cea4 100644 --- a/src/calibre/devices/mtp/windows/content_enumeration.cpp +++ b/src/calibre/devices/mtp/windows/content_enumeration.cpp @@ -7,6 +7,7 @@ #include "global.h" +#include #include namespace wpd { @@ -169,12 +170,14 @@ private: if (PyDict_SetItem(this->items, object_id.ptr(), obj.ptr()) != 0) { PyErr_Clear(); return; } } else Py_INCREF(obj.ptr()); set_properties(obj.ptr(), properties); - pyobject_raii r(PyObject_CallFunction(callback, "OI", obj.ptr(), this->level)); - if (!r) PyErr_Clear(); - else if (r && PyObject_IsTrue(r.ptr())) { - PyObject *borrowed = PyDict_GetItemString(obj.ptr(), "id"); - if (borrowed) if (PyList_Append(this->subfolders, borrowed) != 0) PyErr_Clear(); - } + if (callback) { + pyobject_raii r(PyObject_CallFunction(callback, "OI", obj.ptr(), this->level)); + if (!r) PyErr_Clear(); + else if (r && PyObject_IsTrue(r.ptr())) { + PyObject *borrowed = PyDict_GetItemString(obj.ptr(), "id"); + if (borrowed) if (PyList_Append(this->subfolders, borrowed) != 0) PyErr_Clear(); + } + } } void handle_values(IPortableDeviceValuesCollection* values) { @@ -422,9 +425,11 @@ single_get_filesystem(unsigned int level, CComPtr &conte if (SUCCEEDED(hr) && pv.pwszVal != NULL) { pyobject_raii item(get_object_properties(devprops, properties, pv.pwszVal)); if (!item) return false; - pyobject_raii r(PyObject_CallFunction(callback, "OI", item.ptr(), level)); if (PyDict_SetItem(ans, PyDict_GetItemString(item.ptr(), "id"), item.ptr()) != 0) return false; - if (r && PyObject_IsTrue(r.ptr())) recurse.attach(item.detach()); + if (callback) { + pyobject_raii r(PyObject_CallFunction(callback, "OI", item.ptr(), level)); + if (r && PyObject_IsTrue(r.ptr())) recurse.attach(item.detach()); + } } else { hresult_set_exc("Failed to get item from IPortableDevicePropVariantCollection", hr); return false; } if (recurse) { @@ -468,42 +473,28 @@ create_object_properties(const wchar_t *parent_id, const wchar_t *name, const GU } // }}} PyObject* -list_folder(CComPtr &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *folder_id) { +list_folder(IPortableDevice *device, CComPtr &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *folder_id) { HRESULT hr; CComPtr object_ids; Py_BEGIN_ALLOW_THREADS; hr = object_ids.CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, CLSCTX_INPROC_SERVER); Py_END_ALLOW_THREADS; if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); return NULL; } + pyobject_raii ans(PyDict_New()); if (!ans) return NULL; bool enum_failed = false; if (!find_objects_in(content, object_ids, folder_id, &enum_failed)) return NULL; - DWORD num; - CComPtr devprops; - hr = content->Properties(&devprops); - if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); return NULL; } - - CComPtr properties(create_filesystem_properties_collection()); - if (!properties) return NULL; - hr = object_ids->GetCount(&num); - if (FAILED(hr)) { hresult_set_exc("Failed to get object id count", hr); return NULL; } - pyobject_raii ans(PyList_New(0)); if (!ans) return NULL; - - for (DWORD i = 0; i < num; i++) { - prop_variant pv; - hr = object_ids->GetAt(i, &pv); - if (SUCCEEDED(hr) && pv.pwszVal != NULL) { - pyobject_raii item(get_object_properties(devprops, properties, pv.pwszVal)); - if (!item) return NULL; - if (PyList_Append(ans.ptr(), item.ptr()) != 0) return NULL; - } + if (bulk_properties) { + if (!bulk_get_filesystem(0, device, bulk_properties, object_ids, NULL, ans.ptr(), NULL)) return NULL; + } else { + if (!single_get_filesystem(0, content, object_ids, NULL, ans.ptr(), NULL)) return NULL; } return ans.detach(); } PyObject* -find_in_parent(CComPtr &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *parent_id, PyObject *name) { +find_in_parent(CComPtr &content, const wchar_t *parent_id, PyObject *name) { HRESULT hr; CComPtr object_ids; Py_BEGIN_ALLOW_THREADS; diff --git a/src/calibre/devices/mtp/windows/device.cpp b/src/calibre/devices/mtp/windows/device.cpp index dd2809b8b3..d36e9413a5 100644 --- a/src/calibre/devices/mtp/windows/device.cpp +++ b/src/calibre/devices/mtp/windows/device.cpp @@ -97,7 +97,7 @@ list_folder_by_name(Device *self, PyObject *args) { PyObject *k = PyTuple_GET_ITEM(names, i); if (!PyUnicode_Check(k)) { PyErr_SetString(PyExc_TypeError, "names must contain only unicode strings"); return NULL; } pyobject_raii l(PyObject_CallMethod(k, "lower", NULL)); if (!l) return NULL; - pyobject_raii object_id(wpd::find_in_parent(content, self->bulk_properties, parent_id.ptr(), l.ptr())); + pyobject_raii object_id(wpd::find_in_parent(content, parent_id.ptr(), l.ptr())); if (!object_id) { if (PyErr_Occurred()) return NULL; Py_RETURN_NONE; @@ -106,7 +106,7 @@ list_folder_by_name(Device *self, PyObject *args) { found = true; } if (!found) Py_RETURN_NONE; - return wpd::list_folder(content, self->bulk_properties, parent_id.ptr()); + return wpd::list_folder(self->device, content, self->bulk_properties, parent_id.ptr()); } // }}} // create_folder() {{{ diff --git a/src/calibre/devices/mtp/windows/driver.py b/src/calibre/devices/mtp/windows/driver.py index e8af41de37..a31992c042 100644 --- a/src/calibre/devices/mtp/windows/driver.py +++ b/src/calibre/devices/mtp/windows/driver.py @@ -398,7 +398,7 @@ class MTP_DEVICE(MTPDeviceBase): x = self.dev.list_folder_by_name(parent.object_id, names) if x is None: raise DeviceError(f'Could not find folder named: {"/".join(names)} in {parent.full_path}') - return x + return list(x.values()) @same_thread def get_mtp_file(self, f, stream=None, callback=None): diff --git a/src/calibre/devices/mtp/windows/global.h b/src/calibre/devices/mtp/windows/global.h index d85aa91d26..728ccc983e 100644 --- a/src/calibre/devices/mtp/windows/global.h +++ b/src/calibre/devices/mtp/windows/global.h @@ -50,7 +50,8 @@ extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id extern PyObject* delete_object(IPortableDevice *device, const wchar_t *object_id); extern PyObject* put_file(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name, PyObject *src, unsigned PY_LONG_LONG size, PyObject *callback); extern PyObject* find_in_parent( - CComPtr &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *parent_id, PyObject *name); + CComPtr &content, const wchar_t *parent_id, PyObject *name); extern PyObject* list_folder( - CComPtr &content, IPortableDevicePropertiesBulk *bulk_properties, const wchar_t *folder_id); + IPortableDevice *device, CComPtr &content, IPortableDevicePropertiesBulk *bulk_properties, + const wchar_t *folder_id); }