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.
17 #include "stackframe.h"
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
)
36 if (!baz
) return -32768;
37 ret
= (foo
* bar
) / baz
;
38 if ((ret
> 32767) || (ret
< -32767)) return -32768;
42 /* UTILITY_strip015() removes \015 (^M, CR) from a string;
43 * this is done to convert a MS-DOS-style string to a more
44 * UNIX-friendly format. Replacement is done in-place.
47 void UTILITY_strip015(char *dest
) {
51 while(*src
== '\015') src
++; /* Skip \015s */
52 while((*src
) && (*src
!= '\015')) *(dest
++) = *(src
++);
54 *dest
= '\0'; /* Add null terminator */
57 /**********************************************************************
61 DebugPrintString(char *str
)
63 fprintf(stderr
, "%s\n", str
);
68 * OutputDebugString strips CRs from its (string) parameter and
69 * calls DebugPrintString(), which was written by someone else.
70 * Since this is part of the standard Windows API, it needs no
71 * references to nonstandard DLLs.
74 void OutputDebugString(LPSTR foo
)
76 UTILITY_strip015(foo
);
77 DebugPrintString(foo
);
81 /* UTILITY_qualify(source, dest) takes the format string source and
82 * changes all the parameters to correspond to Linux integer sizes
83 * rather than Windows sizes. For example, it converts %i to %hi
84 * and %lx to %x. No array size checking is done at present.
87 static void UTILITY_qualify(const char *source
, char *dest
)
89 dprintf_utility(stddeb
, "UTILITY_qualify(\"%s\", \"%s\");\n",
91 if(!source
) return; /* Dumbass attack! */
93 /* Find next format code. */
94 while((*source
!= '%') && (*source
)) {
95 *(dest
++) = *(source
++);
97 /* Yeah, I know I shouldn't use gotos.... */
98 if (!(*source
)) goto loop_end
;
100 *(dest
++) = *(source
++);
101 /* Now insert a size qualifier, if needed. */
109 /* We have a 16-bit value here. */
113 /* Here we go 'round the mulberry bush... */
120 /* UTILITY_argsize() evaluates the size of the argument list that
121 * accompanies a vsprintf() or wvsprintf() call.
123 * char *format; printf-style format string.
124 * BOOL windows; if this is TRUE, we assume that ints are
125 * 16 bits in size; otherwise we deal with
128 * size (in bytes) of the arguments that follow the call.
131 size_t UTILITY_argsize(const char *format
, BOOL windows
)
135 #define INT_SIZE (windows ? 2 : 4)
138 while((*format
) && (*format
!= '%')) format
++; /* skip ahead */
141 dprintf_utility(stddeb
, "found:\t\"%%");
142 format
++; /* skip past '%' */
143 /* First skip the flags, field width, etc. */
144 /* First the flags */
145 if ((*format
== '#') || (*format
== '-') || (*format
== '+')
146 || (*format
== ' ')) {
147 dprintf_utility(stddeb
, "%c", *format
);
150 /* Now the field width, etc. */
151 while(isdigit(*format
)) {
152 dprintf_utility(stddeb
, "%c", *format
);
156 dprintf_utility(stddeb
, "%c", *format
);
159 while(isdigit(*format
)) {
160 dprintf_utility(stddeb
, "%c", *format
);
163 /* Now we handle the rest */
164 if((*format
== 'h') || (*format
== 'l') || (*format
== 'L')) {
165 dprintf_utility(stddeb
, "%c", modifier
);
166 modifier
= *(format
++);
168 /* Handle the actual type. */
169 dprintf_utility(stddeb
, "%c\"\n", *format
);
178 size
+= ((modifier
== 'l') ? 4 : INT_SIZE
);
180 case 's': size
+= sizeof(char *); break;
186 /* It doesn't look as if Windows' wvsprintf()
187 supports floating-point arguments. However,
188 I'll leave this code here just in case. */
189 size
+= (modifier
== 'L') ? sizeof(long double) : sizeof(double);
191 case 'p': size
+= sizeof(void *); break;
192 case 'n': size
+= sizeof(int *); break;
197 dprintf_utility(stddeb
, "UTILITY_argsize: returning %i\n", size
);
201 /* UTILITY_convertArgs() creates a 32-bit argument list from a 16-bit list.
202 * This is used to allow wvsprintf() arguments to be fed through
206 * char *fmt; format string
207 * char *winarg; Windows-style arguments
210 * malloc()ed pointer to new argument list. This should
211 * be free()d as soon as it is finished with.
214 char *UTILITY_convertArgs(char *format
, char *winarg
)
216 char *result
= (char *)malloc(UTILITY_argsize(format
, 0));
218 short *wptr
= (short *)winarg
;
219 long *dptr
= (long *)result
;
222 while((*format
) && (*format
!= '%')) format
++; /* skip ahead */
225 dprintf_utility(stddeb
, "found:\t\"%%");
226 format
++; /* skip past '%' */
228 /* First skip the flags, field width, etc. */
229 /* First the flags */
230 if (*format
== '#' || *format
== '-' || *format
== '+'
231 || *format
== ' ') format
++;
233 /* Now the field width, etc. */
234 while (isdigit(*format
)) format
++;
235 if (*format
== '.') format
++;
236 while (isdigit(*format
)) format
++;
238 /* Now we handle the rest */
239 if(*format
== 'h' || *format
== 'l' || *format
== 'L')
240 modifier
= *format
++;
242 /* Handle the actual type. */
243 dprintf_utility(stddeb
, "%c\"\n", *format
);
248 if (modifier
== 'l') {
249 *((int *)rptr
)++ = *((int *)winarg
)++;
251 *((int *)rptr
)++ = *((short *)winarg
)++;
259 if (modifier
== 'l') {
260 *((unsigned int *)rptr
)++ = *((unsigned int *)winarg
)++;
262 *((unsigned int *)rptr
)++ = *((unsigned short *)winarg
)++;
267 case 'n': /* A pointer, is a pointer, is a pointer... */
268 *((char **)rptr
)++ = (char *)PTR_SEG_TO_LIN(*(SEGPTR
*)winarg
);
269 ((SEGPTR
*)winarg
)++;
276 /* It doesn't look as if Windows' wvsprintf()
277 supports floating-point arguments. However,
278 I'll leave this code here just in case. */
280 *((long double *)rptr
)++ = *((long double *)winarg
)++;
282 *((double *)rptr
)++ = *((double *)winarg
)++;
287 for(; (char *)dptr
< rptr
; dptr
++)
288 dprintf_utility( stddeb
, "%08lx ", *dptr
);
289 dprintf_utility( stddeb
, "\n" );
290 for(; (char *)wptr
< winarg
; wptr
++)
291 dprintf_utility( stddeb
, "%04x ", *wptr
);
292 dprintf_utility( stddeb
, "\n" );
297 INT
windows_wsprintf(void)
299 LPSTR lpOutput
, lpFormat
, ptr
;
300 BYTE new_stack
[1024], *stack_ptr
;
303 BYTE
*win_stack
= (BYTE
*)CURRENT_STACK16
->args
;
305 lpOutput
= (LPSTR
) PTR_SEG_TO_LIN(*(DWORD
*)win_stack
);
306 win_stack
+= sizeof(DWORD
);
307 lpFormat
= (LPSTR
) PTR_SEG_TO_LIN(*(DWORD
*)win_stack
);
308 win_stack
+= sizeof(DWORD
);
310 /* create 32-bit stack for libc's vsprintf() */
312 for (ptr
= lpFormat
, stack_ptr
= new_stack
; *ptr
; ptr
++)
314 if (*ptr
!= '%' || *++ptr
== '%')
317 /* skip width/precision */
318 while (*ptr
== '-' || *ptr
== '+' || *ptr
== '.' ||
319 *ptr
== ' ' || isdigit(*ptr
) || *ptr
== '#')
322 /* handle modifier */
323 fLarge
= ((*ptr
== 'l') || (*ptr
== 'L'));
329 *(char**)stack_ptr
= (char *)PTR_SEG_TO_LIN(*(DWORD
*)win_stack
);
330 stack_ptr
+= sizeof(char *);
331 win_stack
+= sizeof(DWORD
);
336 /* windows' wsprintf() %c ignores 0's, we replace 0 with SPACE to make sure
337 that the remaining part of the string isn't ignored by the winapp */
339 if (*(WORD
*)win_stack
)
340 *(DWORD
*)stack_ptr
= *(WORD
*)win_stack
;
342 *(DWORD
*)stack_ptr
= ' ';
343 stack_ptr
+= sizeof(DWORD
);
344 win_stack
+= sizeof(WORD
);
351 *(int*)stack_ptr
= *(INT
*)win_stack
;
352 stack_ptr
+= sizeof(int);
353 win_stack
+= sizeof(INT
);
356 /* else fall through */
362 *(DWORD
*)stack_ptr
= *(DWORD
*)win_stack
;
363 win_stack
+= sizeof(DWORD
);
367 *(DWORD
*)stack_ptr
= *(WORD
*)win_stack
;
368 win_stack
+= sizeof(WORD
);
370 stack_ptr
+= sizeof(DWORD
);
374 *(DWORD
*)stack_ptr
= 0;
375 stack_ptr
+= sizeof(DWORD
);
376 win_stack
+= sizeof(WORD
);
377 fprintf(stderr
, "wsprintf: oops, unknown formattype %c used!\n", *ptr
);
382 return vsprintf(lpOutput
, lpFormat
, new_stack
);
386 /**************************************************************************
387 * wsprintf [USER.420] (not used by relay)
389 int wsprintf(LPSTR lpOutput
, LPSTR lpFormat
, ...)
394 va_start(valist
, lpFormat
);
395 ArgCnt
= vsprintf(lpOutput
, lpFormat
, valist
);
402 /* wvsprintf() is an implementation of vsprintf(). This
403 * implementation converts the arguments to 32-bit integers and
404 * calls the standard library function vsprintf().
406 * Known shortcomings:
407 * wvsprintf() doesn't yet convert the arguments back after
408 * calling vsprintf(), so if Windows implements %n and a
409 * program depends on it, we're in trouble.
412 int wvsprintf(LPSTR buf
, LPSTR format
, LPSTR args
)
417 if(!buf
|| !format
) return 0;
419 /* Convert agruments to 32-bit values */
420 newargs
= UTILITY_convertArgs(format
, args
);
421 result
= vsprintf(buf
, format
, newargs
);
427 /******************************************************************************
428 * DragDetect ( USER.465 )
430 * Hardly ever called at all
434 /******************************************************************************
435 * DragObject ( USER.464 )
437 * responsible for generation of WM_QUERYDROPOBJECT, WM_DRAGLOOP,
438 * WM_DRAGMOVE, WM_DROPOBJECT
440 LONG
DragObject(HWND hDesktop
, HWND hWnd
, UINT Unknown1
, WORD Unknown2
, WORD Unknown3
, HCURSOR hCursor
)
443 fprintf(stdnimp
,"DragObject: EmptyStub!!!\n");