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.

434 lines
12 KiB

  1. //
  2. // Windows NT WOW v5
  3. //
  4. // fmtmsg.c -- 16-bit FormatMessage API, lifted from Win95
  5. // \win\core\user\wn32rare.c by Dave Hart
  6. //
  7. //
  8. #include "user.h"
  9. typedef DWORD ULONG;
  10. // from win95 user.h
  11. #define CODESEG _based(_segname("_CODE"))
  12. #define TESTFAR(p) SELECTOROF(p)
  13. // from win95 dev\inc16\windows.h
  14. #define FORMAT_MESSAGE_ALLOCATE_BUFFER 0x00000100 /* ;Internal NT */
  15. #define FORMAT_MESSAGE_IGNORE_INSERTS 0x00000200 /* ;Internal NT */
  16. #define FORMAT_MESSAGE_FROM_STRING 0x00000400 /* ;Internal NT */
  17. #define FORMAT_MESSAGE_FROM_HMODULE 0x00000800 /* ;Internal NT */
  18. #define FORMAT_MESSAGE_FROM_SYSTEM 0x00001000 /* ;Internal NT */
  19. //#define FORMAT_MESSAGE_ARGUMENT_ARRAY 0x00002000 /* ;Internal */
  20. #define FORMAT_MESSAGE_MAX_WIDTH_MASK 0x000000FF /* ;Internal NT */
  21. #define FORMAT_MESSAGE_VALID 0x00003FFF /* ;Internal */
  22. char CODESEG szStringFormat[] = "%s";
  23. char CODESEG szStringFormat2[] = "%%%lu";
  24. char CODESEG szStringFormat3[] = "%%%lu!%s!";
  25. #if 0
  26. // ----------------------------------------------------------------------------
  27. //
  28. // GetSystemInstance()
  29. //
  30. // _loadds function to return hInstanceWin. Needed cuz FormatMessage can
  31. // LocalAlloc a buffer for an app. We GlobalAlloc() a temp buffer to do the
  32. // actual work in. Both local & global memory go away when the context that
  33. // created it terminates.
  34. //
  35. // ----------------------------------------------------------------------------
  36. HINSTANCE NEAR _loadds FMGetSystemInstance(void)
  37. {
  38. return(hInstanceWin);
  39. }
  40. #endif
  41. #undef LocalAlloc
  42. #undef LocalFree
  43. extern HLOCAL WINAPI LocalAlloc(UINT, UINT);
  44. extern HLOCAL WINAPI LocalFree(HLOCAL);
  45. // ----------------------------------------------------------------------------
  46. //
  47. // FormatMessage()
  48. //
  49. // 16-bit version of FormatMessage32().
  50. //
  51. // Note that this API is NOT _loadds. We might need to LocalAlloc() a buffer
  52. // for the result. Therefore, we can't just use random static string vars.
  53. // They _must_ be CODESEG.
  54. //
  55. // ----------------------------------------------------------------------------
  56. UINT _far _pascal FormatMessage(DWORD dwFlags, LPVOID lpSource, UINT idMessage,
  57. UINT idLanguage, LPSTR lpResult, UINT cbResultMax, DWORD FAR * rglArgs)
  58. {
  59. LPSTR lpBuffer;
  60. HINSTANCE hInstance;
  61. UINT Column;
  62. UINT MaximumWidth;
  63. DWORD rgInserts[100];
  64. WORD MaxInsert, CurInsert;
  65. UINT cbNeeded, cbResult;
  66. char szMessage[256];
  67. LPSTR MessageFormat;
  68. UINT cbMessage;
  69. UINT PrintParameterCount;
  70. DWORD PrintParameter1;
  71. DWORD PrintParameter2;
  72. char PrintFormatString[32];
  73. LPSTR s, s1, s1base;
  74. LPSTR lpAlloc;
  75. LPSTR lpDst, lpDstBeg;
  76. //
  77. // Force idLanguage to be 0 for 16-bit apps, for now...
  78. //
  79. if (idLanguage)
  80. {
  81. DebugErr(DBF_ERROR, "FormatMessage: language id must be 0");
  82. return(0);
  83. }
  84. //
  85. // Prevent NULL lpResult
  86. //
  87. if (!TESTFAR(lpResult))
  88. {
  89. DebugErr(DBF_ERROR, "FormatMessage: NULL result buffer");
  90. return(0);
  91. }
  92. //
  93. // Prevent caller from using non-defined flags...
  94. //
  95. if (dwFlags & ~FORMAT_MESSAGE_VALID)
  96. {
  97. DebugErr(DBF_ERROR, "FormatMessage: invalid flags");
  98. return(0);
  99. }
  100. //
  101. // Get temporary buffer.
  102. //
  103. if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  104. cbResultMax = 0x7FFE;
  105. lpBuffer = MAKELP(GlobalAlloc(GHND, (DWORD)cbResultMax+1), 0);
  106. if (!SELECTOROF(lpBuffer))
  107. {
  108. DebugErr(DBF_ERROR, "FormatMessage: Couldn't allocate enough memory");
  109. return(0);
  110. }
  111. lpAlloc = NULL;
  112. cbResult = 0;
  113. MaximumWidth = LOWORD(dwFlags & FORMAT_MESSAGE_MAX_WIDTH_MASK);
  114. //
  115. // Get message string
  116. //
  117. if (dwFlags & FORMAT_MESSAGE_FROM_STRING)
  118. {
  119. if (!TESTFAR(lpSource))
  120. {
  121. DebugErr(DBF_ERROR, "FormatMessage: NULL format string");
  122. goto FailureExit;
  123. }
  124. MessageFormat = lpSource;
  125. cbMessage = lstrlen(MessageFormat);
  126. }
  127. else
  128. {
  129. if (dwFlags & FORMAT_MESSAGE_FROM_HMODULE)
  130. {
  131. hInstance = (HINSTANCE)OFFSETOF(lpSource);
  132. if (!hInstance)
  133. {
  134. DebugErr(DBF_ERROR, "FormatMessage: NULL hInstance not allowed for 16 bits");
  135. goto FailureExit;
  136. }
  137. }
  138. else if (dwFlags & FORMAT_MESSAGE_FROM_SYSTEM)
  139. #if 0
  140. // This doesn't work on WOW and it's not worth
  141. // fixing because our user.exe doesn't have any
  142. // FormatMessage text as string resources.
  143. hInstance = FMGetSystemInstance();
  144. #else
  145. {
  146. DebugErr(DBF_ERROR, "FormatMessage: FORMAT_MESSAGE_FROM_SYSTEM");
  147. goto FailureExit;
  148. }
  149. #endif
  150. else
  151. {
  152. DebugErr(DBF_ERROR, "FormatMessage: Invalid source");
  153. goto FailureExit;
  154. }
  155. //
  156. // Load the string
  157. //
  158. cbMessage = LoadString(hInstance, idMessage, szMessage,
  159. sizeof(szMessage)-1);
  160. if (!cbMessage)
  161. {
  162. DebugErr(DBF_ERROR, "FormatMessage: Couldn't load source string");
  163. goto FailureExit;
  164. }
  165. MessageFormat = (LPSTR)szMessage;
  166. }
  167. lpDst = lpBuffer;
  168. MaxInsert = 0;
  169. Column = 0;
  170. s = MessageFormat;
  171. while (*s)
  172. {
  173. if (*s == '%')
  174. {
  175. s++;
  176. lpDstBeg = lpDst;
  177. if (*s >= '1' && *s <= '9')
  178. {
  179. CurInsert = *s++ - '0';
  180. if (*s >= '0' && *s <= '9')
  181. {
  182. CurInsert = (CurInsert * 10) + (*s++ - '0');
  183. }
  184. CurInsert--;
  185. PrintParameterCount = 0;
  186. if (*s == '!')
  187. {
  188. s1 = s1base = PrintFormatString;
  189. *s1++ = '%';
  190. s++;
  191. while (*s != '!')
  192. {
  193. if (*s != '\0')
  194. {
  195. if (s1 >= (s1base + sizeof(PrintFormatString) - 1))
  196. {
  197. goto ParamError;
  198. }
  199. if (*s == '*')
  200. {
  201. if (PrintParameterCount++ > 1)
  202. {
  203. goto ParamError;
  204. }
  205. }
  206. *s1++ = *s++;
  207. }
  208. else
  209. {
  210. ParamError:
  211. DebugErr(DBF_ERROR, "FormatMessage: Invalid format string");
  212. goto FailureExit;
  213. }
  214. }
  215. s++;
  216. *s1 = '\0';
  217. }
  218. else
  219. {
  220. lstrcpy(PrintFormatString, szStringFormat);
  221. s1 = PrintFormatString + lstrlen(PrintFormatString);
  222. }
  223. if (!(dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS) && TESTFAR(rglArgs))
  224. {
  225. while (CurInsert >= MaxInsert)
  226. {
  227. rgInserts[MaxInsert++] = *(rglArgs++);
  228. }
  229. s1 = (LPSTR)rgInserts[CurInsert];
  230. PrintParameter1 = 0;
  231. PrintParameter2 = 0;
  232. if (PrintParameterCount > 0)
  233. {
  234. PrintParameter1 = rgInserts[MaxInsert++] = *(rglArgs++);
  235. if (PrintParameterCount > 1)
  236. {
  237. PrintParameter2 = rgInserts[MaxInsert++] = *(rglArgs++);
  238. }
  239. }
  240. lpDst += wsprintf(lpDst, PrintFormatString, s1,
  241. PrintParameter1, PrintParameter2);
  242. }
  243. else if (!lstrcmp(PrintFormatString, szStringFormat))
  244. {
  245. lpDst += wsprintf(lpDst, szStringFormat2, CurInsert+1);
  246. }
  247. else
  248. {
  249. lpDst += wsprintf(lpDst, szStringFormat3, CurInsert+1,
  250. (LPSTR)&PrintFormatString[1]);
  251. }
  252. }
  253. else if (*s == '0')
  254. break;
  255. else if (!*s)
  256. goto FailureExit;
  257. else if (*s == '!')
  258. {
  259. *lpDst++ = '!';
  260. s++;
  261. }
  262. else if (*s == 't')
  263. {
  264. *lpDst++ = '\t';
  265. s++;
  266. if (Column % 8)
  267. {
  268. Column = (Column + 7) & ~7;
  269. }
  270. else
  271. {
  272. Column += 8;
  273. }
  274. }
  275. else if (*s == 'b')
  276. {
  277. *lpDst++ = ' ';
  278. s++;
  279. }
  280. else if (*s == 'r')
  281. {
  282. *lpDst++ = '\r';
  283. s++;
  284. lpDstBeg = NULL;
  285. }
  286. else if (*s == '\n')
  287. {
  288. *lpDst++ = '\r';
  289. *lpDst++ = '\n';
  290. s++;
  291. lpDstBeg = NULL;
  292. }
  293. else
  294. {
  295. if (dwFlags & FORMAT_MESSAGE_IGNORE_INSERTS)
  296. {
  297. *lpDst++ = '%';
  298. }
  299. *lpDst++ = *s++;
  300. }
  301. if (!TESTFAR(lpDstBeg))
  302. {
  303. Column = 0;
  304. }
  305. else
  306. {
  307. Column += lpDst - lpDstBeg;
  308. }
  309. }
  310. else
  311. {
  312. char c;
  313. c = *s++;
  314. if (c == '\r')
  315. {
  316. if (*s == '\n')
  317. {
  318. s++;
  319. }
  320. if (MaximumWidth)
  321. {
  322. c = ' ';
  323. }
  324. else
  325. {
  326. c = '\n';
  327. }
  328. }
  329. if (c == '\n' || (c == ' ' && MaximumWidth &&
  330. MaximumWidth != FORMAT_MESSAGE_MAX_WIDTH_MASK &&
  331. Column >= MaximumWidth))
  332. {
  333. *lpDst++ = '\r';
  334. *lpDst++ = '\n';
  335. Column = 0;
  336. }
  337. else
  338. {
  339. *lpDst++ = c;
  340. Column++;
  341. }
  342. }
  343. }
  344. *lpDst++ = 0;
  345. cbNeeded = lpDst - lpBuffer;
  346. if (dwFlags & FORMAT_MESSAGE_ALLOCATE_BUFFER)
  347. {
  348. PSTR pstr;
  349. *(PSTR FAR *)lpResult = NULL;
  350. pstr = (PSTR)LocalAlloc(LPTR, cbNeeded);
  351. if (!pstr)
  352. {
  353. DebugErr(DBF_ERROR, "FormatMessge: couldn't LocalAlloc memory for result");
  354. goto FailureExit;
  355. }
  356. lpDst = lpAlloc = (LPSTR)pstr;
  357. }
  358. else if (cbNeeded > cbResultMax)
  359. {
  360. DebugErr(DBF_ERROR, "FormatMessage: passed in buffer is too small for result");
  361. goto FailureExit;
  362. }
  363. else
  364. {
  365. lpDst = lpResult;
  366. }
  367. lstrcpyn(lpDst, lpBuffer, cbNeeded);
  368. cbResult = --cbNeeded;
  369. FailureExit:
  370. if (TESTFAR(lpAlloc))
  371. {
  372. if (cbResult)
  373. {
  374. *(PSTR FAR *)lpResult = (PSTR)OFFSETOF(lpAlloc);
  375. }
  376. else
  377. {
  378. LocalFree((HANDLE)OFFSETOF(lpAlloc));
  379. }
  380. }
  381. if (TESTFAR(lpBuffer))
  382. GlobalFree((HANDLE)SELECTOROF(lpBuffer));
  383. return(cbResult);
  384. }