diff --git a/setup/extensions.json b/setup/extensions.json index 2c9d5187de..4638e5046c 100644 --- a/setup/extensions.json +++ b/setup/extensions.json @@ -141,7 +141,7 @@ "only": "windows", "headers": "calibre/utils/windows/common.h", "sources": "calibre/utils/windows/winutil.cpp", - "libraries": "shell32 wininet advapi32", + "libraries": "shell32 wininet advapi32 Pathcch", "cflags": "/X" }, { diff --git a/src/calibre/utils/windows/winutil.cpp b/src/calibre/utils/windows/winutil.cpp index 125cdd5e85..17fa709359 100644 --- a/src/calibre/utils/windows/winutil.cpp +++ b/src/calibre/utils/windows/winutil.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -724,6 +725,24 @@ get_long_path_name(PyObject *self, PyObject *args) { return ans; } +static PyObject * +canonicalize_path(PyObject *self, PyObject *args) { + wchar_raii path; + if (!PyArg_ParseTuple(args, "O&", py_to_wchar_no_none, &path)) return NULL; + size_t path_len = 0; + wchar_t *p = path.ptr(); + while (p[path_len]) { + if (p[path_len] == '/') p[path_len] = '\\'; + path_len++; + } + wchar_t *ans; + HRESULT hr = PathAllocCanonicalize(p, PATHCCH_ENSURE_IS_EXTENDED_LENGTH_PATH, &ans); + if (FAILED(hr)) return error_from_hresult(hr, "Failed to canonicalize path", PyTuple_GET_ITEM(args, 0)); + PyObject *r = PyUnicode_FromWideChar(ans, -1); + LocalFree(ans); + return r; +} + static PyObject * get_process_times(PyObject *self, PyObject *pid) { HANDLE h = INVALID_HANDLE_VALUE; @@ -1006,6 +1025,7 @@ static PyMethodDef winutil_methods[] = { M(set_handle_information, METH_VARARGS), M(get_long_path_name, METH_VARARGS), M(get_process_times, METH_O), + M(canonicalize_path, METH_VARARGS), M(get_handle_information, METH_VARARGS), M(get_last_error, METH_NOARGS), M(load_library, METH_VARARGS),