1 /* utility.c Utility functions for Wine
5 * This unit contains the implementations of
6 * various Windows API functions that perform
7 * utility tasks; i.e., that do not fit into
8 * any major category but perform useful tasks.
18 /* #define DEBUG_UTILITY */
22 /* static char Copyright[] = "Copyright Andrew C. Bulhak, 1993"; */
25 /* MulDiv is a simple function that may as well have been
26 * implemented as a macro; however Microsoft, in their infinite
27 * wisdom, have implemented it as a DLL function and therefore
29 * Basically, it takes two 16-bit integers, multiplies them
30 * and divides by a third integer.
33 int MulDiv(int foo
, int bar
, int baz
)
35 return (long)(((int)foo
*bar
)/baz
);
38 /* UTILITY_strip015() removes \015 (^M, CR) from a string;
39 * this is done to convert a MS-DOS-style string to a more
40 * UNIX-friendly format. Replacement is done in-place.
43 void UTILITY_strip015(char *dest
) {
47 while(*src
== '\015') src
++; /* Skip \015s */
48 while((*src
) && (*src
!= '\015')) *(dest
++) = *(src
++);
50 *dest
= '\0'; /* Add null terminator */
53 /**********************************************************************
57 DebugPrintString(char *str
)
59 fprintf(stderr
, "%s", str
);
64 * OutputDebugString strips CRs from its (string) parameter and
65 * calls DebugPrintString(), which was written by someone else.
66 * Since this is part of the standard Windows API, it needs no
67 * references to nonstandard DLLs.
70 void OutputDebugString(LPSTR foo
)
72 UTILITY_strip015(foo
);
73 DebugPrintString(foo
);
77 /* UTILITY_qualify(source, dest) takes the format string source and
78 * changes all the parameters to correspond to Linux integer sizes
79 * rather than Windows sizes. For example, it converts %i to %hi
80 * and %lx to %x. No array size checking is done at present.
83 static void UTILITY_qualify(const char *source
, char *dest
)
85 dprintf_utility(stddeb
, "UTILITY_qualify(\"%s\", \"%s\");\n",
87 if(!source
) return; /* Dumbass attack! */
89 /* Find next format code. */
90 while((*source
!= '%') && (*source
)) {
91 *(dest
++) = *(source
++);
93 /* Yeah, I know I shouldn't use gotos.... */
94 if (!(*source
)) goto loop_end
;
96 *(dest
++) = *(source
++);
97 /* Now insert a size qualifier, if needed. */
105 /* We have a 16-bit value here. */
109 /* Here we go 'round the mulberry bush... */
116 /* UTILITY_argsize() evaluates the size of the argument list that
117 * accompanies a vsprintf() or wvsprintf() call.
119 * char *format; printf-style format string.
120 * BOOL windows; if this is TRUE, we assume that ints are
121 * 16 bits in size; otherwise we deal with
124 * size (in bytes) of the arguments that follow the call.
127 size_t UTILITY_argsize(const char *format
, BOOL windows
)
131 #define INT_SIZE (windows ? 2 : 4)
134 while((*format
) && (*format
!= '%')) format
++; /* skip ahead */
137 dprintf_utility(stddeb
, "found:\t\"%%");
138 format
++; /* skip past '%' */
139 /* First skip the flags, field width, etc. */
140 /* First the flags */
141 if ((*format
== '#') || (*format
== '-') || (*format
== '+')
142 || (*format
== ' ')) {
143 dprintf_utility(stddeb
, "%c", *format
);
146 /* Now the field width, etc. */
147 while(isdigit(*format
)) {
148 dprintf_utility(stddeb
, "%c", *format
);
152 dprintf_utility(stddeb
, "%c", *format
);
155 while(isdigit(*format
)) {
156 dprintf_utility(stddeb
, "%c", *format
);
159 /* Now we handle the rest */
160 if((*format
== 'h') || (*format
== 'l') || (*format
== 'L')) {
161 dprintf_utility(stddeb
, "%c", modifier
);
162 modifier
= *(format
++);
164 /* Handle the actual type. */
165 dprintf_utility(stddeb
, "%c\"\n", *format
);
174 size
+= ((modifier
== 'l') ? 4 : INT_SIZE
);
176 case 's': size
+= sizeof(char *); break;
182 /* It doesn't look as if Windows' wvsprintf()
183 supports floating-point arguments. However,
184 I'll leave this code here just in case. */
185 size
+= (modifier
== 'L') ? sizeof(long double) : sizeof(double);
187 case 'p': size
+= sizeof(void *); break;
188 case 'n': size
+= sizeof(int *); break;
193 dprintf_utility(stddeb
, "UTILITY_argsize: returning %i\n", size
);
197 /* UTILITY_convertArgs() creates a 32-bit argument list from a 16-bit list.
198 * This is used to allow wvsprintf() arguments to be fed through
202 * char *fmt; format string
203 * char *winarg; Windows-style arguments
206 * malloc()ed pointer to new argument list. This should
207 * be free()d as soon as it is finished with.
210 char *UTILITY_convertArgs(char *format
, char *winarg
)
212 char *result
= (char *)malloc(UTILITY_argsize(format
, 0));
216 while((*format
) && (*format
!= '%')) format
++; /* skip ahead */
219 dprintf_utility(stddeb
, "found:\t\"%%");
220 format
++; /* skip past '%' */
221 /* First skip the flags, field width, etc. */
222 /* First the flags */
223 if ((*format
== '#') || (*format
== '-') || (*format
== '+')
224 || (*format
== ' ')) format
++;
225 /* Now the field width, etc. */
226 while(isdigit(*format
)) format
++;
227 if(*format
== '.') format
++;
228 while(isdigit(*format
)) format
++;
229 /* Now we handle the rest */
230 if((*format
== 'h') || (*format
== 'l') || (*format
== 'L'))
231 modifier
= *(format
++);
232 /* Handle the actual type. */
233 dprintf_utility(stddeb
, "%c\"\n", *format
);
237 *(((int *)rptr
)++) = (modifier
=='l') ? *(((int *)winarg
)++) : *(((short *)winarg
)++);
244 *(((unsigned int *)rptr
)++) = (modifier
=='l') ? *(((unsigned int *)winarg
)++)
245 : *(((unsigned short *)winarg
)++);
249 case 'n': /* A pointer, is a pointer, is a pointer... */
250 *(((char **)rptr
)++) = (char *)PTR_SEG_TO_LIN(*(((char **)winarg
)++));
257 /* It doesn't look as if Windows' wvsprintf()
258 supports floating-point arguments. However,
259 I'll leave this code here just in case. */
261 *(((long double *)rptr
)++) = *(((long double *)winarg
)++);
262 else *(((double *)rptr
)++) = *(((double *)winarg
)++);
271 INT
windows_wsprintf(BYTE
*win_stack
)
273 LPSTR lpOutput
, lpFormat
, ptr
;
274 BYTE new_stack
[1024], *stack_ptr
;
277 lpOutput
= (LPSTR
) PTR_SEG_TO_LIN(*(DWORD
*)win_stack
);
278 win_stack
+= sizeof(DWORD
);
279 lpFormat
= (LPSTR
) PTR_SEG_TO_LIN(*(DWORD
*)win_stack
);
280 win_stack
+= sizeof(DWORD
);
282 /* create 32-bit stack for libc's vsprintf() */
284 for (ptr
= lpFormat
, stack_ptr
= new_stack
; *ptr
; ptr
++)
286 if (*ptr
!= '%' || *++ptr
== '%')
289 /* skip width/precision */
290 while (*ptr
== '-' || *ptr
== '+' || *ptr
== '.' ||
291 *ptr
== ' ' || isdigit(*ptr
) || *ptr
== '#')
294 /* handle modifier */
295 fLarge
= ((*ptr
== 'l') || (*ptr
== 'L'));
301 *(char**)stack_ptr
= (char *)PTR_SEG_TO_LIN(*(DWORD
*)win_stack
);
302 stack_ptr
+= sizeof(char *);
303 win_stack
+= sizeof(DWORD
);
308 /* windows' wsprintf() %c ignores 0's, we replace 0 with SPACE to make sure
309 that the remaining part of the string isn't ignored by the winapp */
311 if (*(WORD
*)win_stack
)
312 *(DWORD
*)stack_ptr
= *(WORD
*)win_stack
;
314 *(DWORD
*)stack_ptr
= ' ';
315 stack_ptr
+= sizeof(DWORD
);
316 win_stack
+= sizeof(WORD
);
323 *(int*)stack_ptr
= *(INT
*)win_stack
;
324 stack_ptr
+= sizeof(int);
325 win_stack
+= sizeof(INT
);
328 /* else fall through */
334 *(DWORD
*)stack_ptr
= *(DWORD
*)win_stack
;
335 win_stack
+= sizeof(DWORD
);
339 *(DWORD
*)stack_ptr
= *(WORD
*)win_stack
;
340 win_stack
+= sizeof(WORD
);
342 stack_ptr
+= sizeof(DWORD
);
346 *(DWORD
*)stack_ptr
= 0;
347 stack_ptr
+= sizeof(DWORD
);
348 win_stack
+= sizeof(WORD
);
349 fprintf(stderr
, "wsprintf: oops, unknown formattype %c used!\n", *ptr
);
354 return vsprintf(lpOutput
, lpFormat
, new_stack
);
358 /**************************************************************************
359 * wsprintf [USER.420] (not used by relay)
361 int wsprintf(LPSTR lpOutput
, LPSTR lpFormat
, ...)
366 va_start(valist
, lpFormat
);
367 ArgCnt
= vsprintf(lpOutput
, lpFormat
, valist
);
374 /* wvsprintf() is an implementation of vsprintf(). This
375 * implementation converts the arguments to 32-bit integers and
376 * calls the standard library function vsprintf().
378 * Known shortcomings:
379 * wvsprintf() doesn't yet convert the arguments back after
380 * calling vsprintf(), so if Windows implements %n and a
381 * program depends on it, we're in trouble.
384 int wvsprintf(LPSTR buf
, LPSTR format
, LPSTR args
)
389 if(!buf
|| !format
) return 0;
391 /* Convert agruments to 32-bit values */
392 newargs
= UTILITY_convertArgs(format
, args
);
393 result
= vsprintf(buf
, format
, newargs
);