1 /*
2 * This file is part of FFmpeg.
3 *
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #ifndef COMPAT_W32DLFCN_H
20 #define COMPAT_W32DLFCN_H
21
22 #ifdef _WIN32
23 #include <stdint.h>
24
25 #include <windows.h>
26
27 #include "config.h"
28 #include "libavutil/macros.h"
29 #include "libavutil/wchar_filename.h"
30
get_module_filename(HMODULE module)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
57 /**
58 * Safe function used to open dynamic libs. This attempts to improve program security
59 * by removing the current directory from the dll search path. Only dll's found in the
60 * executable or system directory are allowed to be loaded.
61 * @param name The dynamic lib name.
62 * @return A handle to the opened lib.
63 */
win32_dlopen(const char * name)64 static inline HMODULE win32_dlopen(const char *name)
65 {
66 wchar_t *name_w;
67 HMODULE module = NULL;
68 if (utf8towchar(name, &name_w))
69 name_w = NULL;
70 #if _WIN32_WINNT < 0x0602
71 // On Win7 and earlier we check if KB2533623 is available
72 if (!GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "SetDefaultDllDirectories")) {
73 wchar_t *path = NULL, *new_path;
74 DWORD pathlen, pathsize, namelen;
75 if (!name_w)
76 goto exit;
77 namelen = wcslen(name_w);
78 // Try local directory first
79 path = get_module_filename(NULL);
80 if (!path)
81 goto exit;
82 new_path = wcsrchr(path, '\\');
83 if (!new_path)
84 goto exit;
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;
91 wcscpy(path + pathlen + 1, name_w);
92 module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
93 if (module == NULL) {
94 // Next try System32 directory
95 pathlen = GetSystemDirectoryW(path, pathsize);
96 if (!pathlen)
97 goto exit;
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'\\';
113 wcscpy(path + pathlen + 1, name_w);
114 module = LoadLibraryExW(path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
115 }
116 exit:
117 av_free(path);
118 av_free(name_w);
119 return module;
120 }
121 #endif
122 #ifndef LOAD_LIBRARY_SEARCH_APPLICATION_DIR
123 # define LOAD_LIBRARY_SEARCH_APPLICATION_DIR 0x00000200
124 #endif
125 #ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
126 # define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
127 #endif
128 #if HAVE_WINRT
129 if (!name_w)
130 return NULL;
131 module = LoadPackagedLibrary(name_w, 0);
132 #else
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
139 #endif
140 av_free(name_w);
141 return module;
142 }
143 #define dlopen(name, flags) win32_dlopen(name)
144 #define dlclose FreeLibrary
145 #define dlsym GetProcAddress
146 #else
147 #include <dlfcn.h>
148 #endif
149
150 #endif /* COMPAT_W32DLFCN_H */
151