Leaked source code of windows server 2003
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.

275 lines
8.2 KiB

  1. /*++
  2. Copyright (c) 2000-2001 Microsoft Corporation
  3. Module Name:
  4. SampleShim.cpp
  5. Abstract:
  6. This DLL serves as a template for the creation of shim DLLs. Follow
  7. the commenting/coding style of this source file wherever possible.
  8. Never use tabs, configure your editor to insert spaces instead of
  9. tab characters.
  10. Notes:
  11. Hooking COM functions is also possible but is not covered in this
  12. sample for simplicity sake. Contact markder or linstev for more
  13. information on COM hooking.
  14. History:
  15. 02/02/2000 markder Created
  16. 11/14/2000 markder Converted to framework version 2
  17. 02/13/2001 mnikkel Changed notify to handle new DLL_PROCESS
  18. capabilities
  19. 03/31/2001 robkenny Changed to use CString
  20. 04/10/2002 robkenny Updated to compile.
  21. --*/
  22. #include "ShimHook.h"
  23. #include "StrSafe.h"
  24. using namespace ShimLib;
  25. //
  26. // You must declare the type of shim this is at the top. If your shim
  27. // coexists with other shims in the same DLL,
  28. // use IMPLEMENT_SHIM_BEGIN(SampleShim)
  29. // otherwise use IMPLEMENT_SHIM_STANDALONE(SampleShim)
  30. //
  31. IMPLEMENT_SHIM_STANDALONE(SampleShim)
  32. #include "ShimHookMacro.h"
  33. //
  34. // Add APIs that you wish to hook to this macro construction.
  35. //
  36. APIHOOK_ENUM_BEGIN
  37. APIHOOK_ENUM_ENTRY(MessageBoxA)
  38. APIHOOK_ENUM_ENTRY(MessageBoxW)
  39. APIHOOK_ENUM_END
  40. /*++
  41. This stub function intercepts all calls to MessageBoxA
  42. and prefixes the output string with "SampleShim says:".
  43. --*/
  44. int
  45. APIHOOK(MessageBoxA)(
  46. HWND hWnd, // handle to owner window
  47. LPCSTR lpText, // text in message box
  48. LPCSTR lpCaption, // message box title
  49. UINT uType // message box style
  50. )
  51. {
  52. //
  53. // Use Hungarian notation for local variables:
  54. //
  55. // Type Scope
  56. // ----------------------- ------------------
  57. // Pointers p Global g_
  58. // DWORD dw Class member m_
  59. // LONG l Static s_
  60. // ANSI strings sz
  61. // Wide-char strings wsz
  62. // Arrays rg
  63. // CString cs
  64. //
  65. int iReturnValue;
  66. //
  67. // We use the CString class to perform all string operations in UNICODE
  68. // to prevent any problems with DBCS characters.
  69. //
  70. // Place all CString operations inside a CSTRING_TRY/CSTRING_CATCH
  71. // exception handler. CString will throw an exception if it encounters
  72. // any memory allocation failures.
  73. //
  74. // Performing all string operations by using the CString class also prevents
  75. // us from accidentally modifying the original string.
  76. //
  77. CSTRING_TRY
  78. {
  79. CString csNewOutputString(lpText);
  80. csNewOutputString.Insert(0, L"SampleShim says: ");
  81. //
  82. // Use the DPF macro to print debug strings. See Hooks\inc\ShimDebug.h
  83. // for debug level values. Use eDbgLevelError if an unexpected error
  84. // occurs in your shim code. For informational output, use eDbgLevelInfo.
  85. //
  86. // Make sure you don't end the message with '\n' in this case because
  87. // the macro will do it by default.
  88. //
  89. // Note that when printing CString, use %S and you must call the Get() method,
  90. // to explicitly return a WCHAR *.
  91. //
  92. DPFN( eDbgLevelInfo,
  93. "MessageBoxA called with lpText = \"%s\".", lpText);
  94. //
  95. // Use the ORIGINAL_API macro to call the original API. You must use
  96. // this so that API chaining and inclusion/exclusion information is
  97. // preserved.
  98. //
  99. // CString will perform automatic type conversion to const WCHAR * (LPCWSTR)
  100. // It will not, however, automatically convert to char *, you must call GetAnsi()
  101. // (or GetAnsiNIE() if you wish a NULL pointer be returned when the string is empty)
  102. //
  103. iReturnValue = ORIGINAL_API(MessageBoxA)(hWnd, csNewOutputString.GetAnsi(), lpCaption, uType);
  104. //
  105. // Use the LOG macro to print messages to the log file. This macro should
  106. // be used to indicate that the shim had affected execution of the program
  107. // in some way. Use eDbgLevelError to indicate that the shim has
  108. // consciously fixed something that would have caused problems. Use
  109. // eDbgLevelWarning if the shim has affected execution, but it is unclear
  110. // whether it actually helped the program.
  111. //
  112. LOGN( eDbgLevelWarning,
  113. "MessageBoxA converted lpText from \"%s\" to \"%S\".", lpText, csNewOutputString.Get());
  114. }
  115. CSTRING_CATCH
  116. {
  117. //
  118. // We had a CString failure, call the original API with the original args
  119. //
  120. iReturnValue = ORIGINAL_API(MessageBoxA)(hWnd, lpText, lpCaption, uType);
  121. }
  122. return iReturnValue;
  123. }
  124. /*++
  125. This stub function intercepts all calls to MessageBoxW and prefixes the
  126. output string with "SampleShim says:".
  127. Note that to make your shim generally applicable in an NT environment,
  128. you should include both ANSI and wide-character versions of your stub
  129. function. However, if your shim emulates Win9x behaviour, it is
  130. redundant to include wide-character versions because Win9x did not
  131. support them.
  132. --*/
  133. int
  134. APIHOOK(MessageBoxW)(
  135. HWND hWnd, // handle to owner window
  136. LPCWSTR lpText, // text in message box
  137. LPCWSTR lpCaption, // message box title
  138. UINT uType // message box style
  139. )
  140. {
  141. int iReturnValue;
  142. CSTRING_TRY
  143. {
  144. CString csNewOutputString(lpText);
  145. csNewOutputString.Insert(0, L"SampleShim says: ");
  146. DPFN( eDbgLevelInfo,
  147. "MessageBoxW called with lpText = \"%S\".", lpText);
  148. iReturnValue = ORIGINAL_API(MessageBoxW)(
  149. hWnd,
  150. csNewOutputString,
  151. lpCaption,
  152. uType);
  153. LOGN( eDbgLevelWarning,
  154. "MessageBoxW converted lpText from \"%S\" to \"%S\".",
  155. lpText, csNewOutputString.Get());
  156. }
  157. CSTRING_CATCH
  158. {
  159. iReturnValue = ORIGINAL_API(MessageBoxW)(
  160. hWnd,
  161. lpText,
  162. lpCaption,
  163. uType);
  164. }
  165. return iReturnValue;
  166. }
  167. /*++
  168. Handle DLL_PROCESS_ATTACH, SHIM_STATIC_DLLS_INITIALIZED
  169. and DLL_PROCESS_DETACH in your notify function
  170. to do initialization and uninitialization.
  171. IMPORTANT: Make sure you ONLY call NTDLL and KERNEL32 APIs during
  172. DLL_PROCESS_ATTACH notification. No other DLLs are initialized at that
  173. point.
  174. SHIM_STATIC_DLLS_INITIALIZED is called after all of the application's
  175. DLLs have been initialized.
  176. If your shim cannot initialize properly (during DLL_PROCESS_ATTACH),
  177. return FALSE and none of the APIs specified will be hooked.
  178. --*/
  179. BOOL
  180. NOTIFY_FUNCTION(
  181. DWORD fdwReason)
  182. {
  183. //
  184. // Note that there are further cases besides attach and detach.
  185. //
  186. switch (fdwReason)
  187. {
  188. case DLL_PROCESS_ATTACH:
  189. DPFN( eDbgLevelSpew, "Sample Shim initialized.");
  190. break;
  191. case SHIM_STATIC_DLLS_INITIALIZED:
  192. DPFN( eDbgLevelSpew,
  193. "Sample Shim notification: All DLLs have been loaded.");
  194. break;
  195. case DLL_PROCESS_DETACH:
  196. DPFN( eDbgLevelSpew, "Sample Shim uninitialized.");
  197. break;
  198. default:
  199. break;
  200. }
  201. return TRUE;
  202. }
  203. /*++
  204. Register hooked functions
  205. --*/
  206. HOOK_BEGIN
  207. //
  208. // If you have any initialization to do, you must include this line.
  209. // Then you must implement the NOTIFY_FUNCTION as above.
  210. //
  211. CALL_NOTIFY_FUNCTION
  212. //
  213. // Add APIs that you wish to hook here. All API prototypes
  214. // must be declared in Hooks\inc\ShimProto.h. Compiler errors
  215. // will result if you forget to add them.
  216. //
  217. APIHOOK_ENTRY(USER32.DLL, MessageBoxA)
  218. APIHOOK_ENTRY(USER32.DLL, MessageBoxW)
  219. HOOK_END
  220. IMPLEMENT_SHIM_END