diff options
author | Ron Yorston <rmy@pobox.com> | 2020-06-02 07:53:10 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-06-02 08:27:46 +0100 |
commit | 27c718aa1a4674587925adb543362cb8e60814c4 (patch) | |
tree | db22579586cede7cb0f3351ce66c36f98a9a5a7a | |
parent | 5ea460a32a9882906c7ee3656b8fb0dcdbce2abc (diff) | |
download | busybox-w32-27c718aa1a4674587925adb543362cb8e60814c4.tar.gz busybox-w32-27c718aa1a4674587925adb543362cb8e60814c4.tar.bz2 busybox-w32-27c718aa1a4674587925adb543362cb8e60814c4.zip |
win32: use lazy loading for certain DLLs
Only a handful of functions are used from shell32.dll, userenv.dll
and psapi.dll. Mostly these functions are in out of the way places.
By loading the functions only when required we can avoid the startup
cost of linking the three DLLs in the common case that they aren't
needed.
-rw-r--r-- | Makefile.flags | 2 | ||||
-rw-r--r-- | loginutils/suw32.c | 7 | ||||
-rw-r--r-- | win32/lazyload.h | 16 | ||||
-rw-r--r-- | win32/mingw.c | 27 | ||||
-rw-r--r-- | win32/process.c | 15 |
5 files changed, 43 insertions, 24 deletions
diff --git a/Makefile.flags b/Makefile.flags index dddeb0ce6..26031f561 100644 --- a/Makefile.flags +++ b/Makefile.flags | |||
@@ -146,7 +146,7 @@ endif | |||
146 | ifeq ($(CONFIG_PLATFORM_MINGW32),y) | 146 | ifeq ($(CONFIG_PLATFORM_MINGW32),y) |
147 | CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident | 147 | CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident |
148 | EXEEXT = .exe | 148 | EXEEXT = .exe |
149 | LDLIBS += userenv psapi ws2_32 | 149 | LDLIBS += ws2_32 |
150 | endif | 150 | endif |
151 | 151 | ||
152 | ifneq ($(CONFIG_PLATFORM_MINGW32),y) | 152 | ifneq ($(CONFIG_PLATFORM_MINGW32),y) |
diff --git a/loginutils/suw32.c b/loginutils/suw32.c index de29f423a..3500c08db 100644 --- a/loginutils/suw32.c +++ b/loginutils/suw32.c | |||
@@ -22,6 +22,7 @@ | |||
22 | //usage: "\n -c CMD Command to pass to 'sh -c'" | 22 | //usage: "\n -c CMD Command to pass to 'sh -c'" |
23 | 23 | ||
24 | #include "libbb.h" | 24 | #include "libbb.h" |
25 | #include "lazyload.h" | ||
25 | 26 | ||
26 | int suw32_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 27 | int suw32_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
27 | int suw32_main(int argc UNUSED_PARAM, char **argv) | 28 | int suw32_main(int argc UNUSED_PARAM, char **argv) |
@@ -29,6 +30,7 @@ int suw32_main(int argc UNUSED_PARAM, char **argv) | |||
29 | char *opt_command = NULL; | 30 | char *opt_command = NULL; |
30 | SHELLEXECUTEINFO info; | 31 | SHELLEXECUTEINFO info; |
31 | char *bb_path, *cwd; | 32 | char *bb_path, *cwd; |
33 | DECLARE_PROC_ADDR(BOOL, ShellExecuteExA, SHELLEXECUTEINFOA *); | ||
32 | 34 | ||
33 | getopt32(argv, "c:", &opt_command); | 35 | getopt32(argv, "c:", &opt_command); |
34 | if (argv[optind]) | 36 | if (argv[optind]) |
@@ -63,5 +65,8 @@ int suw32_main(int argc UNUSED_PARAM, char **argv) | |||
63 | /* info.lpDirectory = NULL; */ | 65 | /* info.lpDirectory = NULL; */ |
64 | info.nShow = SW_SHOWNORMAL; | 66 | info.nShow = SW_SHOWNORMAL; |
65 | 67 | ||
66 | return !ShellExecuteEx(&info); | 68 | if (!INIT_PROC_ADDR(shell32.dll, ShellExecuteExA)) |
69 | return -1; | ||
70 | |||
71 | return !ShellExecuteExA(&info); | ||
67 | } | 72 | } |
diff --git a/win32/lazyload.h b/win32/lazyload.h index a9fcff209..034bc7e45 100644 --- a/win32/lazyload.h +++ b/win32/lazyload.h | |||
@@ -21,19 +21,7 @@ struct proc_addr { | |||
21 | #define INIT_PROC_ADDR(dll, function) \ | 21 | #define INIT_PROC_ADDR(dll, function) \ |
22 | (function = get_proc_addr(#dll, #function, &proc_addr_##function)) | 22 | (function = get_proc_addr(#dll, #function, &proc_addr_##function)) |
23 | 23 | ||
24 | static inline void *get_proc_addr(const char *dll, const char *function, struct proc_addr *proc) | 24 | void *get_proc_addr(const char *dll, const char *function, |
25 | { | 25 | struct proc_addr *proc); |
26 | /* only do this once */ | ||
27 | if (!proc->initialized) { | ||
28 | HANDLE hnd = LoadLibraryExA(dll, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); | ||
29 | if (hnd) | ||
30 | proc->pfunction = GetProcAddress(hnd, function); | ||
31 | proc->initialized = 1; | ||
32 | } | ||
33 | /* set ENOSYS if DLL or function was not found */ | ||
34 | if (!proc->pfunction) | ||
35 | errno = ENOSYS; | ||
36 | return proc->pfunction; | ||
37 | } | ||
38 | 26 | ||
39 | #endif | 27 | #endif |
diff --git a/win32/mingw.c b/win32/mingw.c index 5c4c39b9d..105b7864d 100644 --- a/win32/mingw.c +++ b/win32/mingw.c | |||
@@ -837,17 +837,17 @@ static char *gethomedir(void) | |||
837 | static char *buf = NULL; | 837 | static char *buf = NULL; |
838 | DWORD len = PATH_MAX; | 838 | DWORD len = PATH_MAX; |
839 | HANDLE h; | 839 | HANDLE h; |
840 | DECLARE_PROC_ADDR(BOOL, GetUserProfileDirectoryA, HANDLE, LPSTR, LPDWORD); | ||
840 | 841 | ||
841 | if (!buf) | 842 | if (buf) |
842 | buf = xzalloc(PATH_MAX); | ||
843 | |||
844 | if (buf[0]) | ||
845 | return buf; | 843 | return buf; |
846 | 844 | ||
845 | buf = xzalloc(PATH_MAX); | ||
847 | if ( !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &h) ) | 846 | if ( !OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &h) ) |
848 | return buf; | 847 | return buf; |
849 | 848 | ||
850 | GetUserProfileDirectory(h, buf, &len); | 849 | if (INIT_PROC_ADDR(userenv.dll, GetUserProfileDirectoryA)) |
850 | GetUserProfileDirectoryA(h, buf, &len); | ||
851 | CloseHandle(h); | 851 | CloseHandle(h); |
852 | return bs_to_slash(buf); | 852 | return bs_to_slash(buf); |
853 | } | 853 | } |
@@ -1027,7 +1027,6 @@ int link(const char *oldpath, const char *newpath) | |||
1027 | LPSECURITY_ATTRIBUTES); | 1027 | LPSECURITY_ATTRIBUTES); |
1028 | 1028 | ||
1029 | if (!INIT_PROC_ADDR(kernel32.dll, CreateHardLinkA)) { | 1029 | if (!INIT_PROC_ADDR(kernel32.dll, CreateHardLinkA)) { |
1030 | errno = ENOSYS; | ||
1031 | return -1; | 1030 | return -1; |
1032 | } | 1031 | } |
1033 | if (!CreateHardLinkA(newpath, oldpath, NULL)) { | 1032 | if (!CreateHardLinkA(newpath, oldpath, NULL)) { |
@@ -1767,3 +1766,19 @@ void make_sparse(int fd, off_t start, off_t end) | |||
1767 | DeviceIoControl(fh, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi), | 1766 | DeviceIoControl(fh, FSCTL_SET_ZERO_DATA, &fzdi, sizeof(fzdi), |
1768 | NULL, 0, &dwTemp, NULL); | 1767 | NULL, 0, &dwTemp, NULL); |
1769 | } | 1768 | } |
1769 | |||
1770 | void *get_proc_addr(const char *dll, const char *function, | ||
1771 | struct proc_addr *proc) | ||
1772 | { | ||
1773 | /* only do this once */ | ||
1774 | if (!proc->initialized) { | ||
1775 | HANDLE hnd = LoadLibraryExA(dll, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32); | ||
1776 | if (hnd) | ||
1777 | proc->pfunction = GetProcAddress(hnd, function); | ||
1778 | proc->initialized = 1; | ||
1779 | } | ||
1780 | /* set ENOSYS if DLL or function was not found */ | ||
1781 | if (!proc->pfunction) | ||
1782 | errno = ENOSYS; | ||
1783 | return proc->pfunction; | ||
1784 | } | ||
diff --git a/win32/process.c b/win32/process.c index 04775100b..5833a0323 100644 --- a/win32/process.c +++ b/win32/process.c | |||
@@ -446,6 +446,17 @@ static char *get_bb_string(DWORD pid, const char *exe, char *string) | |||
446 | char exepath[PATH_MAX]; | 446 | char exepath[PATH_MAX]; |
447 | char *name = NULL; | 447 | char *name = NULL; |
448 | int i; | 448 | int i; |
449 | DECLARE_PROC_ADDR(DWORD, GetProcessImageFileNameA, HANDLE, | ||
450 | LPSTR, DWORD); | ||
451 | DECLARE_PROC_ADDR(BOOL, EnumProcessModules, HANDLE, HMODULE *, | ||
452 | DWORD, LPDWORD); | ||
453 | DECLARE_PROC_ADDR(DWORD, GetModuleFileNameExA, HANDLE, HMODULE, | ||
454 | LPSTR, DWORD); | ||
455 | |||
456 | if (!INIT_PROC_ADDR(psapi.dll, GetProcessImageFileNameA) || | ||
457 | !INIT_PROC_ADDR(psapi.dll, EnumProcessModules) || | ||
458 | !INIT_PROC_ADDR(psapi.dll, GetModuleFileNameExA)) | ||
459 | return NULL; | ||
449 | 460 | ||
450 | if (!(proc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, | 461 | if (!(proc=OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, |
451 | FALSE, pid))) { | 462 | FALSE, pid))) { |
@@ -453,7 +464,7 @@ static char *get_bb_string(DWORD pid, const char *exe, char *string) | |||
453 | } | 464 | } |
454 | 465 | ||
455 | if (exe == NULL) { | 466 | if (exe == NULL) { |
456 | if (GetProcessImageFileName(proc, exepath, PATH_MAX) != 0) { | 467 | if (GetProcessImageFileNameA(proc, exepath, PATH_MAX) != 0) { |
457 | exe = bb_basename(exepath); | 468 | exe = bb_basename(exepath); |
458 | } | 469 | } |
459 | } | 470 | } |
@@ -470,7 +481,7 @@ static char *get_bb_string(DWORD pid, const char *exe, char *string) | |||
470 | 481 | ||
471 | for (i=0; exe != NULL && i<needed/sizeof(HMODULE); ++i) { | 482 | for (i=0; exe != NULL && i<needed/sizeof(HMODULE); ++i) { |
472 | char modname[MAX_PATH]; | 483 | char modname[MAX_PATH]; |
473 | if (GetModuleFileNameEx(proc, mlist[i], modname, sizeof(modname))) { | 484 | if (GetModuleFileNameExA(proc, mlist[i], modname, sizeof(modname))) { |
474 | if (strcasecmp(bb_basename(modname), exe) == 0) { | 485 | if (strcasecmp(bb_basename(modname), exe) == 0) { |
475 | break; | 486 | break; |
476 | } | 487 | } |