| @@ -20,11 +20,40 @@ · 19 unmodified lines |
| 20 | #define COMPAT_W32DLFCN_H | 20 | #define COMPAT_W32DLFCN_H |
| 21 | | 21 | |
| 22 | #ifdef _WIN32 | 22 | #ifdef _WIN32 |
| | 23 | #include <stdint.h> |
| | 24 | |
| 23 | #include <windows.h> | 25 | #include <windows.h> |
| | 26 | |
| 24 | #include "config.h" | 27 | #include "config.h" |
| 25 | #if (_WIN32_WINNT < 0x0602) || HAVE_WINRT | 28 | #include "libavutil/macros.h" |
| 26 | #include "libavutil/wchar_filename.h" | 29 | #include "libavutil/wchar_filename.h" |
| 27 | #endif | 30 | |
| | 31 | static inline wchar_t *get_module_filename(HMODULE module) |
| | 32 | { |
| | 33 | wchar_t *path = NULL, *new_path; |
| | 34 | DWORD path_size = 0, path_len; |
| | 35 | |
| | 36 | do { |
| | 37 | path_size = path_size ? FFMIN(2 * path_size, INT16_MAX + 1) : MAX_PATH; |
| | 38 | new_path = av_realloc_array(path, path_size, sizeof *path); |
| | 39 | if (!new_path) { |
| | 40 | av_free(path); |
| | 41 | return NULL; |
| | 42 | } |
| | 43 | path = new_path; |
| | 44 | // Returns path_size in case of insufficient buffer. |
| | 45 | // Whether the error is set or not and whether the output |
| | 46 | // is null-terminated or not depends on the version of Windows. |
| | 47 | path_len = GetModuleFileNameW(module, path, path_size); |
| | 48 | } while (path_len && path_size <= INT16_MAX && path_size <= path_len); |
| | 49 | |
| | 50 | if (!path_len) { |
| | 51 | av_free(path); |
| | 52 | return NULL; |
| | 53 | } |
| | 54 | return path; |
| | 55 | } |
| | 56 | |
| 28 | /** | 57 | /** |
| 29 | * Safe function used to open dynamic libs. This attempts to improve program security | 58 | * Safe function used to open dynamic libs. This attempts to improve program security |
| 30 | * by removing the current directory from the dll search path. Only dll's found in the | 59 | * by removing the current directory from the dll search path. Only dll's found in the |
| @@ -34,29 +63,53 @@ · 3 unmodified lines |
| 34 | */ | 63 | */ |
| 35 | static inline HMODULE win32_dlopen(const char *name) | 64 | static inline HMODULE win32_dlopen(const char *name) |
| 36 | { | 65 | { |
| | 66 | wchar_t *name_w; |
| | 67 | HMODULE module = NULL; |
| | 68 | if (utf8towchar(name, &name_w)) |
| | 69 | name_w = NULL; |
| 37 | #if _WIN32_WINNT < 0x0602 | 70 | #if _WIN32_WINNT < 0x0602 |
| 38 | // Need to check if KB2533623 is available | 71 | // On Win7 and earlier we check if KB2533623 is available |
| 39 | if (!GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories")) { | 72 | if (!GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories")) { |
| 40 | HMODULE module = NULL; | 73 | wchar_t *path = NULL, *new_path; |
| 41 | wchar_t *path = NULL, *name_w = NULL; | 74 | DWORD pathlen, pathsize, namelen; |
| 42 | DWORD pathlen; | 75 | if (!name_w) |
| 43 | if (utf8towchar(name, &name_w)) | | |
| 44 | goto exit; | 76 | goto exit; |
| 45 | path = (wchar_t *)av_calloc(MAX_PATH, sizeof(wchar_t)); | 77 | namelen = wcslen(name_w); |
| 46 | // Try local directory first | 78 | // Try local directory first |
| 47 | pathlen = GetModuleFileNameW(NULL, path, MAX_PATH); | 79 | path = get_module_filename(NULL); |
| 48 | pathlen = wcsrchr(path, '\\') - path; | 80 | if (!path) |
| 49 | if (pathlen == 0 || pathlen + wcslen(name_w) + 2 > MAX_PATH) | 81 | goto exit; |
| | 82 | new_path = wcsrchr(path, '\\'); |
| | 83 | if (!new_path) |
| 50 | goto exit; | 84 | goto exit; |
| 51 | path[pathlen] = '\\'; | 85 | pathlen = new_path - path; |
| | 86 | pathsize = pathlen + namelen + 2; |
| | 87 | new_path = av_realloc_array(path, pathsize, sizeof *path); |
| | 88 | if (!new_path) |
| | 89 | goto exit; |
| | 90 | path = new_path; |
| 52 | wcscpy(path + pathlen + 1, name_w); | 91 | wcscpy(path + pathlen + 1, name_w); |
| 53 | module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | 92 | module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); |
| 54 | if (module == NULL) { | 93 | if (module == NULL) { |
| 55 | // Next try System32 directory | 94 | // Next try System32 directory |
| 56 | pathlen = GetSystemDirectoryW(path, MAX_PATH); | 95 | pathlen = GetSystemDirectoryW(path, pathsize); |
| 57 | if (pathlen == 0 || pathlen + wcslen(name_w) + 2 > MAX_PATH) | 96 | if (!pathlen) |
| 58 | goto exit; | 97 | goto exit; |
| 59 | path[pathlen] = '\\'; | 98 | // Buffer is not enough in two cases: |
| | 99 | // 1. system directory + \ + module name |
| | 100 | // 2. system directory even without the module name. |
| | 101 | if (pathlen + namelen + 2 > pathsize) { |
| | 102 | pathsize = pathlen + namelen + 2; |
| | 103 | new_path = av_realloc_array(path, pathsize, sizeof *path); |
| | 104 | if (!new_path) |
| | 105 | goto exit; |
| | 106 | path = new_path; |
| | 107 | // Query again to handle the case #2. |
| | 108 | pathlen = GetSystemDirectoryW(path, pathsize); |
| | 109 | if (!pathlen) |
| | 110 | goto exit; |
| | 111 | } |
| | 112 | path[pathlen] = L'\\'; |
| 60 | wcscpy(path + pathlen + 1, name_w); | 113 | wcscpy(path + pathlen + 1, name_w); |
| 61 | module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); | 114 | module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH); |
| 62 | } | 115 | } |
| @@ -73,16 +126,19 @@ exit: · 10 unmodified lines |
| 73 | # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 | 126 | # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800 |
| 74 | #endif | 127 | #endif |
| 75 | #if HAVE_WINRT | 128 | #if HAVE_WINRT |
| 76 | wchar_t *name_w = NULL; | 129 | if (!name_w) |
| 77 | int ret; | | |
| 78 | if (utf8towchar(name, &name_w)) | | |
| 79 | return NULL; | 130 | return NULL; |
| 80 | ret = LoadPackagedLibrary(name_w, 0); | 131 | module = LoadPackagedLibrary(name_w, 0); |
| 81 | av_free(name_w); | | |
| 82 | return ret; | | |
| 83 | #else | 132 | #else |
| 84 | return LoadLibraryExA(name, NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); | 133 | #define LOAD_FLAGS (LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32) |
| | 134 | /* filename may be be in CP_ACP */ |
| | 135 | if (!name_w) |
| | 136 | return LoadLibraryExA(name, NULL, LOAD_FLAGS); |
| | 137 | module = LoadLibraryExW(name_w, NULL, LOAD_FLAGS); |
| | 138 | #undef LOAD_FLAGS |
| 85 | #endif | 139 | #endif |
| | 140 | av_free(name_w); |
| | 141 | return module; |
| 86 | } | 142 | } |
| 87 | #define dlopen(name, flags) win32_dlopen(name) | 143 | #define dlopen(name, flags) win32_dlopen(name) |
| 88 | #define dlclose FreeLibrary | 144 | #define dlclose FreeLibrary |