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.

393 lines
9.1 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. IMPLEMENT_SHIM_BEGIN(HandleAPIExceptions)
  29. #include "ShimHookMacro.h"
  30. APIHOOK_ENUM_BEGIN
  31. APIHOOK_ENUM_ENTRY(BackupSeek)
  32. APIHOOK_ENUM_ENTRY(CreateEventA)
  33. APIHOOK_ENUM_ENTRY(CreateEventW)
  34. APIHOOK_ENUM_ENTRY(GetFileAttributesA)
  35. APIHOOK_ENUM_ENTRY(GetFileAttributesW)
  36. APIHOOK_ENUM_ENTRY(VirtualProtect)
  37. APIHOOK_ENUM_ENTRY(GetTextExtentPoint32A)
  38. APIHOOK_ENUM_ENTRY(GetMenuItemInfoA)
  39. APIHOOK_ENUM_ENTRY(wsprintfA)
  40. APIHOOK_ENUM_END
  41. #define MAX_WIN9X_STRSIZE 8192
  42. /*++
  43. Stub returns for bad parameters.
  44. --*/
  45. BOOL
  46. APIHOOK(BackupSeek)(
  47. HANDLE hFile,
  48. DWORD dwLowBytesToSeek,
  49. DWORD dwHighBytesToSeek,
  50. LPDWORD lpdwLowBytesSeeked,
  51. LPDWORD lpdwHighBytesSeeked,
  52. LPVOID *lpContext
  53. )
  54. {
  55. if (!hFile) {
  56. LOGN(
  57. eDbgLevelError,
  58. "[BackupSeek] Bad parameter, returning NULL");
  59. return NULL;
  60. }
  61. DWORD dwLowSeeked, dwHighSeeked;
  62. if (IsBadWritePtr(lpdwLowBytesSeeked, 4)) {
  63. LOGN(
  64. eDbgLevelError,
  65. "[BackupSeek] Bad parameter, fixing");
  66. lpdwLowBytesSeeked = &dwLowSeeked;
  67. }
  68. if (IsBadWritePtr(lpdwHighBytesSeeked, 4)) {
  69. LOGN(
  70. eDbgLevelError,
  71. "[BackupSeek] Bad parameter, fixing");
  72. lpdwHighBytesSeeked = &dwHighSeeked;
  73. }
  74. return ORIGINAL_API(BackupSeek)(hFile, dwLowBytesToSeek, dwHighBytesToSeek,
  75. lpdwLowBytesSeeked, lpdwHighBytesSeeked, lpContext);
  76. }
  77. /*++
  78. Validate parameters
  79. --*/
  80. HANDLE
  81. APIHOOK(CreateEventA)(
  82. LPSECURITY_ATTRIBUTES lpEventAttributes,
  83. BOOL bManualReset,
  84. BOOL bInitialState,
  85. LPCSTR lpName
  86. )
  87. {
  88. if (lpEventAttributes &&
  89. IsBadReadPtr(lpEventAttributes, sizeof(*lpEventAttributes))) {
  90. LOGN(
  91. eDbgLevelError,
  92. "[CreateEventA] Bad parameter, returning NULL");
  93. return NULL;
  94. }
  95. if (lpName &&
  96. IsBadStringPtrA(lpName, MAX_PATH)) {
  97. LOGN(
  98. eDbgLevelError,
  99. "[CreateEventA] Bad parameter, returning NULL");
  100. return NULL;
  101. }
  102. return (ORIGINAL_API(CreateEventA)(lpEventAttributes, bManualReset,
  103. bInitialState, lpName));
  104. }
  105. /*++
  106. Validate parameters
  107. --*/
  108. HANDLE
  109. APIHOOK(CreateEventW)(
  110. LPSECURITY_ATTRIBUTES lpEventAttributes,
  111. BOOL bManualReset,
  112. BOOL bInitialState,
  113. LPCWSTR lpName
  114. )
  115. {
  116. if (lpEventAttributes &&
  117. IsBadReadPtr(lpEventAttributes, sizeof(*lpEventAttributes))) {
  118. LOGN(
  119. eDbgLevelError,
  120. "[CreateEventW] Bad parameter, returning NULL");
  121. return NULL;
  122. }
  123. if (lpName &&
  124. IsBadStringPtrW(lpName, MAX_PATH)) {
  125. LOGN(
  126. eDbgLevelError,
  127. "[CreateEventW] Bad parameter, returning NULL");
  128. return NULL;
  129. }
  130. return (ORIGINAL_API(CreateEventW)(lpEventAttributes, bManualReset,
  131. bInitialState, lpName));
  132. }
  133. /*++
  134. This function to emulate Win9x behaviour when getting file attributes.
  135. --*/
  136. DWORD
  137. APIHOOK(GetFileAttributesA)(
  138. LPCSTR lpFileName
  139. )
  140. {
  141. DWORD dwFileAttributes = INVALID_FILE_ATTRIBUTES;
  142. if (!IsBadStringPtrA(lpFileName, MAX_PATH)) {
  143. dwFileAttributes = ORIGINAL_API(GetFileAttributesA)(
  144. lpFileName);
  145. } else {
  146. LOGN(
  147. eDbgLevelError,
  148. "[GetFileAttributesA] Bad parameter - returning INVALID_FILE_ATTRIBUTES.");
  149. }
  150. return dwFileAttributes;
  151. }
  152. /*++
  153. This function is used to emulate Win9x behaviour when getting file attributes.
  154. --*/
  155. DWORD
  156. APIHOOK(GetFileAttributesW)(
  157. LPCWSTR lpFileName
  158. )
  159. {
  160. DWORD dwFileAttributes = INVALID_FILE_ATTRIBUTES;
  161. if (!IsBadStringPtrW(lpFileName, MAX_PATH)) {
  162. dwFileAttributes = ORIGINAL_API(GetFileAttributesW)(
  163. lpFileName);
  164. } else {
  165. LOGN(
  166. eDbgLevelError,
  167. "[GetFileAttributesW] Bad parameter - returning INVALID_FILE_ATTRIBUTES.");
  168. }
  169. return dwFileAttributes;
  170. }
  171. /*++
  172. Win9x allowed the last parameter to be NULL.
  173. --*/
  174. BOOL
  175. APIHOOK(VirtualProtect)(
  176. LPVOID lpAddress,
  177. SIZE_T dwSize,
  178. DWORD flNewProtect,
  179. PDWORD lpflOldProtect
  180. )
  181. {
  182. DWORD dwOldProtect = 0;
  183. if (!lpflOldProtect) {
  184. //
  185. // Detected a bad last parameter, fix it.
  186. //
  187. LOGN(eDbgLevelError, "[VirtualProtect] Bad parameter - fixing");
  188. lpflOldProtect = &dwOldProtect;
  189. }
  190. return ORIGINAL_API(VirtualProtect)(lpAddress, dwSize, flNewProtect, lpflOldProtect);
  191. }
  192. /*++
  193. Win9x only allows 8192 for the size of the string
  194. --*/
  195. BOOL
  196. APIHOOK(GetTextExtentPoint32A)(
  197. HDC hdc,
  198. LPCSTR lpString,
  199. int cbString,
  200. LPSIZE lpSize
  201. )
  202. {
  203. if (cbString > MAX_WIN9X_STRSIZE) {
  204. //
  205. // Detected a bad string size, fix it.
  206. //
  207. if (!IsBadStringPtrA(lpString, cbString)) {
  208. cbString = strlen(lpString);
  209. LOGN(eDbgLevelError, "[GetTextExtentPoint32A] Bad parameter - fixing");
  210. } else {
  211. LOGN(eDbgLevelError, "[GetTextExtentPoint32A] Bad parameter - returning FALSE");
  212. return FALSE;
  213. }
  214. }
  215. return ORIGINAL_API(GetTextExtentPoint32A)(hdc, lpString, cbString, lpSize);
  216. }
  217. /*++
  218. Emulate Win9x bad pointer protection.
  219. --*/
  220. BOOL
  221. APIHOOK(GetMenuItemInfoA)(
  222. HMENU hMenu, // handle to menu
  223. UINT uItem, // menu item
  224. BOOL fByPosition, // meaning of uItem
  225. LPMENUITEMINFO lpmii // menu item information
  226. )
  227. {
  228. if (IsBadWritePtr(lpmii, sizeof(*lpmii))) {
  229. LOGN(eDbgLevelInfo, "[GetMenuItemInfoA] invalid lpmii pointer, returning FALSE");
  230. return FALSE;
  231. }
  232. if ((lpmii->fMask & MIIM_STRING || lpmii->fMask & MIIM_TYPE) && (lpmii->cch !=0)) {
  233. MENUITEMINFO MyMII={0};
  234. ULONG cch;
  235. MyMII.cbSize = sizeof(MyMII);
  236. MyMII.fMask = MIIM_STRING;
  237. if (ORIGINAL_API(GetMenuItemInfoA)(hMenu, uItem, fByPosition, &MyMII)) {
  238. cch = min(lpmii->cch, MyMII.cch + 1);
  239. if (IsBadWritePtr(lpmii->dwTypeData, cch)) {
  240. LOGN(eDbgLevelInfo, "[GetMenuItemInfoA] invalid pointer for string, clearing it");
  241. lpmii->dwTypeData = 0;
  242. }
  243. } else {
  244. DPFN(eDbgLevelError, "[GetMenuItemInfoA] Internal call to find string size fail (%08X)", GetLastError());
  245. }
  246. }
  247. return ORIGINAL_API(GetMenuItemInfoA)(hMenu, uItem, fByPosition, lpmii);
  248. }
  249. /*++
  250. Make sure format string for wsprintfA is not NULL
  251. --*/
  252. //Avoid wvsprintfA deprecated warning/error
  253. #pragma warning(disable : 4995)
  254. int
  255. APIHOOK(wsprintfA)(
  256. LPSTR lpOut,
  257. LPCSTR lpFmt,
  258. ...)
  259. {
  260. int iRet = 0;
  261. //
  262. // lpFmt can't be NULL, wvsprintfA throw AV
  263. //
  264. if (lpFmt == NULL) {
  265. if (!IsBadWritePtr(lpOut, 1)) {
  266. *lpOut = '\0';
  267. }
  268. DPFN( eDbgLevelInfo, "[wsprintfA] received NULL as format string");
  269. return iRet;
  270. }
  271. va_list arglist;
  272. va_start(arglist, lpFmt);
  273. iRet = wvsprintfA(lpOut, lpFmt, arglist);
  274. va_end(arglist);
  275. return iRet;
  276. }
  277. //Enable back deprecated warning/error
  278. #pragma warning(default : 4995)
  279. /*++
  280. Register hooked functions
  281. --*/
  282. HOOK_BEGIN
  283. APIHOOK_ENTRY(KERNEL32.DLL, BackupSeek)
  284. APIHOOK_ENTRY(KERNEL32.DLL, CreateEventA)
  285. APIHOOK_ENTRY(KERNEL32.DLL, CreateEventW)
  286. APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesA)
  287. APIHOOK_ENTRY(KERNEL32.DLL, GetFileAttributesW)
  288. APIHOOK_ENTRY(KERNEL32.DLL, VirtualProtect)
  289. APIHOOK_ENTRY(GDI32.DLL, GetTextExtentPoint32A)
  290. APIHOOK_ENTRY(USER32.DLL, GetMenuItemInfoA)
  291. APIHOOK_ENTRY(USER32.DLL, wsprintfA)
  292. HOOK_END
  293. IMPLEMENT_SHIM_END