From 57572d977a65771d0193678c8bf5784343d702ce Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 11 Jun 2019 15:57:12 +0530 Subject: [PATCH] Dont use win32com to get file associations --- src/calibre/gui2/actions/view.py | 7 ++++--- src/calibre/utils/file_associations.py | 15 --------------- src/calibre/utils/windows/wintest.py | 4 ++++ src/calibre/utils/windows/winutil.c | 5 +++++ src/calibre/utils/windows/winutilpp.cpp | 10 ++++++++++ 5 files changed, 23 insertions(+), 18 deletions(-) delete mode 100644 src/calibre/utils/file_associations.py diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 501f7d4df3..9ad6954d28 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -10,7 +10,7 @@ from functools import partial from PyQt5.Qt import Qt, QAction, pyqtSignal -from calibre.constants import isosx, iswindows +from calibre.constants import isosx, iswindows, plugins from calibre.gui2 import ( error_dialog, Dispatcher, question_dialog, config, open_local_file, info_dialog, elided_text) @@ -18,6 +18,7 @@ from calibre.gui2.dialogs.choose_format import ChooseFormatDialog from calibre.utils.config import prefs, tweaks from calibre.ptempfile import PersistentTemporaryFile from calibre.gui2.actions import InterfaceAction +from polyglot.builtins import unicode_type class HistoryAction(QAction): @@ -125,11 +126,11 @@ class ViewAction(InterfaceAction): kwargs=dict(args=args)) else: if iswindows: - from calibre.utils.file_associations import file_assoc_windows + winutil = plugins['winutil'][0] ext = name.rpartition('.')[-1] if ext: try: - prog = file_assoc_windows(ext) + prog = winutil.file_association(unicode_type('.' + ext)) except Exception: prog = None if prog and prog.lower().endswith('calibre.exe'): diff --git a/src/calibre/utils/file_associations.py b/src/calibre/utils/file_associations.py deleted file mode 100644 index 324f3ce073..0000000000 --- a/src/calibre/utils/file_associations.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env python2 -# vim:fileencoding=utf-8 -from __future__ import absolute_import, division, print_function, unicode_literals - -__license__ = 'GPL v3' -__copyright__ = '2013, Kovid Goyal ' - - -def file_assoc_windows(ft): - # See the IQueryAssociations::GetString method documentation on MSDN - from win32com.shell import shell, shellcon - a = shell.AssocCreate() - a.Init(0, '.' + ft.lower()) - return a.GetString(0, shellcon.ASSOCSTR_EXECUTABLE) - diff --git a/src/calibre/utils/windows/wintest.py b/src/calibre/utils/windows/wintest.py index 8ac5ed25c0..51980b8557 100644 --- a/src/calibre/utils/windows/wintest.py +++ b/src/calibre/utils/windows/wintest.py @@ -23,6 +23,10 @@ class TestWinutil(unittest.TestCase): self.winutil.add_to_recent_docs(path, None) self.winutil.add_to_recent_docs(path, 'some-app-uid') + def test_file_association(self): + self.assertIn('notepad.exe', self.winutil.file_association('.txt')) + self.assertIsNone(self.winutil.file_association('.mkjsfks')) + def find_tests(): return unittest.defaultTestLoader.loadTestsFromTestCase(TestWinutil) diff --git a/src/calibre/utils/windows/winutil.c b/src/calibre/utils/windows/winutil.c index add7c03010..38b5a87e75 100644 --- a/src/calibre/utils/windows/winutil.c +++ b/src/calibre/utils/windows/winutil.c @@ -376,6 +376,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); static PyMethodDef winutil_methods[] = { {"special_folder_path", winutil_folder_path, METH_VARARGS, @@ -447,6 +448,10 @@ be a unicode string. Returns unicode strings." "add_to_recent_docs()\n\nAdd a path to the recent documents list" }, + {"file_association", (PyCFunction)file_association, METH_VARARGS, + "file_association()\n\nGet the executable associated with the given file extension" + }, + {NULL, NULL, 0, NULL} }; diff --git a/src/calibre/utils/windows/winutilpp.cpp b/src/calibre/utils/windows/winutilpp.cpp index dd150227a8..6050c5b488 100644 --- a/src/calibre/utils/windows/winutilpp.cpp +++ b/src/calibre/utils/windows/winutilpp.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include // for CComPtr #include @@ -60,4 +61,13 @@ add_to_recent_docs(PyObject *self, PyObject *args) { } +PyObject * +file_association(PyObject *self, PyObject *args) { + wchar_t *ext, buf[2048]; + DWORD sz = sizeof(buf); + if (!PyArg_ParseTuple(args, "O&", py_to_wchar, &ext)) return NULL; + HRESULT hr = AssocQueryStringW(0, ASSOCSTR_EXECUTABLE, ext, NULL, buf, &sz); + free_wchar_buffer(&ext); + if (!SUCCEEDED(hr)) Py_RETURN_NONE; + return Py_BuildValue("u#", buf, (int)sz); }