From 48e26a754dcfff25fc48e2220fee359f1e80c98f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jun 2019 18:20:56 +0530 Subject: [PATCH] Couple more places to get rid of win32com --- src/calibre/gui2/preferences/server.py | 6 +++--- src/calibre/utils/windows/wintest.py | 2 ++ src/calibre/utils/windows/winutil.c | 5 +++++ src/calibre/utils/windows/winutilpp.cpp | 20 ++++++++++++++++++++ src/calibre/utils/winreg/default_programs.py | 5 +---- 5 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/calibre/gui2/preferences/server.py b/src/calibre/gui2/preferences/server.py index a8bb1c5dae..ea630285a5 100644 --- a/src/calibre/gui2/preferences/server.py +++ b/src/calibre/gui2/preferences/server.py @@ -18,7 +18,7 @@ from PyQt5.Qt import ( ) from calibre import as_unicode -from calibre.constants import isportable, iswindows +from calibre.constants import isportable, iswindows, plugins from calibre.gui2 import ( choose_files, choose_save_file, config, error_dialog, gprefs, info_dialog, open_url, warning_dialog @@ -49,8 +49,8 @@ if iswindows and not isportable: return exe def startup_shortcut_path(): - from win32com.shell import shell, shellcon - startup_path = shell.SHGetFolderPath(0, shellcon.CSIDL_STARTUP, 0, 0) + winutil = plugins['winutil'][0] + startup_path = winutil.special_folder_path(winutil.CSIDL_STARTUP) return os.path.join(startup_path, "calibre.lnk") class Shortcut(object): diff --git a/src/calibre/utils/windows/wintest.py b/src/calibre/utils/windows/wintest.py index cad6b2c170..b46aee16fb 100644 --- a/src/calibre/utils/windows/wintest.py +++ b/src/calibre/utils/windows/wintest.py @@ -27,6 +27,8 @@ class TestWinutil(unittest.TestCase): q = self.winutil.file_association('.txt') self.assertIn('notepad.exe', q.lower()) self.assertNotIn('\0', q) + q = self.winutil.friendly_name(None, 'notepad.exe') + self.assertEqual('Notepad', q) def test_special_folder_path(self): self.assertEqual(os.path.expanduser('~'), self.winutil.special_folder_path(self.winutil.CSIDL_PROFILE)) diff --git a/src/calibre/utils/windows/winutil.c b/src/calibre/utils/windows/winutil.c index 6a404d22ed..9066c7a7aa 100644 --- a/src/calibre/utils/windows/winutil.c +++ b/src/calibre/utils/windows/winutil.c @@ -377,6 +377,7 @@ winutil_strftime(PyObject *self, PyObject *args) static char winutil_doc[] = "Defines utility methods to interface with windows."; extern PyObject *add_to_recent_docs(PyObject *self, PyObject *args); extern PyObject *file_association(PyObject *self, PyObject *args); +extern PyObject *friendly_name(PyObject *self, PyObject *args); extern PyObject *notify_associations_changed(PyObject *self, PyObject *args); static PyMethodDef winutil_methods[] = { @@ -453,6 +454,10 @@ be a unicode string. Returns unicode strings." "file_association()\n\nGet the executable associated with the given file extension" }, + {"friendly_name", (PyCFunction)friendly_name, METH_VARARGS, + "friendly_name()\n\nGet the friendly name for the specified prog_id/exe" + }, + {"notify_associations_changed", (PyCFunction)notify_associations_changed, METH_VARARGS, "notify_associations_changed()\n\nNotify the OS that file associations have changed" }, diff --git a/src/calibre/utils/windows/winutilpp.cpp b/src/calibre/utils/windows/winutilpp.cpp index 5cee908e76..ef990b3a8f 100644 --- a/src/calibre/utils/windows/winutilpp.cpp +++ b/src/calibre/utils/windows/winutilpp.cpp @@ -72,6 +72,26 @@ file_association(PyObject *self, PyObject *args) { return Py_BuildValue("u", buf); } +PyObject * +friendly_name(PyObject *self, PyObject *args) { + wchar_t *exe, *prog_id, buf[2048], *p; + DWORD sz = sizeof(buf); + if (!PyArg_ParseTuple(args, "O&O&", py_to_wchar, &prog_id, py_to_wchar, &exe)) return NULL; + ASSOCF flags = ASSOCF_REMAPRUNDLL; + if (exe) { + p = exe; + flags |= ASSOCF_OPEN_BYEXENAME; + } else p = prog_id; + if (!p) { + free_wchar_buffer(&exe); free_wchar_buffer(&prog_id); + Py_RETURN_NONE; + } + HRESULT hr = AssocQueryStringW(flags, ASSOCSTR_FRIENDLYAPPNAME, p, NULL, buf, &sz); + free_wchar_buffer(&exe); free_wchar_buffer(&prog_id); + if (!SUCCEEDED(hr) || sz < 1) Py_RETURN_NONE; + return Py_BuildValue("u", buf); +} + PyObject * notify_associations_changed(PyObject *self, PyObject *args) { SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_DWORD | SHCNF_FLUSH, NULL, NULL); diff --git a/src/calibre/utils/winreg/default_programs.py b/src/calibre/utils/winreg/default_programs.py index 6080a8e004..4a76f82feb 100644 --- a/src/calibre/utils/winreg/default_programs.py +++ b/src/calibre/utils/winreg/default_programs.py @@ -250,10 +250,7 @@ def split_commandline(commandline): def friendly_app_name(prog_id=None, exe=None): try: - from win32com.shell import shell, shellcon - a = shell.AssocCreate() - a.Init((shellcon.ASSOCF_INIT_BYEXENAME if exe else 0), exe or prog_id) - return a.GetString(shellcon.ASSOCF_REMAPRUNDLL, shellcon.ASSOCSTR_FRIENDLYAPPNAME) + return plugins['winutil'][0].friendly_name(prog_id, exe) except Exception: import traceback traceback.print_exc()