WPD: Create folders and use the actual file name instead of the nominal_name

This commit is contained in:
Kovid Goyal 2012-08-22 16:22:09 +05:30
parent 922e02e0d7
commit 179d4781f0
4 changed files with 96 additions and 1 deletions

View File

@ -28,6 +28,7 @@ static IPortableDeviceKeyCollection* create_filesystem_properties_collection() {
ADDPROP(WPD_OBJECT_PARENT_ID); ADDPROP(WPD_OBJECT_PARENT_ID);
ADDPROP(WPD_OBJECT_PERSISTENT_UNIQUE_ID); ADDPROP(WPD_OBJECT_PERSISTENT_UNIQUE_ID);
ADDPROP(WPD_OBJECT_NAME); ADDPROP(WPD_OBJECT_NAME);
ADDPROP(WPD_OBJECT_ORIGINAL_FILE_NAME);
// ADDPROP(WPD_OBJECT_SYNC_ID); // ADDPROP(WPD_OBJECT_SYNC_ID);
ADDPROP(WPD_OBJECT_ISSYSTEM); ADDPROP(WPD_OBJECT_ISSYSTEM);
ADDPROP(WPD_OBJECT_ISHIDDEN); ADDPROP(WPD_OBJECT_ISHIDDEN);
@ -92,8 +93,9 @@ static void set_properties(PyObject *obj, IPortableDeviceValues *values) {
set_content_type_property(obj, values); set_content_type_property(obj, values);
set_string_property(obj, WPD_OBJECT_PARENT_ID, "parent_id", values); set_string_property(obj, WPD_OBJECT_PARENT_ID, "parent_id", values);
set_string_property(obj, WPD_OBJECT_NAME, "name", values); set_string_property(obj, WPD_OBJECT_NAME, "nominal_name", values);
// set_string_property(obj, WPD_OBJECT_SYNC_ID, "sync_id", values); // set_string_property(obj, WPD_OBJECT_SYNC_ID, "sync_id", values);
set_string_property(obj, WPD_OBJECT_ORIGINAL_FILE_NAME, "name", values);
set_string_property(obj, WPD_OBJECT_PERSISTENT_UNIQUE_ID, "persistent_id", values); set_string_property(obj, WPD_OBJECT_PERSISTENT_UNIQUE_ID, "persistent_id", values);
set_bool_property(obj, WPD_OBJECT_ISHIDDEN, "is_hidden", values); set_bool_property(obj, WPD_OBJECT_ISHIDDEN, "is_hidden", values);
@ -370,6 +372,37 @@ end:
} }
// }}} // }}}
static IPortableDeviceValues* create_object_properties(const wchar_t *parent_id, const wchar_t *name, const GUID content_type) { // {{{
IPortableDeviceValues *values = NULL;
HRESULT hr;
BOOL ok = FALSE;
hr = CoCreateInstance(CLSID_PortableDeviceValues, NULL,
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&values));
if (FAILED(hr)) { hresult_set_exc("Failed to create values interface", hr); goto end; }
hr = values->SetStringValue(WPD_OBJECT_PARENT_ID, parent_id);
if (FAILED(hr)) { hresult_set_exc("Failed to set parent_id value", hr); goto end; }
hr = values->SetStringValue(WPD_OBJECT_NAME, name);
if (FAILED(hr)) { hresult_set_exc("Failed to set name value", hr); goto end; }
hr = values->SetStringValue(WPD_OBJECT_ORIGINAL_FILE_NAME, name);
if (FAILED(hr)) { hresult_set_exc("Failed to set original_file_name value", hr); goto end; }
hr = values->SetGuidValue(WPD_OBJECT_FORMAT, WPD_OBJECT_FORMAT_UNSPECIFIED);
if (FAILED(hr)) { hresult_set_exc("Failed to set object_format value", hr); goto end; }
hr = values->SetGuidValue(WPD_OBJECT_CONTENT_TYPE, content_type);
if (FAILED(hr)) { hresult_set_exc("Failed to set content_type value", hr); goto end; }
ok = TRUE;
end:
if (!ok && values != NULL) { values->Release(); values = NULL; }
return values;
} // }}}
PyObject* wpd::get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties) { // {{{ PyObject* wpd::get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties) { // {{{
PyObject *folders = NULL; PyObject *folders = NULL;
IPortableDevicePropVariantCollection *object_ids = NULL; IPortableDevicePropVariantCollection *object_ids = NULL;
@ -500,4 +533,43 @@ end:
Py_RETURN_NONE; Py_RETURN_NONE;
} // }}} } // }}}
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;
PyObject *ans = NULL;
HRESULT hr;
wchar_t *newid = NULL;
values = create_object_properties(parent_id, name, WPD_CONTENT_TYPE_FOLDER);
if (values == NULL) goto end;
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; }
hr = content->Properties(&devprops);
if (FAILED(hr)) { hresult_set_exc("Failed to get IPortableDeviceProperties interface", hr); goto end; }
properties = create_filesystem_properties_collection();
if (properties == NULL) goto end;
Py_BEGIN_ALLOW_THREADS;
hr = content->CreateObjectWithPropertiesOnly(values, &newid);
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;
} // }}}
} // namespace wpd } // namespace wpd

