diff --git a/src/calibre/devices/mtp/driver.py b/src/calibre/devices/mtp/driver.py index 9af5cca337..fd950e0fc9 100644 --- a/src/calibre/devices/mtp/driver.py +++ b/src/calibre/devices/mtp/driver.py @@ -577,13 +577,15 @@ def main(): dev.filesystem_cache.dump() print('Prefix for main mem:', dev.prefix_for_location(None), flush=True) raw = os.urandom(32 * 1024) - f = dev.put_file(dev.filesystem_cache.entries[0], 'developing-mtp-driver.bin', io.BytesIO(raw), len(raw)) + folder = dev.create_folder(dev.filesystem_cache.entries[0], 'developing-mtp-driver') + f = dev.put_file(folder, 'developing-mtp-driver.bin', io.BytesIO(raw), len(raw)) print('Put file:', f, flush=True) buf = io.BytesIO() dev.get_file(f.mtp_id_path, buf) if buf.getvalue() != raw: raise ValueError('Getting previously put file did not return expected data') print('Successfully got previously put file', flush=True) + dev.recursive_delete(f) finally: dev.shutdown() diff --git a/src/calibre/devices/mtp/windows/content_enumeration.cpp b/src/calibre/devices/mtp/windows/content_enumeration.cpp index 06ba2739fe..6388548a24 100644 --- a/src/calibre/devices/mtp/windows/content_enumeration.cpp +++ b/src/calibre/devices/mtp/windows/content_enumeration.cpp @@ -591,82 +591,65 @@ wpd::get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest, PyObject* wpd::create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name) { // {{{ - IPortableDeviceContent *content = NULL; - IPortableDeviceValues *values = NULL; - IPortableDeviceProperties *devprops = NULL; - IPortableDeviceKeyCollection *properties = NULL; - wchar_t *newid = NULL; - PyObject *ans = NULL; + CComPtr content; + CComPtr values; + CComPtr devprops; + CComPtr properties; HRESULT hr; values = create_object_properties(parent_id, name, WPD_CONTENT_TYPE_FOLDER, 0); - if (values == NULL) goto end; + if (!values) return NULL; Py_BEGIN_ALLOW_THREADS; hr = device->Content(&content); Py_END_ALLOW_THREADS; - if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); goto end; } + if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); return NULL; } hr = content->Properties(&devprops); - if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); goto end; } + if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); return NULL; } properties = create_filesystem_properties_collection(); - if (properties == NULL) goto end; + if (!properties) return NULL; + wchar_raii newid; Py_BEGIN_ALLOW_THREADS; - hr = content->CreateObjectWithPropertiesOnly(values, &newid); + hr = content->CreateObjectWithPropertiesOnly(values, newid.unsafe_address()); Py_END_ALLOW_THREADS; - if (FAILED(hr) || newid == NULL) { hresult_set_exc("Failed to create folder", hr); goto end; } - - ans = get_object_properties(devprops, properties, newid); -end: - if (content != NULL) content->Release(); - if (values != NULL) values->Release(); - if (devprops != NULL) devprops->Release(); - if (properties != NULL) properties->Release(); - if (newid != NULL) CoTaskMemFree(newid); - return ans; + if (FAILED(hr) || !newid) { hresult_set_exc("Failed to create folder", hr); return NULL; } + return get_object_properties(devprops, properties, newid.ptr()); } // }}} PyObject* wpd::delete_object(IPortableDevice *device, const wchar_t *object_id) { // {{{ - IPortableDeviceContent *content = NULL; + CComPtr content; + CComPtr object_ids; HRESULT hr; - BOOL ok = FALSE; - PROPVARIANT pv; - IPortableDevicePropVariantCollection *object_ids = NULL; - - PropVariantInit(&pv); - pv.vt = VT_LPWSTR; Py_BEGIN_ALLOW_THREADS; - hr = CoCreateInstance(CLSID_PortableDevicePropVariantCollection, NULL, - CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&object_ids)); + 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); goto end; } + if (FAILED(hr)) { hresult_set_exc("Failed to create propvariantcollection", hr); return NULL; } + + prop_variant pv(VT_LPWSTR); pv.pwszVal = (wchar_t*)object_id; hr = object_ids->Add(&pv); pv.pwszVal = NULL; - if (FAILED(hr)) { hresult_set_exc("Failed to add device id to propvariantcollection", hr); goto end; } + if (FAILED(hr)) { hresult_set_exc("Failed to add device id to propvariantcollection", hr); return NULL; } Py_BEGIN_ALLOW_THREADS; hr = device->Content(&content); Py_END_ALLOW_THREADS; - if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); goto end; } + if (FAILED(hr)) { hresult_set_exc("Failed to create content interface", hr); return NULL; } hr = content->Delete(PORTABLE_DEVICE_DELETE_NO_RECURSION, object_ids, NULL); - if (hr == E_ACCESSDENIED) PyErr_SetString(WPDError, "Do not have permission to delete this object"); - else if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)) PyErr_SetString(WPDError, "Cannot delete object as it has children"); - else if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) || SUCCEEDED(hr)) ok = TRUE; - else hresult_set_exc("Cannot delete object", hr); + if (hr == HRESULT_FROM_WIN32(ERROR_NOT_FOUND) || SUCCEEDED(hr)) {Py_RETURN_NONE;} -end: - PropVariantClear(&pv); - if (content != NULL) content->Release(); - if (object_ids != NULL) object_ids->Release(); - if (!ok) return NULL; - Py_RETURN_NONE; + if (hr == E_ACCESSDENIED) { PyErr_SetExcFromWindowsErr(WPDError, ERROR_ACCESS_DENIED); } + else if (hr == HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY) || hr == HRESULT_FROM_WIN32(ERROR_INVALID_OPERATION)) { + PyErr_SetString(WPDError, "Cannot delete object as it has children"); } + else hresult_set_exc("Cannot delete object", hr); + return NULL; } // }}} diff --git a/src/calibre/devices/mtp/windows/remote.py b/src/calibre/devices/mtp/windows/remote.py deleted file mode 100644 index 265b0423b2..0000000000 --- a/src/calibre/devices/mtp/windows/remote.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python -# vim:fileencoding=UTF-8:ts=4:sw=4:sta:et:sts=4:fdm=marker:ai - - -__license__ = 'GPL v3' -__copyright__ = '2012, Kovid Goyal ' -__docformat__ = 'restructuredtext en' - -import subprocess, os, pprint, signal, time, glob, io -pprint, io -from polyglot.builtins import environ_item - - -def build(mod='wpd'): - master = subprocess.Popen('ssh -MN getafix'.split()) - master2 = subprocess.Popen('ssh -MN win64'.split()) - try: - while not glob.glob(os.path.expanduser('~/.ssh/*kovid@win64*')): - time.sleep(0.05) - builder = subprocess.Popen('ssh win64 ~/build-wpd'.split()) - if builder.wait() != 0: - raise Exception('Failed to build plugin') - while not glob.glob(os.path.expanduser('~/.ssh/*kovid@getafix*')): - time.sleep(0.05) - syncer = subprocess.Popen('ssh getafix ~/update-calibre'.split()) - if syncer.wait() != 0: - raise Exception('Failed to rsync to getafix') - subprocess.check_call( - ('scp win64:build/calibre/src/calibre/plugins/%s.pyd /tmp'%mod).split()) - subprocess.check_call( - ('scp /tmp/%s.pyd getafix:calibre-src/src/calibre/devices/mtp/windows'%mod).split()) - p = subprocess.Popen( - 'ssh getafix calibre-debug -e calibre-src/src/calibre/devices/mtp/windows/remote.py'.split()) - p.wait() - print() - finally: - for m in (master2, master): - m.send_signal(signal.SIGHUP) - for m in (master2, master): - m.wait() - - -def main(): - fp, d = os.path.abspath(__file__), os.path.dirname - if 'CALIBRE_DEVELOP_FROM' not in os.environ: - env = os.environ.copy() - env['CALIBRE_DEVELOP_FROM'] = environ_item(d(d(d(d(d(fp)))))) - subprocess.call(['calibre-debug', '-e', fp], env=env) - return - - # from calibre.devices.mtp.test import run - # run() - # return - - from calibre.devices.winusb import scan_usb_devices - from calibre.devices.mtp.driver import MTP_DEVICE - dev = MTP_DEVICE(None) - dev.startup() - print(dev.wpd, dev.wpd_error) - - try: - devices = scan_usb_devices() - pnp_id = dev.detect_managed_devices(devices) - if not pnp_id: - raise ValueError('Failed to detect device') - # pprint.pprint(dev.detected_devices) - print('Trying to connect to:', pnp_id) - dev.open(pnp_id, '') - pprint.pprint(dev.dev.data) - print('Connected to:', dev.get_gui_name()) - print('Total space', dev.total_space()) - print('Free space', dev.free_space()) - # pprint.pprint(dev.dev.create_folder(dev.filesystem_cache.entries[0].object_id, - # 'zzz')) - # print ('Fetching file: oFF (198214 bytes)') - # stream = dev.get_file('oFF') - # print ("Fetched size: ", stream.tell()) - # size = 4 - # stream = io.BytesIO(b'a'*size) - # name = 'zzz-test-file.txt' - # stream.seek(0) - # f = dev.put_file(dev.filesystem_cache.entries[0], name, stream, size) - # print ('Put file:', f) - dev.filesystem_cache.dump() - finally: - dev.shutdown() - - print('Device connection shutdown') - - -if __name__ == '__main__': - main()