aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2020-06-02 07:53:10 +0100
committerRon Yorston <rmy@pobox.com>2020-06-02 08:27:46 +0100
commit27c718aa1a4674587925adb543362cb8e60814c4 (patch)
treedb22579586cede7cb0f3351ce66c36f98a9a5a7a
parent5ea460a32a9882906c7ee3656b8fb0dcdbce2abc (diff)
downloadbusybox-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.flags2
-rw-r--r--loginutils/suw32.c7
-rw-r--r--win32/lazyload.h16
-rw-r--r--win32/mingw.c27
-rw-r--r--win32/process.c15
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
146ifeq ($(CONFIG_PLATFORM_MINGW32),y) 146ifeq ($(CONFIG_PLATFORM_MINGW32),y)
147CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident 147CFLAGS += -Iwin32 -DHAVE_STRING_H=1 -DHAVE_CONFIG_H=0 -fno-builtin-stpcpy -fno-ident
148EXEEXT = .exe 148EXEEXT = .exe
149LDLIBS += userenv psapi ws2_32 149LDLIBS += ws2_32
150endif 150endif
151 151
152ifneq ($(CONFIG_PLATFORM_MINGW32),y) 152ifneq ($(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
26int suw32_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 27int suw32_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
27int suw32_main(int argc UNUSED_PARAM, char **argv) 28int 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
24static inline void *get_proc_addr(const char *dll, const char *function, struct proc_addr *proc) 24void *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
1770void *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 }