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...

  1. would avoid loading specific function under xp don't need call getmodulehandle , getprocaddress?
  2. 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

Popular posts from this blog

php - Vagrant up error - Uncaught Reflection Exception: Class DOMDocument does not exist -

vue.js - Create hooks for automated testing -

Add new key value to json node in java -