windows - Are delay-loaded DLLs useful to avoid linking specific functions? -
consider following code needs call 1 of 2 functions in user32.dll
.
if( iswindowsvistaorgreater() ) addclipboardformatlistener(hwnd) ; else setclipboardviewer(hwnd) ;
if i'm not mistaken, program fail start on winxp because addclipboardformatlistener
not exist in user32.dll
under xp.
one way solve not calling addclipboardformatlistener
directly rather pointer ourselves:
getprocaddress(getmodulehandle("user32.dll"), "addclipboardformatlistener")
.
however, if instruct linker delay-load user32.dll
...
- would avoid loading specific function under xp don't need call
getmodulehandle
,getprocaddress
? - is recommended delay-load dll when few functions need delay-loaded?
the case of user32.dll
particularly dramatic on second point since of functions used in program know exist in dll on windows versions.
guess linking @ load-time more efficient @ run-time since latter needs additional checks before each function call.
i'm guessing, hence question.
would avoid loading specific function under xp don't need call
getmodulehandle
,getprocaddress
?
yes. type of situation delay-loading invented for. code can call dll function if statically linked, executable not load dll function pointer @ runtime until function called first time. internally, delay-load mechanism uses loadlibrary()
, getprocaddress()
you.
is recommended delay-load dll when few functions need delay-loaded?
if dll delay-loaded, of functions delay-loaded, cannot pick , choose ones want. so, if app needs use lot of functions same dll, user32.dll
, static linking more efficient, , can use getprocaddress()
manually few functions need handle differently.
in case, suggest getting rid of os check altogether , rely on whether dll function exists or not, eg:
typedef bool (winapi *lpfn_acfl)(hwnd); lpfn_acfl lpaddclipboardformatlistener = (lpfn_acfl) getprocaddress(getmodulehandle(text("user32")), "addclipboardformatlistener"); if( lpaddclipboardformatlistener != null ) lpaddclipboardformatlistener(hwnd); else setclipboardviewer(hwnd);
where delay-loading shines in hooks. instance, on earlier systems, can use delay-load failure hook implement own version of addclipboardformatlistener()
, , main code can call addclipboardformatlistener()
unconditionally on systems , won't know difference. example (just demo, not tested):
lresult callback clipboardsubclassproc(hwnd hwnd, uint umsg, wparam wparam, lparam lparam, uint_ptr uidsubclass, dword_ptr dwrefdata) { switch (umsg) { case wm_ncdestroy: removewindowsubclass(hwnd, &clipboardsubclassproc, uidsubclass); break; case wm_changecbchain: { if (wparam == dwrefdata) setwindowsubclass(hwnd, &clipboardsubclassproc, uidsubclass, lparam); else if (dwrefdata != 0) sendmessage((hwnd)dwrefdata, umsg, wparam, lparam); break; } case wm_drawclipboard: { sendmessage(hwnd, wm_clipboardupdate, 0, 0); if (dwrefdata != 0) sendmessage((hwnd)dwrefdata, umsg, wparam, lparam); break; } } return defsubclassproc(hwnd, umsg, wparam, lparam); } bool winapi my_addclipboardformatlistener(hwnd hwnd) { hwnd hwndnext = setclipboardviewer(hwnd); if ((!hwndnext) && (getlasterror() != 0)) return false; if (!setwindowsubclass(hwnd, &clipboardsubclassproc, 1, (dword_ptr)hwndnext)) { dword dwerr = getlasterror(); changeclipboardchain(hwnd, hwndnext); setlasterror(dwerr); return false; } return true; } bool winapi my_removeclipboardformatlistener(hwnd hwnd) { dword_ptr dwrefdata; if (!getwindowsubclass(hwnd, &clipboardsubclassproc, 1, &dwrefdata)) { setlasterror(error_not_found); return false; } removewindowsubclass(hwnd, &clipboardsubclassproc, 1); return changeclipboardchain(hwnd, (hwnd)dwrefdata); } farproc winapi mydlifailurehook(unsigned dlinotify, pdelayloadinfo pdli) { if ((dlinotify == dlifailgetproc) && (pdli->dlp.fimportbyname)) { if (strcmp(pdli->dlp.szprocname, "addclipboardformatlistener") == 0) return (farproc) &my_addclipboardformatlistener; if (strcmp(pdli->dlp.szprocname, "removeclipboardformatlistener") == 0) return (farproc) &my_removeclipboardformatlistener; } return null; } __pfndlifailurehook2 = &mydlifailurehook; ... lresult callback mywndproc(hwnd hwnd, uint umsg, wparam wparam, lparam lparam) { switch (umsg) { case wm_create: addclipboardformatlistener(hwnd); break; case wm_destroy: removeclipboardformatlistener(hwnd); break; case wm_clipboardupdate: // of clipboard processing here... break; ... } return defwindowproc(hwnd, umsg, wparam, lparam); }
Comments
Post a Comment