View File

@ -103,6 +103,20 @@ py_get_file(Device *self, PyObject *args, PyObject *kwargs) {
return wpd::get_file(self->device, object, stream, callback); return wpd::get_file(self->device, object, stream, callback);
} // }}} } // }}}
// create_folder() {{{
static PyObject*
py_create_folder(Device *self, PyObject *args, PyObject *kwargs) {
PyObject *pparent_id, *pname;
wchar_t *parent_id, *name;
if (!PyArg_ParseTuple(args, "OO", &pparent_id, &pname)) return NULL;
parent_id = unicode_to_wchar(pparent_id);
name = unicode_to_wchar(pname);
if (parent_id == NULL || name == NULL) return NULL;
return wpd::create_folder(self->device, parent_id, name);
} // }}}
static PyMethodDef Device_methods[] = { static PyMethodDef Device_methods[] = {
{"update_data", (PyCFunction)update_data, METH_VARARGS, {"update_data", (PyCFunction)update_data, METH_VARARGS,
"update_data() -> Reread the basic device data from the device (total, space, free space, storage locations, etc.)" "update_data() -> Reread the basic device data from the device (total, space, free space, storage locations, etc.)"
@ -116,6 +130,10 @@ static PyMethodDef Device_methods[] = {
"get_file(object_id, stream, callback=None) -> Get the file identified by object_id from the device. The file is written to the stream object, which must be a file like object. If callback is not None, it must be a callable that accepts two arguments: (bytes_read, total_size). It will be called after each chunk is read from the device. Note that it can be called multiple times with the same values." "get_file(object_id, stream, callback=None) -> Get the file identified by object_id from the device. The file is written to the stream object, which must be a file like object. If callback is not None, it must be a callable that accepts two arguments: (bytes_read, total_size). It will be called after each chunk is read from the device. Note that it can be called multiple times with the same values."
}, },
{"create_folder", (PyCFunction)py_create_folder, METH_VARARGS,
"create_folder(parent_id, name) -> Create a folder. Returns the folder metadata."
},
{NULL} {NULL}
}; };

View File

@ -58,6 +58,7 @@ extern IPortableDevice* open_device(const wchar_t *pnp_id, IPortableDeviceValues
extern PyObject* get_device_information(IPortableDevice *device, IPortableDevicePropertiesBulk **bulk_properties); extern PyObject* get_device_information(IPortableDevice *device, IPortableDevicePropertiesBulk **bulk_properties);
extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties); extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties);
extern PyObject* get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest, PyObject *callback); extern PyObject* get_file(IPortableDevice *device, const wchar_t *object_id, PyObject *dest, PyObject *callback);
extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name);
} }

View File

@ -71,12 +71,16 @@ def main():
print ('Total space', dev.total_space()) print ('Total space', dev.total_space())
print ('Free space', dev.free_space()) print ('Free space', dev.free_space())
dev.filesystem_cache.dump() dev.filesystem_cache.dump()
# pprint.pprint(dev.dev.create_folder(dev.filesystem_cache.entries[0].object_id,
# 'zzz'))
# print ('Fetching file: oFF (198214 bytes)') # print ('Fetching file: oFF (198214 bytes)')
# stream = dev.get_file('oFF') # stream = dev.get_file('oFF')
# print ("Fetched size: ", stream.tell()) # print ("Fetched size: ", stream.tell())
finally: finally:
dev.shutdown() dev.shutdown()
print ('Device connection shutdown')
if __name__ == '__main__': if __name__ == '__main__':
main() main()