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.

452 lines
8.5 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. sprintf.c
  5. Abstract:
  6. Implements Windows friendly versions of sprintf and vsprintf
  7. Author:
  8. Revision History:
  9. 2/15/89 craigc Initial
  10. 4/6/93 ROBWI For VxD
  11. --*/
  12. #include "precomp.h"
  13. #pragma hdrstop
  14. #pragma code_seg("PAGE")
  15. #include <stdlib.h>
  16. #include <ctype.h>
  17. #include <string.h>
  18. #ifndef CSC_RECORDMANAGER_WINNT
  19. #include "basedef.h"
  20. #include "vmm.h"
  21. #pragma VxD_LOCKED_CODE_SEG
  22. #endif //ifndef CSC_RECORDMANAGER_WINNT
  23. #include "vxdwraps.h"
  24. #define WSPRINTF_LIMIT 1024
  25. #define DEBUG_BUFFER_SIZE 16376
  26. extern int SP_PutNumber(char *, long, int, int, int);
  27. extern void SP_Reverse(char * lp1, char * lp2);
  28. DWORD DebugBufferLength = 0;
  29. char * DebugBuffer;
  30. #define out(c) if (--cchLimit) *lpOut++=(c); else goto errorout
  31. #pragma intrinsic (memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen)
  32. /*
  33. * GetFmtValue
  34. *
  35. * reads a width or precision value from the format string
  36. */
  37. char * SP_GetFmtValue(char * lpch, int * lpw)
  38. {
  39. register int i=0;
  40. while (*lpch>='0' && *lpch<='9')
  41. {
  42. i *= 10;
  43. i += (int)(*lpch-'0');
  44. lpch++;
  45. }
  46. *lpw=i;
  47. /* return the address of the first non-digit character */
  48. return lpch;
  49. }
  50. /*
  51. * vsprintf()
  52. *
  53. * VxD version of vsprintf(). Does not support floating point or
  54. * pointer types, and all strings are assumed to be NEAR. Supports only
  55. * the left alignment flag.
  56. *
  57. * Takes pointers to an output buffer, where the string is built, a
  58. * pointer to an input buffer, and a pointer to a list of parameters.
  59. *
  60. */
  61. int vxd_vsprintf(char * lpOut, char * lpFmt, CONST VOID * lpParms)
  62. {
  63. int left;
  64. char prefix;
  65. register int width;
  66. register int prec;
  67. char fillch;
  68. int size;
  69. int sign;
  70. int radix;
  71. int upper;
  72. int cchLimit=WSPRINTF_LIMIT;
  73. int cch;
  74. char * lpT;
  75. union {
  76. long l;
  77. ULONG ul;
  78. char sz[sizeof(long)];
  79. } val;
  80. int fWideChar;
  81. while (*lpFmt)
  82. {
  83. if (*lpFmt=='%')
  84. {
  85. /* read the flags. These can be in any order */
  86. left=0;
  87. prefix=0;
  88. fWideChar = 0;
  89. while (*++lpFmt)
  90. {
  91. if (*lpFmt=='-')
  92. left++;
  93. else if (*lpFmt=='#')
  94. prefix++;
  95. else
  96. break;
  97. }
  98. /* find fill character */
  99. if (*lpFmt=='0')
  100. {
  101. fillch='0';
  102. lpFmt++;
  103. }
  104. else
  105. fillch=' ';
  106. /* read the width specification */
  107. lpFmt=SP_GetFmtValue(lpFmt,&cch);
  108. width=cch;
  109. /* read the precision */
  110. if (*lpFmt=='.')
  111. {
  112. lpFmt=SP_GetFmtValue(++lpFmt,&cch);
  113. prec=cch;
  114. }
  115. else
  116. prec=-1;
  117. /* get the operand size */
  118. if (*lpFmt=='l')
  119. {
  120. size=1;
  121. lpFmt++;
  122. }
  123. else
  124. {
  125. size=0;
  126. if (*lpFmt=='h')
  127. lpFmt++;
  128. }
  129. upper=0;
  130. sign=0;
  131. radix=10;
  132. switch (*lpFmt)
  133. {
  134. case 0:
  135. goto errorout;
  136. case 'i':
  137. case 'd':
  138. sign++;
  139. case 'u':
  140. /* turn off prefix if decimal */
  141. prefix=0;
  142. donumeric:
  143. /* special cases to act like MSC v5.10 */
  144. if (left || prec>=0)
  145. fillch=' ';
  146. if (size)
  147. val.l=*((long *)lpParms)++;
  148. else
  149. if (sign)
  150. val.l=*((long *)lpParms)++;
  151. else
  152. val.ul=(ULONG)*((ULONG *)lpParms)++;
  153. if (sign && val.l<0L)
  154. val.l=-val.l;
  155. else
  156. sign=0;
  157. lpT=lpOut;
  158. /* blast the number backwards into the user buffer */
  159. cch=SP_PutNumber(lpOut,val.l,cchLimit,radix,upper);
  160. if (!(cchLimit-=cch))
  161. goto errorout;
  162. lpOut+=cch;
  163. width-=cch;
  164. prec-=cch;
  165. if (prec>0)
  166. width-=prec;
  167. /* fill to the field precision */
  168. while (prec-->0)
  169. out('0');
  170. if (width>0 && !left)
  171. {
  172. /* if we're filling with spaces, put sign first */
  173. if (fillch!='0')
  174. {
  175. if (sign)
  176. {
  177. sign=0;
  178. out('-');
  179. width--;
  180. }
  181. if (prefix)
  182. {
  183. out(prefix);
  184. out('0');
  185. prefix=0;
  186. }
  187. }
  188. if (sign)
  189. width--;
  190. /* fill to the field width */
  191. while (width-->0)
  192. out(fillch);
  193. /* still have a sign? */
  194. if (sign)
  195. out('-');
  196. if (prefix)
  197. {
  198. out(prefix);
  199. out('0');
  200. }
  201. /* now reverse the string in place */
  202. SP_Reverse(lpT,lpOut-1);
  203. }
  204. else
  205. {
  206. /* add the sign character */
  207. if (sign)
  208. {
  209. out('-');
  210. width--;
  211. }
  212. if (prefix)
  213. {
  214. out(prefix);
  215. out('0');
  216. }
  217. /* reverse the string in place */
  218. SP_Reverse(lpT,lpOut-1);
  219. /* pad to the right of the string in case left aligned */
  220. while (width-->0)
  221. out(fillch);
  222. }
  223. break;
  224. case 'X':
  225. upper++;
  226. case 'x':
  227. radix=16;
  228. if (prefix)
  229. if (upper)
  230. prefix='X';
  231. else
  232. prefix='x';
  233. goto donumeric;
  234. case 'c':
  235. val.sz[0] = *((char *)lpParms);
  236. val.sz[1]=0;
  237. lpT=val.sz;
  238. cch = 1; // Length is one character.
  239. // Fix for Bug #1862 --01/10/91-- SANKAR --
  240. /* stack aligned to larger size */
  241. (BYTE *)lpParms += sizeof(DWORD);
  242. goto putstring;
  243. case 'w':
  244. fWideChar = 1;
  245. case 's':
  246. lpT=*((char **)lpParms)++;
  247. cch=((!fWideChar)?strlen(lpT):wstrlen((USHORT *)lpT));
  248. putstring:
  249. if (prec>=0 && cch>prec)
  250. cch=prec;
  251. width -= cch;
  252. if (left)
  253. {
  254. while (cch--) {
  255. if (*lpT == 0x0A || *lpT == 0x0D) {
  256. out(0x0D);
  257. out(0x0A);
  258. }
  259. else
  260. out(*lpT++);
  261. if (fWideChar)
  262. {
  263. ++lpT;
  264. }
  265. }
  266. while (width-->0)
  267. out(fillch);
  268. }
  269. else
  270. {
  271. while (width-->0)
  272. out(fillch);
  273. while (cch--) {
  274. if (*lpT == 0x0A || *lpT == 0x0D) {
  275. out(0x0D);
  276. out(0x0A);
  277. }
  278. else
  279. out(*lpT++);
  280. if (fWideChar)
  281. {
  282. ++lpT;
  283. }
  284. }
  285. }
  286. break;
  287. default:
  288. /* This is an unsupported character that followed %; So,
  289. * we must output that character as it is; This is the
  290. * Documented behaviour; This is the Fix for Bug #15410.
  291. * Please note that this could be due to a typo in the app as in the
  292. * case of the sample app for Bug #13946 and in such cases,
  293. * we might mis-interpret the parameters that follow and that
  294. * could result in a GP Fault. But, this is clearly a bug in the app
  295. * and we can't do anything about it. We will just RIP and let
  296. * them know in such cases.
  297. */
  298. if (*lpFmt == 0x0A || *lpFmt == 0x0D) {
  299. out(0x0D);
  300. out(0x0A);
  301. }
  302. else
  303. out(*lpFmt); /* Output the invalid char and continue */
  304. break;
  305. } /* END OF SWITCH(*lpFmt) */
  306. } /* END OF IF(%) */
  307. else
  308. {
  309. /* character not a '%', just do it */
  310. if (*lpFmt == 0x0A || *lpFmt == 0x0D) {
  311. out(0x0D);
  312. out(0x0A);
  313. }
  314. else
  315. out(*lpFmt);
  316. }
  317. /* advance to next format string character */
  318. lpFmt++;
  319. } /* END OF OUTER WHILE LOOP */
  320. errorout:
  321. *lpOut=0;
  322. return WSPRINTF_LIMIT-cchLimit;
  323. }
  324. int vxd_vprintf(char * Format, CONST VOID * lpParms)
  325. {
  326. int length;
  327. if (DebugBufferLength+WSPRINTF_LIMIT < DEBUG_BUFFER_SIZE) {
  328. length = vxd_vsprintf(DebugBuffer+DebugBufferLength, Format, lpParms);
  329. DebugBufferLength += length;
  330. }
  331. else
  332. length = 0;
  333. return length;
  334. }
  335. #ifdef CSC_RECORDMANAGER_WINNT
  336. int
  337. SP_PutNumber(
  338. LPSTR lpb,
  339. long n,
  340. int limit,
  341. int radix,
  342. int strCase
  343. )
  344. {
  345. unsigned long nT = (unsigned long)n, nRem=0;
  346. int i;
  347. for (i=0; i < limit; ++i)
  348. {
  349. nRem = nT%radix;
  350. nT = nT/radix;
  351. lpb[i] = (char)((nRem > 9)?((nRem-10) + ((strCase)?'A':'a')):(nRem+'0'));
  352. if (!nT)
  353. {
  354. ++i; // bump up the count appropriately
  355. break;
  356. }
  357. }
  358. return (i);
  359. }
  360. void
  361. SP_Reverse(
  362. LPSTR lpFirst,
  363. LPSTR lpLast
  364. )
  365. {
  366. LPSTR lpT = lpFirst;
  367. char ch;
  368. while (lpFirst < lpLast)
  369. {
  370. ch = *lpFirst;
  371. *lpFirst = *lpLast;
  372. *lpLast = ch;
  373. ++lpFirst; --lpLast;
  374. }
  375. }
  376. #endif //ifdef CSC_RECORDMANAGER_WINNT
  377.