From 630c24407c41300d48f595ef1cba252433e32ee1 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Wed, 4 Jan 2023 20:07:05 +0530 Subject: [PATCH] Wrap the newer icon extraction API --- setup/extensions.json | 2 +- .../progress_indicator/QProgressIndicator.cpp | 2 +- src/calibre/utils/windows/winutil.cpp | 39 ++++++++++++++++++- 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/setup/extensions.json b/setup/extensions.json index de58f3c201..7fc30f2683 100644 --- a/setup/extensions.json +++ b/setup/extensions.json @@ -173,7 +173,7 @@ "only": "windows", "headers": "calibre/utils/cpp_binding.h calibre/utils/windows/common.h", "sources": "calibre/utils/windows/winutil.cpp", - "libraries": "shell32 wininet advapi32", + "libraries": "shell32 wininet advapi32 gdi32", "cflags": "/X" }, { diff --git a/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp b/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp index 20472129df..af41ec457a 100644 --- a/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp +++ b/src/calibre/gui2/progress_indicator/QProgressIndicator.cpp @@ -149,7 +149,7 @@ image_from_hbitmap(void* hbitmap) { #ifdef Q_OS_WIN return QImage::fromHBITMAP((HBITMAP)hbitmap); #else - (void)hibitmap; + (void)hbitmap; return QImage(); #endif } diff --git a/src/calibre/utils/windows/winutil.cpp b/src/calibre/utils/windows/winutil.cpp index 6a64abfce0..75147eac71 100644 --- a/src/calibre/utils/windows/winutil.cpp +++ b/src/calibre/utils/windows/winutil.cpp @@ -75,7 +75,7 @@ static PyMethodDef PyGUID_methods[] = { // }}} // Handle {{{ -typedef enum { NormalHandle, ModuleHandle, IconHandle } WinHandleType; +typedef enum { NormalHandle, ModuleHandle, IconHandle, BitmapHandle } WinHandleType; typedef struct { PyObject_HEAD @@ -94,6 +94,8 @@ Handle_close_(Handle *self) { FreeLibrary((HMODULE)self->handle); break; case IconHandle: DestroyIcon((HICON)self->handle); break; + case BitmapHandle: + DeleteObject((HBITMAP)self->handle); break; } self->handle = NULL; } @@ -132,6 +134,8 @@ Handle_repr(Handle * self) { name = "HMODULE"; break; case IconHandle: name = "HICON"; break; + case BitmapHandle: + name = "HBITMAP"; break; } return PyUnicode_FromFormat("", name, self->handle, self->associated_name, ""); } @@ -162,6 +166,7 @@ Handle_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { case NormalHandle: case IconHandle: case ModuleHandle: + case BitmapHandle: break; default: PyErr_Format(PyExc_TypeError, "unknown handle type: %d", type); @@ -978,7 +983,7 @@ write_file(PyObject *self, PyObject *args) { DWORD written = 0; BOOL ok; Py_BEGIN_ALLOW_THREADS - ok = WriteFile(handle, data + offset, size - offset, &written, NULL); + ok = WriteFile(handle, data + offset, (DWORD)(size - offset), &written, NULL); Py_END_ALLOW_THREADS if (!ok) return set_error_from_handle(args); return PyLong_FromUnsignedLong(written); @@ -1134,6 +1139,34 @@ get_icon_for_file(PyObject *self, PyObject *args) { return PyErr_SetExcFromWindowsErrWithFilenameObject(PyExc_OSError, ERROR_RESOURCE_TYPE_NOT_FOUND, PyTuple_GET_ITEM(args, 0)); } // }}} + +static PyObject* +get_bitmap_for_file(PyObject *self, PyObject *args) { + wchar_raii path; + long width = 256, height = 256; + if (!PyArg_ParseTuple(args, "O&|ll", py_to_wchar_no_none, &path, &width, &height)) return NULL; + scoped_com_initializer com; + if (!com.succeeded()) { PyErr_SetString(PyExc_OSError, "Failed to initialize COM"); return NULL; } + IShellItemImageFactory *pImageFactory; + HRESULT hr; + Py_BEGIN_ALLOW_THREADS + hr = SHCreateItemFromParsingName(path.ptr(), NULL, IID_PPV_ARGS(&pImageFactory)); + Py_END_ALLOW_THREADS + if (!SUCCEEDED(hr)) { + return error_from_hresult(hr, "Failed to create Shell Item from path"); + } + SIZE size = { width, height }; + HBITMAP hbmp; + Py_BEGIN_ALLOW_THREADS + hr = pImageFactory->GetImage(size, SIIGBF_BIGGERSIZEOK, &hbmp); + pImageFactory->Release(); + Py_END_ALLOW_THREADS + if (!SUCCEEDED(hr)) { + return error_from_hresult(hr, "Failed to get image from shell item"); + } + return (PyObject*)Handle_create(hbmp, BitmapHandle); +} + // Boilerplate {{{ static const char winutil_doc[] = "Defines utility methods to interface with windows."; @@ -1156,6 +1189,7 @@ static PyMethodDef winutil_methods[] = { M(load_library, METH_VARARGS), M(load_icons, METH_VARARGS), M(get_icon_for_file, METH_VARARGS), + M(get_bitmap_for_file, METH_VARARGS), M(parse_cmdline, METH_VARARGS), M(write_file, METH_VARARGS), M(wait_named_pipe, METH_VARARGS), @@ -1463,6 +1497,7 @@ exec_module(PyObject *m) { A(NormalHandle); A(ModuleHandle); A(IconHandle); + A(BitmapHandle); A(KF_FLAG_DEFAULT); A(KF_FLAG_FORCE_APP_DATA_REDIRECTION);