mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Use RAII for get_device_information
Also the function to set an error from an hresult must return NULL
This commit is contained in:
parent
13d7f3e5d9
commit
2452fbc928
@ -37,12 +37,8 @@ init(Device *self, PyObject *args, PyObject *kwds)
|
|||||||
if (client_information) {
|
if (client_information) {
|
||||||
self->device = open_device(self->pnp_id.ptr(), client_information);
|
self->device = open_device(self->pnp_id.ptr(), client_information);
|
||||||
if (self->device) {
|
if (self->device) {
|
||||||
IPortableDevicePropertiesBulk *bulk_properties = NULL;
|
self->device_information = get_device_information(self->device, self->bulk_properties);
|
||||||
self->device_information = get_device_information(self->device, &bulk_properties);
|
if (self->device_information) ret = 0;
|
||||||
if (self->device_information) {
|
|
||||||
ret = 0;
|
|
||||||
self->bulk_properties = bulk_properties;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
@ -54,7 +50,8 @@ init(Device *self, PyObject *args, PyObject *kwds)
|
|||||||
static PyObject*
|
static PyObject*
|
||||||
update_data(Device *self, PyObject *args) {
|
update_data(Device *self, PyObject *args) {
|
||||||
PyObject *di = NULL;
|
PyObject *di = NULL;
|
||||||
di = get_device_information(self->device, NULL);
|
CComPtr<IPortableDevicePropertiesBulk> bulk_properties;
|
||||||
|
di = get_device_information(self->device, bulk_properties);
|
||||||
if (di == NULL) return NULL;
|
if (di == NULL) return NULL;
|
||||||
Py_XDECREF(self->device_information); self->device_information = di;
|
Py_XDECREF(self->device_information); self->device_information = di;
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
@ -189,83 +189,77 @@ get_storage_info(IPortableDevice *device) { // {{{
|
|||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
PyObject*
|
PyObject*
|
||||||
get_device_information(CComPtr<IPortableDevice> &device, IPortableDevicePropertiesBulk **pb) { // {{{
|
get_device_information(CComPtr<IPortableDevice> &device, CComPtr<IPortableDevicePropertiesBulk> &pb) { // {{{
|
||||||
IPortableDeviceContent *content = NULL;
|
CComPtr<IPortableDeviceContent> content = NULL;
|
||||||
IPortableDeviceProperties *properties = NULL;
|
CComPtr<IPortableDeviceProperties> properties = NULL;
|
||||||
IPortableDevicePropertiesBulk *properties_bulk = NULL;
|
CComPtr<IPortableDeviceKeyCollection> keys = NULL;
|
||||||
IPortableDeviceKeyCollection *keys = NULL;
|
CComPtr<IPortableDeviceValues> values = NULL;
|
||||||
IPortableDeviceValues *values = NULL;
|
CComPtr<IPortableDeviceCapabilities> capabilities = NULL;
|
||||||
IPortableDeviceCapabilities *capabilities = NULL;
|
CComPtr<IPortableDevicePropVariantCollection> categories = NULL;
|
||||||
IPortableDevicePropVariantCollection *categories = NULL;
|
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
DWORD num_of_categories, i;
|
DWORD num_of_categories, i;
|
||||||
LPWSTR temp;
|
|
||||||
ULONG ti;
|
ULONG ti;
|
||||||
PyObject *t, *ans = NULL;
|
PyObject *ans = NULL;
|
||||||
const char *type = NULL;
|
const char *type = NULL;
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL,
|
hr = keys.CoCreateInstance(CLSID_PortableDeviceKeyCollection, NULL, CLSCTX_INPROC_SERVER);
|
||||||
CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&keys));
|
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to create IPortableDeviceKeyCollection", hr); goto end;}
|
if (FAILED(hr)) return hresult_set_exc("Failed to create IPortableDeviceKeyCollection", hr);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
#define A(what) hr = keys->Add(what); if (FAILED(hr)) { return hresult_set_exc("Failed to add key " #what " to IPortableDeviceKeyCollection", hr); }
|
||||||
hr = keys->Add(WPD_DEVICE_PROTOCOL);
|
A(WPD_DEVICE_PROTOCOL);
|
||||||
// Despite the MSDN documentation, this does not exist in PortableDevice.h
|
// Despite the MSDN documentation, this does not exist in PortableDevice.h
|
||||||
// hr = keys->Add(WPD_DEVICE_TRANSPORT);
|
// hr = keys->Add(WPD_DEVICE_TRANSPORT);
|
||||||
hr = keys->Add(WPD_DEVICE_FRIENDLY_NAME);
|
A(WPD_DEVICE_FRIENDLY_NAME);
|
||||||
hr = keys->Add(WPD_DEVICE_MANUFACTURER);
|
A(WPD_DEVICE_MANUFACTURER);
|
||||||
hr = keys->Add(WPD_DEVICE_MODEL);
|
A(WPD_DEVICE_MODEL);
|
||||||
hr = keys->Add(WPD_DEVICE_SERIAL_NUMBER);
|
A(WPD_DEVICE_SERIAL_NUMBER);
|
||||||
hr = keys->Add(WPD_DEVICE_FIRMWARE_VERSION);
|
A(WPD_DEVICE_FIRMWARE_VERSION);
|
||||||
hr = keys->Add(WPD_DEVICE_TYPE);
|
A(WPD_DEVICE_TYPE);
|
||||||
Py_END_ALLOW_THREADS;
|
#undef A
|
||||||
if (FAILED(hr)) {hresult_set_exc("Failed to add keys to IPortableDeviceKeyCollection", hr); goto end;}
|
|
||||||
|
|
||||||
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 IPortableDeviceContent", hr); goto end; }
|
if (FAILED(hr)) return hresult_set_exc("Failed to get IPortableDeviceContent", hr);
|
||||||
|
|
||||||
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 IPortableDeviceProperties", hr); goto end; }
|
if (FAILED(hr)) return hresult_set_exc("Failed to get IPortableDeviceProperties", hr);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = properties->GetValues(WPD_DEVICE_OBJECT_ID, keys, &values);
|
hr = properties->GetValues(WPD_DEVICE_OBJECT_ID, keys, &values);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if(FAILED(hr)) {hresult_set_exc("Failed to get device info", hr); goto end; }
|
if(FAILED(hr)) return hresult_set_exc("Failed to get device info", hr);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = device->Capabilities(&capabilities);
|
hr = device->Capabilities(&capabilities);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if(FAILED(hr)) {hresult_set_exc("Failed to get device capabilities", hr); goto end; }
|
if(FAILED(hr)) return hresult_set_exc("Failed to get device capabilities", hr);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = capabilities->GetFunctionalCategories(&categories);
|
hr = capabilities->GetFunctionalCategories(&categories);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if(FAILED(hr)) {hresult_set_exc("Failed to get device functional categories", hr); goto end; }
|
if(FAILED(hr)) return hresult_set_exc("Failed to get device functional categories", hr);
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = categories->GetCount(&num_of_categories);
|
hr = categories->GetCount(&num_of_categories);
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
if(FAILED(hr)) {hresult_set_exc("Failed to get device functional categories number", hr); goto end; }
|
if(FAILED(hr)) return hresult_set_exc("Failed to get device functional categories number", hr);
|
||||||
|
|
||||||
ans = PyDict_New();
|
ans = PyDict_New();
|
||||||
if (ans == NULL) {PyErr_NoMemory(); goto end;}
|
if (ans == NULL) return NULL;
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_DEVICE_PROTOCOL, &temp))) {
|
#define S(what, key) { \
|
||||||
t = PyUnicode_FromWideChar(temp, wcslen(temp));
|
com_wchar_raii temp; \
|
||||||
if (t != NULL) {PyDict_SetItemString(ans, "protocol", t); Py_DECREF(t);}
|
if (SUCCEEDED(values->GetStringValue(what, &temp))) { \
|
||||||
CoTaskMemFree(temp);
|
pyobject_raii t(PyUnicode_FromWideChar(temp.ptr(), -1)); \
|
||||||
}
|
if (t) if (PyDict_SetItemString(ans, key, t.ptr()) != 0) PyErr_Clear(); \
|
||||||
|
}}
|
||||||
|
|
||||||
// if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_DEVICE_TRANSPORT, &ti))) {
|
S(WPD_DEVICE_PROTOCOL, "protocol");
|
||||||
// PyDict_SetItemString(ans, "isusb", (ti == WPD_DEVICE_TRANSPORT_USB) ? Py_True : Py_False);
|
|
||||||
// t = PyLong_FromUnsignedLong(ti);
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_DEVICE_TYPE, &ti))) {
|
if (SUCCEEDED(values->GetUnsignedIntegerValue(WPD_DEVICE_TYPE, &ti))) {
|
||||||
type = "unknown";
|
type = "unknown";
|
||||||
@ -285,57 +279,29 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
case WPD_DEVICE_TYPE_GENERIC:
|
case WPD_DEVICE_TYPE_GENERIC:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t = PyUnicode_FromString(type);
|
pyobject_raii t(PyUnicode_FromString(type));
|
||||||
if (t != NULL) {
|
if (t) PyDict_SetItemString(ans, "type", t.ptr());
|
||||||
PyDict_SetItemString(ans, "type", t); Py_DECREF(t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_DEVICE_FRIENDLY_NAME, &temp))) {
|
S(WPD_DEVICE_FRIENDLY_NAME, "friendly_name");
|
||||||
t = PyUnicode_FromWideChar(temp, wcslen(temp));
|
S(WPD_DEVICE_MANUFACTURER, "manufacturer_name");
|
||||||
if (t != NULL) {PyDict_SetItemString(ans, "friendly_name", t); Py_DECREF(t);}
|
S(WPD_DEVICE_MODEL, "model_name");
|
||||||
CoTaskMemFree(temp);
|
S(WPD_DEVICE_SERIAL_NUMBER, "serial_number");
|
||||||
}
|
S(WPD_DEVICE_FIRMWARE_VERSION, "device_version");
|
||||||
|
#undef S
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_DEVICE_MANUFACTURER, &temp))) {
|
bool has_storage = false;
|
||||||
t = PyUnicode_FromWideChar(temp, wcslen(temp));
|
for (i = 0; i < num_of_categories && !has_storage; i++) {
|
||||||
if (t != NULL) {PyDict_SetItemString(ans, "manufacturer_name", t); Py_DECREF(t);}
|
|
||||||
CoTaskMemFree(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_DEVICE_MODEL, &temp))) {
|
|
||||||
t = PyUnicode_FromWideChar(temp, wcslen(temp));
|
|
||||||
if (t != NULL) {PyDict_SetItemString(ans, "model_name", t); Py_DECREF(t);}
|
|
||||||
CoTaskMemFree(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_DEVICE_SERIAL_NUMBER, &temp))) {
|
|
||||||
t = PyUnicode_FromWideChar(temp, wcslen(temp));
|
|
||||||
if (t != NULL) {PyDict_SetItemString(ans, "serial_number", t); Py_DECREF(t);}
|
|
||||||
CoTaskMemFree(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SUCCEEDED(values->GetStringValue(WPD_DEVICE_FIRMWARE_VERSION, &temp))) {
|
|
||||||
t = PyUnicode_FromWideChar(temp, wcslen(temp));
|
|
||||||
if (t != NULL) {PyDict_SetItemString(ans, "device_version", t); Py_DECREF(t);}
|
|
||||||
CoTaskMemFree(temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
t = Py_False;
|
|
||||||
for (i = 0; i < num_of_categories; i++) {
|
|
||||||
PROPVARIANT pv;
|
PROPVARIANT pv;
|
||||||
PropVariantInit(&pv);
|
PropVariantInit(&pv);
|
||||||
if (SUCCEEDED(categories->GetAt(i, &pv)) && pv.puuid != NULL) {
|
if (SUCCEEDED(categories->GetAt(i, &pv)) && pv.puuid != NULL) {
|
||||||
if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_STORAGE, *pv.puuid)) {
|
if (IsEqualGUID(WPD_FUNCTIONAL_CATEGORY_STORAGE, *pv.puuid)) has_storage = true;
|
||||||
t = Py_True;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
PropVariantClear(&pv);
|
PropVariantClear(&pv);
|
||||||
if (t == Py_True) break;
|
|
||||||
}
|
}
|
||||||
PyDict_SetItemString(ans, "has_storage", t);
|
PyDict_SetItemString(ans, "has_storage", has_storage ? Py_True : Py_False);
|
||||||
|
|
||||||
if (t == Py_True) {
|
if (has_storage) {
|
||||||
pyobject_raii storage(get_storage_info(device));
|
pyobject_raii storage(get_storage_info(device));
|
||||||
if (!storage) {
|
if (!storage) {
|
||||||
pyobject_raii exc_type, exc_value, exc_tb;
|
pyobject_raii exc_type, exc_value, exc_tb;
|
||||||
@ -344,7 +310,8 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
|
PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
|
||||||
PyDict_SetItemString(ans, "storage_error", exc_value.ptr());
|
PyDict_SetItemString(ans, "storage_error", exc_value.ptr());
|
||||||
} else {
|
} else {
|
||||||
PyDict_SetItemString(ans, "storage_error", PyUnicode_FromString("get_storage_info() failed without an error set"));
|
pyobject_raii t(PyUnicode_FromString("get_storage_info() failed without an error set"));
|
||||||
|
if (t) PyDict_SetItemString(ans, "storage_error", t.ptr());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PyDict_SetItemString(ans, "storage", storage.ptr());
|
PyDict_SetItemString(ans, "storage", storage.ptr());
|
||||||
@ -352,19 +319,9 @@ get_device_information(CComPtr<IPortableDevice> &device, IPortableDeviceProperti
|
|||||||
}
|
}
|
||||||
|
|
||||||
Py_BEGIN_ALLOW_THREADS;
|
Py_BEGIN_ALLOW_THREADS;
|
||||||
hr = properties->QueryInterface(IID_PPV_ARGS(&properties_bulk));
|
hr = properties->QueryInterface(IID_PPV_ARGS(&pb));
|
||||||
Py_END_ALLOW_THREADS;
|
Py_END_ALLOW_THREADS;
|
||||||
PyDict_SetItemString(ans, "has_bulk_properties", (FAILED(hr)) ? Py_False: Py_True);
|
PyDict_SetItemString(ans, "has_bulk_properties", (FAILED(hr)) ? Py_False: Py_True);
|
||||||
if (pb != NULL) *pb = (SUCCEEDED(hr)) ? properties_bulk : NULL;
|
|
||||||
|
|
||||||
end:
|
|
||||||
if (keys != NULL) keys->Release();
|
|
||||||
if (values != NULL) values->Release();
|
|
||||||
if (properties != NULL) properties->Release();
|
|
||||||
if (properties_bulk != NULL && pb == NULL) properties_bulk->Release();
|
|
||||||
if (content != NULL) content->Release();
|
|
||||||
if (capabilities != NULL) capabilities->Release();
|
|
||||||
if (categories != NULL) categories->Release();
|
|
||||||
return ans;
|
return ans;
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
|
@ -47,15 +47,15 @@ typedef struct {
|
|||||||
} Device;
|
} Device;
|
||||||
extern PyTypeObject DeviceType;
|
extern PyTypeObject DeviceType;
|
||||||
|
|
||||||
// Utility functions
|
#define hresult_set_exc(msg, hr) set_error_from_hresult(wpd::WPDError, __FILE__, __LINE__, hr, msg)
|
||||||
PyObject *hresult_set_exc(const char *msg, HRESULT hr);
|
|
||||||
wchar_t *unicode_to_wchar(PyObject *o);
|
wchar_t *unicode_to_wchar(PyObject *o);
|
||||||
PyObject *wchar_to_unicode(const wchar_t *o);
|
PyObject *wchar_to_unicode(const wchar_t *o);
|
||||||
int pump_waiting_messages();
|
int pump_waiting_messages();
|
||||||
|
|
||||||
extern IPortableDeviceValues* get_client_information();
|
extern IPortableDeviceValues* get_client_information();
|
||||||
extern IPortableDevice* open_device(const wchar_t *pnp_id, CComPtr<IPortableDeviceValues> &client_information);
|
extern IPortableDevice* open_device(const wchar_t *pnp_id, CComPtr<IPortableDeviceValues> &client_information);
|
||||||
extern PyObject* get_device_information(CComPtr<IPortableDevice> &device, IPortableDevicePropertiesBulk **bulk_properties);
|
extern PyObject* get_device_information(CComPtr<IPortableDevice> &device, CComPtr<IPortableDevicePropertiesBulk> &bulk_properties);
|
||||||
extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties, PyObject *callback);
|
extern PyObject* get_filesystem(IPortableDevice *device, const wchar_t *storage_id, IPortableDevicePropertiesBulk *bulk_properties, PyObject *callback);
|
||||||
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);
|
extern PyObject* create_folder(IPortableDevice *device, const wchar_t *parent_id, const wchar_t *name);
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
|
|
||||||
using namespace wpd;
|
using namespace wpd;
|
||||||
|
|
||||||
PyObject *wpd::hresult_set_exc(const char *msg, HRESULT hr) {
|
|
||||||
return error_from_hresult(hr, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t *wpd::unicode_to_wchar(PyObject *o) {
|
wchar_t *wpd::unicode_to_wchar(PyObject *o) {
|
||||||
wchar_t *buf;
|
wchar_t *buf;
|
||||||
Py_ssize_t len;
|
Py_ssize_t len;
|
||||||
|
@ -140,7 +140,8 @@ wpd_device_info(PyObject *self, PyObject *args) {
|
|||||||
CComPtr<IPortableDeviceValues> client_information = get_client_information();
|
CComPtr<IPortableDeviceValues> client_information = get_client_information();
|
||||||
if (client_information) {
|
if (client_information) {
|
||||||
device = open_device(pnp_id.ptr(), client_information);
|
device = open_device(pnp_id.ptr(), client_information);
|
||||||
if (device) ans = get_device_information(device, NULL);
|
CComPtr<IPortableDevicePropertiesBulk> properties_bulk;
|
||||||
|
if (device) ans = get_device_information(device, properties_bulk);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device) device->Close();
|
if (device) device->Close();
|
||||||
|
@ -14,17 +14,17 @@
|
|||||||
#define arraysz(x) (sizeof(x)/sizeof(x[0]))
|
#define arraysz(x) (sizeof(x)/sizeof(x[0]))
|
||||||
|
|
||||||
static inline PyObject*
|
static inline PyObject*
|
||||||
set_error_from_hresult(const char *file, const int line, const HRESULT hr, const char *prefix="", PyObject *name=NULL) {
|
set_error_from_hresult(PyObject *exc_type, const char *file, const int line, const HRESULT hr, const char *prefix="", PyObject *name=NULL) {
|
||||||
_com_error err(hr);
|
_com_error err(hr);
|
||||||
LPCWSTR msg = err.ErrorMessage();
|
LPCWSTR msg = err.ErrorMessage();
|
||||||
PyObject *pmsg = PyUnicode_FromWideChar(msg, -1);
|
PyObject *pmsg = PyUnicode_FromWideChar(msg, -1);
|
||||||
PyObject *ans;
|
PyObject *ans;
|
||||||
if (name) ans = PyErr_Format(PyExc_OSError, "%s:%d:%s:[%li] %V: %S", file, line, prefix, hr, pmsg, "Out of memory", name);
|
if (name) ans = PyErr_Format(exc_type, "%s:%d:%s:[%li] %V: %S", file, line, prefix, hr, pmsg, "Out of memory", name);
|
||||||
else ans = PyErr_Format(PyExc_OSError, "%s:%d:%s:[%li] %V", file, line, prefix, hr, pmsg, "Out of memory");
|
else ans = PyErr_Format(exc_type, "%s:%d:%s:[%li] %V", file, line, prefix, hr, pmsg, "Out of memory");
|
||||||
Py_CLEAR(pmsg);
|
Py_CLEAR(pmsg);
|
||||||
return ans;
|
return NULL;
|
||||||
}
|
}
|
||||||
#define error_from_hresult(hr, ...) set_error_from_hresult(__FILE__, __LINE__, hr, __VA_ARGS__)
|
#define error_from_hresult(hr, ...) set_error_from_hresult(PyExc_OSError, __FILE__, __LINE__, hr, __VA_ARGS__)
|
||||||
|
|
||||||
template<typename T, void free_T(void*), T null>
|
template<typename T, void free_T(void*), T null>
|
||||||
class generic_raii {
|
class generic_raii {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user