Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
7.4 KiB

  1. /*****************************************************************************\
  2. FILE: dllload.cpp
  3. DESCRIPTION:
  4. This file will create stub functions that will just-in-time load a DLL
  5. and call an API. This will delay loading functions that either take a long
  6. time to load or may not exist in certain install cases.
  7. BryanSt 4/4/2000 (Bryan Starbuck)
  8. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  9. \*****************************************************************************/
  10. #include "priv.h"
  11. #include <wininet.h>
  12. #include <guiddef.h>
  13. #pragma warning(disable:4229) // No warnings when modifiers used on data
  14. // Delay loading mechanism. This allows you to write code as if you are
  15. // calling implicitly linked APIs, and yet have these APIs really be
  16. // explicitly linked. You can reduce the initial number of DLLs that
  17. // are loaded (load on demand) using this technique.
  18. //
  19. // Use the following macros to indicate which APIs/DLLs are delay-linked
  20. // and -loaded.
  21. //
  22. // DELAY_LOAD
  23. // DELAY_LOAD_HRESULT
  24. // DELAY_LOAD_SAFEARRAY
  25. // DELAY_LOAD_UINT
  26. // DELAY_LOAD_INT
  27. // DELAY_LOAD_VOID
  28. //
  29. // Use these macros for APIs that are exported by ordinal only.
  30. //
  31. // DELAY_LOAD_ORD
  32. // DELAY_LOAD_ORD_VOID
  33. //
  34. // Use these macros for APIs that only exist on the integrated-shell
  35. // installations (i.e., a new shell32 is on the system).
  36. //
  37. // DELAY_LOAD_SHELL
  38. // DELAY_LOAD_SHELL_HRESULT
  39. // DELAY_LOAD_SHELL_VOID
  40. //
  41. //
  42. /**********************************************************************/
  43. void _GetProcFromDLL(HINSTANCE* phinst, LPCSTR pszDLL, FARPROC* ppfn, LPCSTR pszProc)
  44. {
  45. #ifdef DEBUG
  46. CHAR szProcD[MAX_PATH];
  47. if (HIWORD(pszProc)) {
  48. lstrcpynA(szProcD, pszProc, ARRAYSIZE(szProcD));
  49. } else {
  50. wnsprintfA(szProcD, ARRAYSIZE(szProcD), "(ordinal %d)", LOWORD(pszProc));
  51. }
  52. #endif // DEBUG
  53. // If it's already loaded, return.
  54. if (*ppfn) {
  55. return;
  56. }
  57. if (*phinst == NULL) {
  58. #ifdef DEBUG
  59. TraceMsg(TF_WMTHEME, "DLLLOAD: Loading %s for the first time for %s", pszDLL, szProcD);
  60. if (g_dwBreakFlags & 0x00000080)
  61. {
  62. DebugBreak();
  63. }
  64. #endif // DEBUG
  65. *phinst = LoadLibraryA(pszDLL);
  66. if (*phinst == NULL) {
  67. return;
  68. }
  69. }
  70. #ifdef DEBUG
  71. TraceMsg(TF_WMTHEME, "DLLLOAD: GetProc'ing %s from %s for the first time", pszDLL, szProcD);
  72. #endif // DEBUG
  73. *ppfn = GetProcAddress(*phinst, pszProc);
  74. }
  75. /*----------------------------------------------------------
  76. Purpose: Performs a loadlibrary on the DLL only if the machine
  77. has the integrated shell installation.
  78. */
  79. void _SHGetProcFromDLL(HINSTANCE* phinst, LPCSTR pszDLL, FARPROC* ppfn, LPCSTR pszProc)
  80. {
  81. _GetProcFromDLL(phinst, pszDLL, ppfn, pszProc);
  82. }
  83. #define DELAY_LOAD_MAP(_hinst, _dll, _ret, _fnpriv, _fn, _args, _nargs, _err) \
  84. _ret __stdcall _fnpriv _args \
  85. { \
  86. static _ret (* __stdcall _pfn##_fn) _args = NULL; \
  87. _GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, #_fn); \
  88. if (_pfn##_fn) \
  89. return _pfn##_fn _nargs; \
  90. return (_ret)_err; \
  91. }
  92. #define DELAY_MAP_HRESULT(_hinst, _dll, _fnpriv, _fn, _args, _nargs) DELAY_LOAD_MAP(_hinst, _dll, HRESULT, _fnpriv, _fn, _args, _nargs, E_FAIL)
  93. #define DELAY_MAP_DWORD(_hinst, _dll, _fnpriv, _fn, _args, _nargs) DELAY_LOAD_MAP(_hinst, _dll, DWORD, _fnpriv, _fn, _args, _nargs, 0)
  94. #define DELAY_LOAD_ERR(_hinst, _dll, _ret, _fn, _args, _nargs, _err) DELAY_LOAD_MAP(_hinst, _dll, _ret, _fn, _fn, _args, _nargs, _err)
  95. #define DELAY_LOAD(_hinst, _dll, _ret, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, _ret, _fn, _args, _nargs, 0)
  96. #define DELAY_LOAD_HRESULT(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, HRESULT, _fn, _args, _nargs, E_FAIL)
  97. #define DELAY_LOAD_SAFEARRAY(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, SAFEARRAY *, _fn, _args, _nargs, NULL)
  98. #define DELAY_LOAD_DWORD(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, DWORD, _fn, _args, _nargs, 0)
  99. #define DELAY_LOAD_UINT(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, UINT, _fn, _args, _nargs, 0)
  100. #define DELAY_LOAD_INT(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, INT, _fn, _args, _nargs, 0)
  101. #define DELAY_LOAD_BOOL(_hinst, _dll, _fn, _args, _nargs) DELAY_LOAD_ERR(_hinst, _dll, BOOL, _fn, _args, _nargs, FALSE)
  102. #define DELAY_LOAD_VOID(_hinst, _dll, _fn, _args, _nargs) \
  103. void __stdcall _fn _args \
  104. { \
  105. static void (* __stdcall _pfn##_fn) _args = NULL; \
  106. _GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, #_fn); \
  107. if (_pfn##_fn) \
  108. _pfn##_fn _nargs; \
  109. return; \
  110. }
  111. //
  112. // For private entrypoints exported by ordinal.
  113. //
  114. #define DELAY_LOAD_ORD_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, _err) \
  115. _ret __stdcall _fn _args \
  116. { \
  117. static _ret (* __stdcall _pfn##_fn) _args = NULL; \
  118. _GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
  119. if (_pfn##_fn) \
  120. return _pfn##_fn _nargs; \
  121. return (_ret)_err; \
  122. }
  123. #define DELAY_LOAD_ORD(_hinst, _dll, _ret, _fn, _ord, _args, _nargs) DELAY_LOAD_ORD_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, 0)
  124. #define DELAY_LOAD_ORD_HRESULT(_hinst, _dll, _fn, _ord, _args, _nargs) DELAY_LOAD_ORD(_hinst, _dll, HRESULT, _fn, _ord, _args, _nargs)
  125. #define DELAY_LOAD_ORD_VOID(_hinst, _dll, _fn, _ord, _args, _nargs) \
  126. void __stdcall _fn _args \
  127. { \
  128. static void (* __stdcall _pfn##_fn) _args = NULL; \
  129. _GetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
  130. if (_pfn##_fn) \
  131. _pfn##_fn _nargs; \
  132. return; \
  133. }
  134. //
  135. // Private exports by ordinal for integrated-shell installs
  136. //
  137. #define DELAY_LOAD_SHELL_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, _err) \
  138. _ret __stdcall _fn _args \
  139. { \
  140. static _ret (* __stdcall _pfn##_fn) _args = NULL; \
  141. _SHGetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
  142. if (_pfn##_fn) \
  143. return _pfn##_fn _nargs; \
  144. return (_ret)_err; \
  145. }
  146. #define DELAY_LOAD_SHELL(_hinst, _dll, _ret, _fn, _ord, _args, _nargs) DELAY_LOAD_SHELL_ERR(_hinst, _dll, _ret, _fn, _ord, _args, _nargs, 0)
  147. #define DELAY_LOAD_SHELL_HRESULT(_hinst, _dll, _fn, _ord, _args, _nargs) DELAY_LOAD_SHELL_ERR(_hinst, _dll, HRESULT, _fn, _ord, _args, _nargs, E_FAIL)
  148. #define DELAY_LOAD_SHELL_VOID(_hinst, _dll, _fn, _ord, _args, _nargs) \
  149. void __stdcall _fn _args \
  150. { \
  151. static void (* __stdcall _pfn##_fn) _args = NULL; \
  152. _SHGetProcFromDLL(&_hinst, #_dll, (FARPROC*)&_pfn##_fn, (LPCSTR)_ord); \
  153. if (_pfn##_fn) \
  154. _pfn##_fn _nargs; \
  155. return; \
  156. }
  157. /**********************************************************************/
  158. // --------- WINMM.DLL ---------------
  159. HINSTANCE g_hinstWINMM = NULL;
  160. DELAY_LOAD_BOOL(g_hinstWINMM, WINMM.DLL, sndPlaySoundW,
  161. (LPCWSTR pszSound, UINT fuSound),
  162. (pszSound, fuSound));
  163. /**********************************************************************/
  164. #pragma warning(default:4229)