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.

394 lines
8.7 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name:
  4. HandleAPIExceptions.cpp
  5. Abstract:
  6. Handle exceptions thrown by APIs that used to simply fail on Win9x. So far
  7. we have:
  8. 1. BackupSeek: AVs if hFile == NULL
  9. 2. CreateEvent passed bad lpEventAttributes and/or lpName
  10. 3. GetFileAttributes
  11. Also emulate the win9x behavior for VirtualProtect, whereby the last
  12. parameter can be NULL.
  13. GetTextExtentPoint32 AV's when a large/uninitialized value is passed for
  14. the string length. This API now emulates Win9x.
  15. Add sanity checks to pointers in the call to GetMenuItemInfo. This is to match 9x, as
  16. some apps to pass bogus pointers and it AV on NT.
  17. When wsprintf receives lpFormat argument as NULL, no AV on 9x.
  18. But it AV on XP.Shim verifies format string, if it is NULL return the call don't forward
  19. Notes:
  20. This is a general purpose shim.
  21. History:
  22. 04/03/2000 linstev Created
  23. 04/01/2001 linstev Munged with other exception handling shims
  24. 07/11/2001 prashkud Added handling for GetTextExtentPoint32
  25. 04/24/2002 v-ramora Added handling for wsprintfA
  26. --*/
  27. #include "precomp.h"
  28. #include "LegalStr.h"
  29. IMPLEMENT_SHIM_BEGIN(HandleAPIExceptions)
  30. #include "ShimHookMacro.h"
  31. APIHOOK_ENUM_BEGIN
  32. APIHOOK_ENUM_ENTRY(BackupSeek)
  33. APIHOOK_ENUM_ENTRY(CreateEventA)
  34. APIHOOK_ENUM_ENTRY(CreateEventW)
  35. APIHOOK_ENUM_ENTRY(GetFileAttributesA)
  36. APIHOOK_ENUM_ENTRY(GetFileAttributesW)
  37. APIHOOK_ENUM_ENTRY(VirtualProtect)
  38. APIHOOK_ENUM_ENTRY(GetTextExtentPoint32A)
  39. APIHOOK_ENUM_ENTRY(GetMenuItemInfoA)
  40. APIHOOK_ENUM_ENTRY(wsprintfA)
  41. APIHOOK_ENUM_END
  42. #define MAX_WIN9X_STRSIZE 8192
  43. /*++
  44. Stub returns for bad parameters.
  45. --*/
  46. BOOL
  47. APIHOOK(BackupSeek)(
  48. HANDLE hFile,
  49. DWORD dwLowBytesToSeek,
  50. DWORD dwHighBytesToSeek,
  51. LPDWORD lpdwLowBytesSeeked,
  52. LPDWORD lpdwHighBytesSeeked,
  53. LPVOID *lpContext
  54. )
  55. {
  56. if (!hFile) {
  57. LOGN(
  58. eDbgLevelError,
  59. "[BackupSeek] Bad parameter, returning NULL");
  60. return NULL;
  61. }
  62. DWORD dwLowSeeked, dwHighSeeked;
  63. if (IsBadWritePtr(lpdwLowBytesSeeked, 4)) {
  64. LOGN(
  65. eDbgLevelError,
  66. "[BackupSeek] Bad parameter, fixing");
  67. lpdwLowBytesSeeked = &dwLowSeeked;
  68. }
  69. if (IsBadWritePtr(lpdwHighBytesSeeked, 4)) {
  70. LOGN(
  71. eDbgLevelError,
  72. "[BackupSeek] Bad parameter, fixing");
  73. lpdwHighBytesSeeked = &dwHighSeeked;
  74. }
  75. return ORIGINAL_API(BackupSeek)(hFile, dwLowBytesToSeek, dwHighBytesToSeek,
  76. lpdwLowBytesSeeked, lpdwHighBytesSeeked, lpContext);
  77. }
  78. /*++
  79. Validate parameters
  80. --*/
  81. HANDLE
  82. APIHOOK(CreateEventA)(
  83. LPSECURITY_ATTRIBUTES lpEventAttributes,
  84. BOOL bManualReset,
  85. BOOL bInitialState,
  86. LPCSTR lpName
  87. )
  88. {
  89. if (lpEventAttributes &&
  90. IsBadReadPtr(lpEventAttributes, sizeof(*lpEventAttributes))) {
  91. LOGN(
  92. eDbgLevelError,
  93. "[CreateEventA] Bad parameter, returning NULL");
  94. return NULL;
  95. }
  96. if (lpName &&
  97. IsBadStringPtrA(lpName, MAX_PATH)) {
  98. LOGN(
  99. eDbgLevelError,
  100. "[CreateEventA] Bad parameter, returning NULL");
  101. return NULL;
  102. }
  103. return (ORIGINAL_API(CreateEventA)(lpEventAttributes, bManualReset,
  104. bInitialState, lpName));
  105. }
  106. /*++
  107. Validate parameters
  108. --*/
  109. HANDLE
  110. APIHOOK(CreateEventW)(
  111. LPSECURITY_ATTRIBUTES lpEventAttributes,
  112. BOOL bManualReset,
  113. BOOL bInitialState,
  114. LPCWSTR lpName
  115. )
  116. {
  117. if (lpEventAttributes &&
  118. IsBadReadPtr(lpEventAttributes, sizeof(*lpEventAttributes))) {
  119. LOGN(
  120. eDbgLevelError,
  121. "[CreateEventW] Bad parameter, returning NULL");
  122. return NULL;
  123. }
  124. if (lpName &&
  125. IsBadStringPtrW(lpName, MAX_PATH)) {
  126. LOGN(
  127. eDbgLevelError,
  128. "[CreateEventW] Bad parameter, returning NULL");
  129. return NULL;
  130. }
  131. return (ORIGINAL_API(CreateEventW)(lpEventAttributes, bManualReset,
  132. bInitialState, lpName));
  133. }
  134. /*++
  135. This function to emulate Win9x behaviour when getting file attributes.
  136. --*/
  137. DWORD
  138. APIHOOK(GetFileAttributesA)(
  139. LPCSTR lpFileName
  140. )
  141. {
  142. DWORD dwFileAttributes = INVALID_FILE_ATTRIBUTES;
  143. if (!IsBadStringPtrA(lpFileName, MAX_PATH)) {
  144. dwFileAttributes = ORIGINAL_API(GetFileAttributesA)(
  145. lpFileName);
  146. } else {
  147. LOGN(
  148. eDbgLevelError,
  149. "[GetFileAttributesA] Bad parameter - returning INVALID_FILE_ATTRIBUTES.");
  150. }
  151. return dwFileAttributes;
  152. }
  153. /*++
  154. This function is used to emulate Win9x behaviour when getting file attributes.
  155. --*/
  156. DWORD
  157. APIHOOK(GetFileAttributesW)(
  158. LPCWSTR lpFileName
  159. )
  160. {
  161. DWORD dwFileAttributes = INVALID_FILE_ATTRIBUTES;
  162. if (!IsBadStringPtrW(lpFileName, MAX_PATH)) {
  163. dwFileAttributes = ORIGINAL_API(GetFileAttributesW)(
  164. lpFileName);
  165. } else {
  166. LOGN(
  167. eDbgLevelError,
  168. "[GetFileAttributesW] Bad parameter - returning INVALID_FILE_ATTRIBUTES.");
  169. }
  170. return dwFileAttributes;
  171. }
  172. /*++
  173. Win9x allowed the last parameter to be NULL.
  174. --*/
  175. BOOL
  176. APIHOOK(VirtualProtect)(
  177. LPVOID lpAddress,
  178. SIZE_T dwSize,
  179. DWORD flNewProtect,
  180. PDWORD lpflOldProtect
  181. )
  182. {
  183. DWORD dwOldProtect = 0;
  184. if (!lpflOldProtect) {
  185. //
  186. // Detected a bad last parameter, fix it.
  187. //
  188. LOGN(eDbgLevelError, "[VirtualProtect] Bad parameter - fixing");
  189. lpflOldProtect = &dwOldProtect;
  190. }
  191. return ORIGINAL_API(VirtualProtect)(lpAddress, dwSize, flNewProtect, lpflOldProtect);
  192. }
  193. /*++
  194. Win9x only allows 8192 for the size of the string
  195. --*/
  196. BOOL
  197. APIHOOK(GetTextExtentPoint32A)(
  198. HDC hdc,
  199. LPCSTR lpString,
  200. int cbString,
  201. LPSIZE lpSize
  202. )
  203. {
  204. if (cbString > MAX_WIN9X_STRSIZE) {
  205. //
  206. // Detected a bad string size, fix it.
  207. //
  208. if (!IsBadStringPtrA(lpString, cbString)) {
  209. cbString = strlen(lpString);
  210. LOGN(eDbgLevelError, "[GetTextExtentPoint32A] Bad parameter - fixing");
  211. } else {
  212. LOGN(eDbgLevelError, "[GetTextExtentPoint32A] Bad parameter - returning FALSE");
  213. return FALSE;
  214. }
  215. }
  216. return ORIGINAL_API(GetTextExtentPoint32A)(hdc, lpString, cbString, lpSize);
  217. }
  218. /*++
  219. Emulate Win9x bad pointer protection.
  220. --*/
  221. BOOL
  222. APIHOOK(GetMenuItemInfoA)(
  223. HMENU hMenu, // handle to menu
  224. UINT uItem, // menu item
  225. BOOL fByPosition, // meaning of uItem
  226. LPMENUITEMINFO lpmii // menu item information
  227. )
  228. {
  229. if (IsBadWritePtr(lpmii, sizeof(*lpmii))) {
  230. LOGN(eDbgLevelInfo, "[GetMenuItemInfoA] invalid lpmii pointer, returning FALSE");
  231. return FALSE;
  232. }
  233. if ((lpmii->fMask & MIIM_STRING || lpmii->fMask & MIIM_TYPE) && (lpmii->cch !=0)) {
  234. MENUITEMINFO MyMII={0};
  235. ULONG cch;
  236. MyMII.cbSize = sizeof(MyMII);
  237. MyMII.fMask = MIIM_STRING;
  238. if (ORIGINAL_API(GetMenuItemInfoA)(hMenu, uItem, fByPosition, &MyMII)) {
  239. cch = min(lpmii->cch, MyMII.cch + 1);
  240. if (IsBadWritePtr(lpmii->dwTypeData, cch)) {
  241. LOGN(eDbgLevelInfo, "[GetMenuItemInfoA] invalid pointer for string, clearing it");
  242. lpmii->dwTypeData = 0;
  243. }
  244. } else {
  245. DPFN(eDbgLevelError, "[GetMenuItemInfoA] Internal call to find string size fail (%08X)", GetLastError());
  246. }
  247. }
  248. return ORIGINAL_API(GetMenuItemInfoA)(hMenu, uItem, fByPosition, lpmii);
  249. }
  250. /*++
  251. Make sure format string for wsprintfA is not NULL
  252. --*/
  253. //Avoid wvsprintfA deprecated warning/error
  254. #pragma warning(disable : 4995)
  255. int
  256. APIHOOK(wsprintfA)(
  257. LPSTR lpOut,
  258. LPCSTR lpFmt,
  259. ...)
  260. {
  261. int iRet = 0;
  262. //
  263. // lpFmt can't be NULL, wvsprintfA throw AV
  264. //
  265. if (lpFmt == NULL) {
  266. if (!IsBadWritePtr(lpOut, 1)) {
  267. *lpOut = '\0';
  268. }
  269. DPFN( eDbgLevelInfo, "[wsprintfA] received NULL as format string");
  270. return iRet;
  271. }
  272. va_list arglist;
  273. va_start(arglist, lpFmt);
  274. iRet = wvsprintfA(lpOut, lpFmt, arglist);
  275. va_end(arglist);
  276. return iRet;
  277. }
  278. //Enable back deprecated warning/error
  279. #pragma warning(default : 4995)
  280. /*++
  281. Register hooked functions
  282. --*/
  283. HOOK_BEGIN
  284. APIHOOK_ENTRY(KERNEL32.DLL, BackupSeek)
  285. APIHOOK_ENTRY(KERNEL32.DLL, CreateEventA)
  286. APIHOOK_ENTRY(KERNEL32.DLL, CreateEventW)
  287. APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesA)
  288. APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesW)
  289. APIHOOK_ENTRY(KERNEL32.DLL, VirtualProtect)
  290. APIHOOK_ENTRY(GDI32.DLL, GetTextExtentPoint32A)
  291. APIHOOK_ENTRY(USER32.DLL, GetMenuItemInfoA)
  292. APIHOOK_ENTRY(USER32.DLL, wsprintfA)
  293. HOOK_END
  294. IMPLEMENT_SHIM_END