From: nihil-admirari <50202386+nihil-admir...@users.noreply.github.com>
Long path support is enabled by adding a manifest to all of fftools.
MAX_PATH-sized buffers are replaced with dynamically sized ones.
---
compat/w32dlfcn.h| 61 +++-
fftools/Makefile | 5 +++
fftools/cmdutils.c | 31
fftools/long_paths_utf8.manifest | 12 +++
fftools/long_paths_utf8.rc | 3 ++
libavformat/avisynth.c | 10 +++---
libavutil/wchar_filename.h | 37 +++
7 files changed, 139 insertions(+), 20 deletions(-)
create mode 100644 fftools/long_paths_utf8.manifest
create mode 100644 fftools/long_paths_utf8.rc
diff --git a/compat/w32dlfcn.h b/compat/w32dlfcn.h
index 52a94ef..ba2330a 100644
--- a/compat/w32dlfcn.h
+++ b/compat/w32dlfcn.h
@@ -25,6 +25,30 @@
#if (_WIN32_WINNT < 0x0602) || HAVE_WINRT
#include "libavutil/wchar_filename.h"
#endif
+
+static inline wchar_t *get_module_filename(const HMODULE module)
+{
+wchar_t *path = NULL;
+int path_size = 0, path_len = 0;
+
+do {
+path_size = path_size ? 1.5 * path_size : MAX_PATH;
+wchar_t *new_path = av_realloc_array(path, path_size, sizeof *path);
+if (!new_path) {
+av_free(path);
+return NULL;
+}
+path = new_path;
+path_len = GetModuleFileNameW(module, path, path_size);
+} while (path_len && path_size <= 32768 && path_size <= path_len);
+
+if (!path_len) {
+av_free(path);
+return NULL;
+}
+return path;
+}
+
/**
* Safe function used to open dynamic libs. This attempts to improve program
security
* by removing the current directory from the dll search path. Only dll's
found in the
@@ -38,24 +62,43 @@ static inline HMODULE win32_dlopen(const char *name)
// Need to check if KB2533623 is available
if (!GetProcAddress(GetModuleHandleW(L"kernel32.dll"),
"SetDefaultDllDirectories")) {
HMODULE module = NULL;
-wchar_t *path = NULL, *name_w = NULL;
-DWORD pathlen;
+wchar_t *path = NULL, *new_path = NULL, *name_w = NULL;
+DWORD pathlen, pathsize, namelen;
if (utf8towchar(name, _w))
goto exit;
-path = (wchar_t *)av_calloc(MAX_PATH, sizeof(wchar_t));
+namelen = wcslen(name_w);
// Try local directory first
-pathlen = GetModuleFileNameW(NULL, path, MAX_PATH);
-pathlen = wcsrchr(path, '\\') - path;
-if (pathlen == 0 || pathlen + wcslen(name_w) + 2 > MAX_PATH)
+path = get_module_filename(NULL);
+if (!path)
+goto exit;
+new_path = wcsrchr(path, '\\');
+if (!new_path)
+goto exit;
+pathlen = new_path - path;
+pathsize = pathlen + namelen + 2;
+new_path = av_realloc_array(path, pathsize, sizeof *path);
+if (!new_path)
goto exit;
-path[pathlen] = '\\';
+path = new_path;
wcscpy(path + pathlen + 1, name_w);
module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
if (module == NULL) {
// Next try System32 directory
-pathlen = GetSystemDirectoryW(path, MAX_PATH);
-if (pathlen == 0 || pathlen + wcslen(name_w) + 2 > MAX_PATH)
+pathlen = GetSystemDirectoryW(path, pathsize);
+if (!pathlen)
goto exit;
+if (pathlen + namelen + 2 > pathsize) {
+pathsize = pathlen + namelen + 2;
+new_path = av_realloc_array(path, pathsize, sizeof *path);
+if (!new_path)
+goto exit;
+path = new_path;
+// The buffer might have been not enough for system directory
+// in the first place.
+pathlen = GetSystemDirectoryW(path, pathsize);
+if (!pathlen)
+goto exit;
+}
path[pathlen] = '\\';
wcscpy(path + pathlen + 1, name_w);
module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
diff --git a/fftools/Makefile b/fftools/Makefile
index da42078..53438b6 100644
--- a/fftools/Makefile
+++ b/fftools/Makefile
@@ -11,6 +11,11 @@ ALLAVPROGS_G = $(AVBASENAMES:%=%$(PROGSSUF)_g$(EXESUF))
OBJS-ffmpeg+= fftools/ffmpeg_opt.o
fftools/ffmpeg_filter.o fftools/ffmpeg_hw.o
+# Windows resource files
+OBJS-ffmpeg-$(HAVE_GNU_WINDRES) += fftools/long_paths_utf8.o
+OBJS-ffplay-$(HAVE_GNU_WINDRES) += fftools/long_paths_utf8.o
+OBJS-ffprobe-$(HAVE_GNU_WINDRES) += fftools/long_paths_utf8.o
+
define DOFFTOOL
OBJS-$(1) += fftools/cmdutils.o fftools/$(1).o $(OBJS-$(1)-yes)
$(1)$(PROGSSUF)_g$(EXESUF): $$(OBJS-$(1))
diff --git a/fftools/cmdutils.c b/fftools/cmdutils.c
index 4b50e15..ea78897 100644
--- a/fftools/cmdutils.c
+++ b/fftools/cmdutils.c
@@ -62,6 +62,7 @@
#endif
#ifdef _WIN32