mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-06-23 15:30:45 -04:00
Use RAII for get_storage_info()
This commit is contained in:
parent
014f7fe82a
commit
d7150a4b86
@ -45,13 +45,13 @@ IPortableDeviceValues *get_client_information() { // {{{
|
|||||||
return client_information.Detach();
|
return client_information.Detach();
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
IPortableDevice *open_device(const wchar_t *pnp_id, CComPtr<IPortableDeviceValues> &client_information) { // {{{
|
IPortableDevice*
|
||||||
IPortableDevice *device = NULL;
|
open_device(const wchar_t *pnp_id, CComPtr<IPortableDeviceValues> &client_information) { // {{{
|
||||||
|
CComPtr<IPortableDevice> device;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = CoCreateInstance(CLSID_PortableDevice, NULL, CLSCTX_INPROC_SERVER,
|
hr = device.CoCreateInstance(CLSID_PortableDevice, NULL, CLSCTX_INPROC_SERVER);
|
||||||
IID_PPV_ARGS(&device));
|
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (FAILED(hr)) { hresult_set_exc("Failed to create IPortableDevice", hr); device = NULL; }
|
if (FAILED(hr)) { hresult_set_exc("Failed to create IPortableDevice", hr); device = NULL; }
|
||||||
else {
|
else {
|
||||||
@ -60,82 +60,80 @@ IPortableDevice *open_device(const wchar_t *pnp_id, CComPtr<IPortableDeviceValue
|
|||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if FAILED(hr) {
|
if FAILED(hr) {
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
device->Release();
|
device.Release();
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
device = NULL;
|
|
||||||
hresult_set_exc((hr == E_ACCESSDENIED) ? "Read/write access to device is denied": "Failed to open device", hr);
|
hresult_set_exc((hr == E_ACCESSDENIED) ? "Read/write access to device is denied": "Failed to open device", hr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return device;
|
return device.Detach();
|
||||||
|
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
PyObject* get_storage_info(IPortableDevice *device) { // {{{
|
static PyObject*
|
||||||
|
get_storage_info(IPortableDevice *device) { // {{{
|
||||||
HRESULT hr, hr2;
|
HRESULT hr, hr2;
|
||||||
IPortableDeviceContent *content = NULL;
|
CComPtr<IPortableDeviceContent> content = NULL;
|
||||||
IEnumPortableDeviceObjectIDs *objects = NULL;
|
CComPtr<IEnumPortableDeviceObjectIDs> objects = NULL;
|
||||||
IPortableDeviceProperties *properties = NULL;
|
CComPtr<IPortableDeviceProperties> properties = NULL;
|
||||||
IPortableDeviceKeyCollection *storage_properties = NULL;
|
CComPtr<IPortableDeviceKeyCollection> storage_properties = NULL;
|
||||||
IPortableDeviceValues *values = NULL;
|
|
||||||
PyObject *ans = NULL, *storage = NULL, *so = NULL, *desc = NULL, *soid = NULL;
|
|
||||||
DWORD fetched, i;
|
DWORD fetched, i;
|
||||||
PWSTR object_ids[10];
|
|
||||||
GUID guid;
|
GUID guid;
|
||||||
ULONGLONG capacity, free_space, capacity_objects, free_objects;
|
ULONGLONG capacity, free_space, capacity_objects, free_objects;
|
||||||
ULONG access, storage_type = WPD_STORAGE_TYPE_UNDEFINED;
|
ULONG access, storage_type = WPD_STORAGE_TYPE_UNDEFINED;
|
||||||
LPWSTR storage_desc = NULL, st = NULL;
|
|
||||||
|
|
||||||
storage = PyList_New(0);
|
pyobject_raii storage(PyList_New(0));
|
||||||
if (storage == NULL) { PyErr_NoMemory(); goto end; }
|
if (!storage) return NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = device->Content(&content);
|
hr = device->Content(&content);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to get content interface from device", hr); goto end;}
|
if (FAILED(hr)) {hresult_set_exc("Failed to get content interface from device", hr); return NULL;}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = content->Properties(&properties);
|
hr = content->Properties(&properties);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to get properties interface", hr); goto end;}
|
if (FAILED(hr)) {hresult_set_exc("Failed to get properties interface", hr); return NULL;}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL,
|
hr = storage_properties.CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER);
|
||||||
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&storage_properties));
|
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to create storage properties collection", hr); goto end;}
|
if (FAILED(hr)) {hresult_set_exc("Failed to create storage properties collection", hr); return NULL;}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
#define A(what) hr = storage_properties->Add(what); if (FAILED(hr)) { hresult_set_exc("Failed to add storage property " #what " for storage query", hr); return NULL; }
|
||||||
hr = storage_properties->Add(WPD_OBJECT_CONTENT_TYPE);
|
A(WPD_OBJECT_CONTENT_TYPE);
|
||||||
hr = storage_properties->Add(WPD_FUNCTIONAL_OBJECT_CATEGORY);
|
A(WPD_FUNCTIONAL_OBJECT_CATEGORY);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_DESCRIPTION);
|
A(WPD_STORAGE_DESCRIPTION);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_CAPACITY);
|
A(WPD_STORAGE_CAPACITY);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_CAPACITY_IN_OBJECTS);
|
A(WPD_STORAGE_CAPACITY_IN_OBJECTS);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_FREE_SPACE_IN_BYTES);
|
A(WPD_STORAGE_FREE_SPACE_IN_BYTES);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_FREE_SPACE_IN_OBJECTS);
|
A(WPD_STORAGE_FREE_SPACE_IN_OBJECTS);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_ACCESS_CAPABILITY);
|
A(WPD_STORAGE_ACCESS_CAPABILITY);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_FILE_SYSTEM_TYPE);
|
A(WPD_STORAGE_FILE_SYSTEM_TYPE);
|
||||||
hr = storage_properties->Add(WPD_STORAGE_TYPE);
|
A(WPD_STORAGE_TYPE);
|
||||||
hr = storage_properties->Add(WPD_OBJECT_NAME);
|
A(WPD_OBJECT_NAME);
|
||||||
Py_END_ALLOW_THREADS;
|
#undef A
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to create collection of properties for storage query", hr); goto end; }
|
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = content->EnumObjects(0, WPD_DEVICE_OBJECT_ID, NULL, &objects);
|
hr = content->EnumObjects(0, WPD_DEVICE_OBJECT_ID, NULL, &objects);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to get objects from device", hr); goto end;}
|
if (FAILED(hr)) {hresult_set_exc("Failed to get objects from device", hr); return NULL;}
|
||||||
|
|
||||||
hr = S_OK;
|
hr = S_OK;
|
||||||
while (hr == S_OK) {
|
while (hr == S_OK) {
|
||||||
|
wchar_t* object_ids[16] = {0};
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = objects->Next(10, object_ids, &fetched);
|
hr = objects->Next(arraysz(object_ids), object_ids, &fetched);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr)) {
|
||||||
|
com_wchar_raii cleanup[arraysz(object_ids)];
|
||||||
|
for (i = 0; i < arraysz(object_ids); i++) { cleanup[i].set_ptr(object_ids[i]); };
|
||||||
for(i = 0; i < fetched; i++) {
|
for(i = 0; i < fetched; i++) {
|
||||||
|
CComPtr<IPortableDeviceValues> values;
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr2 = properties->GetValues(object_ids[i], storage_properties, &values);
|
hr2 = properties->GetValues(object_ids[i], storage_properties, &values);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if SUCCEEDED(hr2) {
|
if (SUCCEEDED(hr2)) {
|
||||||
if (
|
if (
|
||||||
SUCCEEDED(values->GetGuidValue(WPD_OBJECT_CONTENT_TYPE, &guid)) && IsEqualGUID(guid, WPD_CONTENT_TYPE_FUNCTIONAL_OBJECT) &&
|
SUCCEEDED(values->GetGuidValue(WPD_OBJECT_CONTENT_TYPE, &guid)) && IsEqualGUID(guid, WPD_CONTENT_TYPE_FUNCTIONAL_OBJECT) &&
|
||||||
SUCCEEDED(values->GetGuidValue(WPD_FUNCTIONAL_OBJECT_CATEGORY, &guid)) && IsEqualGUID(guid, WPD_FUNCTIONAL_CATEGORY_STORAGE)
|
SUCCEEDED(values->GetGuidValue(WPD_FUNCTIONAL_OBJECT_CATEGORY, &guid)) && IsEqualGUID(guid, WPD_FUNCTIONAL_CATEGORY_STORAGE)
|
||||||
@ -146,28 +144,23 @@ PyObject* get_storage_info(IPortableDevice *device) { // {{{
|
|||||||
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_BYTES, &free_space);
|
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_BYTES, &free_space);
|
||||||
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_OBJECTS, &free_objects);
|
values->GetUnsignedLargeIntegerValue(WPD_STORAGE_FREE_SPACE_IN_OBJECTS, &free_objects);
|
||||||
values->GetUnsignedIntegerValue(WPD_STORAGE_TYPE, &storage_type);
|
values->GetUnsignedIntegerValue(WPD_STORAGE_TYPE, &storage_type);
|
||||||
desc = Py_False;
|
PyObject *paccess = Py_False;
|
||||||
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_STORAGE_ACCESS_CAPABILITY, &access)) && access == WPD_STORAGE_ACCESS_CAPABILITY_READWRITE) desc = Py_True;
|
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_STORAGE_ACCESS_CAPABILITY, &access)) && access == WPD_STORAGE_ACCESS_CAPABILITY_READWRITE) paccess = Py_True;
|
||||||
soid = PyUnicode_FromWideChar(object_ids[i], wcslen(object_ids[i]));
|
pyobject_raii soid(PyUnicode_FromWideChar(object_ids[i], -1));
|
||||||
if (soid == NULL) { PyErr_NoMemory(); goto end; }
|
if (!soid) return NULL;
|
||||||
so = Py_BuildValue("{s:K, s:K, s:K, s:K, s:O, s:N}",
|
pyobject_raii so(Py_BuildValue("{s:K, s:K, s:K, s:K, s:O, s:O}",
|
||||||
"capacity", capacity, "capacity_objects", capacity_objects, "free_space", free_space, "free_objects", free_objects, "rw", desc, "id", soid);
|
"capacity", capacity, "capacity_objects", capacity_objects, "free_space", free_space, "free_objects", free_objects, "rw", paccess, "id", soid.ptr()));
|
||||||
if (so == NULL) { PyErr_NoMemory(); goto end; }
|
if (!so) return NULL;
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_STORAGE_DESCRIPTION, &storage_desc))) {
|
#define A(which, key) { com_wchar_raii buf; if (SUCCEEDED(values->GetStringValue(which, buf.address()))) { \
|
||||||
desc = PyUnicode_FromWideChar(storage_desc, wcslen(storage_desc));
|
pyobject_raii d(PyUnicode_FromWideChar(buf.ptr(), -1)); \
|
||||||
if (desc != NULL) { PyDict_SetItemString(so, "description", desc); Py_DECREF(desc);}
|
if (d) PyDict_SetItemString(so.ptr(), key, d.ptr()); \
|
||||||
CoTaskMemFree(storage_desc); storage_desc = NULL;
|
else PyErr_Clear(); \
|
||||||
}
|
}}
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_OBJECT_NAME, &storage_desc))) {
|
A(WPD_STORAGE_DESCRIPTION, "description");
|
||||||
desc = PyUnicode_FromWideChar(storage_desc, wcslen(storage_desc));
|
A(WPD_OBJECT_NAME, "name");
|
||||||
if (desc != NULL) { PyDict_SetItemString(so, "name", desc); Py_DECREF(desc);}
|
A(WPD_STORAGE_FILE_SYSTEM_TYPE, "filesystem");
|
||||||
CoTaskMemFree(storage_desc); storage_desc = NULL;
|
#undef A
|
||||||
}
|
const wchar_t *st;
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_STORAGE_FILE_SYSTEM_TYPE, &storage_desc))) {
|
|
||||||
desc = PyUnicode_FromWideChar(storage_desc, wcslen(storage_desc));
|
|
||||||
if (desc != NULL) { PyDict_SetItemString(so, "filesystem", desc); Py_DECREF(desc);}
|
|
||||||
CoTaskMemFree(storage_desc); storage_desc = NULL;
|
|
||||||
}
|
|
||||||
switch(storage_type) {
|
switch(storage_type) {
|
||||||
case WPD_STORAGE_TYPE_REMOVABLE_RAM:
|
case WPD_STORAGE_TYPE_REMOVABLE_RAM:
|
||||||
st = L"removable_ram";
|
st = L"removable_ram";
|
||||||
@ -184,26 +177,15 @@ PyObject* get_storage_info(IPortableDevice *device) { // {{{
|
|||||||
default:
|
default:
|
||||||
st = L"unknown_unknown";
|
st = L"unknown_unknown";
|
||||||
}
|
}
|
||||||
desc = PyUnicode_FromWideChar(st, wcslen(st));
|
pyobject_raii dt(PyUnicode_FromWideChar(st, -1));
|
||||||
if (desc != NULL) {PyDict_SetItemString(so, "type", desc); Py_DECREF(desc);}
|
if (dt) PyDict_SetItemString(so.ptr(), "type", dt.ptr());
|
||||||
desc = NULL;
|
if (PyList_Append(storage.ptr(), so.ptr()) != 0) return NULL;
|
||||||
PyList_Append(storage, so);
|
|
||||||
Py_DECREF(so);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (i = 0; i < fetched; i ++) { CoTaskMemFree(object_ids[i]); object_ids[i] = NULL;}
|
|
||||||
}// if(SUCCEEDED(hr))
|
}// if(SUCCEEDED(hr))
|
||||||
}
|
}
|
||||||
ans = storage;
|
return storage.detach();
|
||||||
|
|
||||||
end:
|
|
||||||
if (content != NULL) content->Release();
|
|
||||||
if (objects != NULL) objects->Release();
|
|
||||||
if (properties != NULL) properties->Release();
|
|
||||||
if (storage_properties != NULL) storage_properties->Release();
|
|
||||||
if (values != NULL) values->Release();
|
|
||||||
return ans;
|
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
@ -219,7 +201,7 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
DWORD num_of_categories, i;
|
DWORD num_of_categories, i;
|
||||||
LPWSTR temp;
|
LPWSTR temp;
|
||||||
ULONG ti;
|
ULONG ti;
|
||||||
PyObject *t, *ans = NULL, *storage = NULL;
|
PyObject *t, *ans = NULL;
|
||||||
const char *type = NULL;
|
const char *type = NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
@ -286,6 +268,7 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_DEVICE_TYPE, &ti))) {
|
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_DEVICE_TYPE, &ti))) {
|
||||||
|
type = "unknown";
|
||||||
switch (ti) {
|
switch (ti) {
|
||||||
case WPD_DEVICE_TYPE_CAMERA:
|
case WPD_DEVICE_TYPE_CAMERA:
|
||||||
type = "camera"; break;
|
type = "camera"; break;
|
||||||
@ -299,8 +282,8 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
type = "personal information manager"; break;
|
type = "personal information manager"; break;
|
||||||
case WPD_DEVICE_TYPE_AUDIO_RECORDER:
|
case WPD_DEVICE_TYPE_AUDIO_RECORDER:
|
||||||
type = "audio recorder"; break;
|
type = "audio recorder"; break;
|
||||||
default:
|
case WPD_DEVICE_TYPE_GENERIC:
|
||||||
type = "unknown";
|
break;
|
||||||
}
|
}
|
||||||
t = PyUnicode_FromString(type);
|
t = PyUnicode_FromString(type);
|
||||||
if (t != NULL) {
|
if (t != NULL) {
|
||||||
@ -353,20 +336,19 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
PyDict_SetItemString(ans, "has_storage", t);
|
PyDict_SetItemString(ans, "has_storage", t);
|
||||||
|
|
||||||
if (t == Py_True) {
|
if (t == Py_True) {
|
||||||
storage = get_storage_info(device);
|
pyobject_raii storage(get_storage_info(device));
|
||||||
if (storage == NULL) {
|
if (!storage) {
|
||||||
PyObject *exc_type, *exc_value, *exc_tb;
|
pyobject_raii exc_type, exc_value, exc_tb;
|
||||||
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
PyErr_Fetch(exc_type.address(), exc_value.address(), exc_tb.address());
|
||||||
if (exc_type != NULL && exc_value != NULL) {
|
if (exc_type) {
|
||||||
PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
|
PyErr_NormalizeException(exc_type.address(), exc_value.address(), exc_tb.address());
|
||||||
PyDict_SetItemString(ans, "storage_error", exc_value);
|
PyDict_SetItemString(ans, "storage_error", exc_value.ptr());
|
||||||
Py_DECREF(exc_value); exc_value = NULL;
|
} else {
|
||||||
}
|
PyDict_SetItemString(ans, "storage_error", PyUnicode_FromString("get_storage_info() failed without an error set"));
|
||||||
Py_XDECREF(exc_type); Py_XDECREF(exc_value); Py_XDECREF(exc_tb);
|
}
|
||||||
goto end;
|
} else {
|
||||||
}
|
PyDict_SetItemString(ans, "storage", storage.ptr());
|
||||||
PyDict_SetItemString(ans, "storage", storage);
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
|
@ -45,7 +45,9 @@ class wchar_raii {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *ptr() { return handle; }
|
wchar_t *ptr() { return handle; }
|
||||||
|
wchar_t *detach() { wchar_t *ans = handle; handle = NULL; return ans; }
|
||||||
void set_ptr(wchar_t *val) { handle = val; }
|
void set_ptr(wchar_t *val) { handle = val; }
|
||||||
|
wchar_t **address() { return &handle; }
|
||||||
explicit operator bool() const { return handle != NULL; }
|
explicit operator bool() const { return handle != NULL; }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,6 +69,8 @@ class com_wchar_raii {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wchar_t *ptr() { return handle; }
|
wchar_t *ptr() { return handle; }
|
||||||
|
void set_ptr(wchar_t *val) { handle = val; }
|
||||||
|
wchar_t *detach() { wchar_t *ans = handle; handle = NULL; return ans; }
|
||||||
wchar_t **address() { return &handle; }
|
wchar_t **address() { return &handle; }
|
||||||
explicit operator bool() const { return handle != NULL; }
|
explicit operator bool() const { return handle != NULL; }
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user