2 * msvcrt.dll misc functions
4 * Copyright 2000 Jon Griffiths
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <sys/types.h>
25 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
32 static unsigned int output_format
;
34 /*********************************************************************
37 void CDECL
_beep( unsigned int freq
, unsigned int duration
)
39 TRACE(":Freq %d, Duration %d\n",freq
,duration
);
43 /*********************************************************************
46 void CDECL
srand( unsigned int seed
)
48 thread_data_t
*data
= msvcrt_get_thread_data();
49 data
->random_seed
= seed
;
52 /*********************************************************************
57 thread_data_t
*data
= msvcrt_get_thread_data();
59 /* this is the algorithm used by MSVC, according to
60 * http://en.wikipedia.org/wiki/List_of_pseudorandom_number_generators */
61 data
->random_seed
= data
->random_seed
* 214013 + 2531011;
62 return (data
->random_seed
>> 16) & RAND_MAX
;
65 /*********************************************************************
68 int CDECL
rand_s(unsigned int *pval
)
70 if (!pval
|| !RtlGenRandom(pval
, sizeof(*pval
)))
78 /*********************************************************************
81 void CDECL
_sleep(__msvcrt_ulong timeout
)
83 TRACE("_sleep for %ld milliseconds\n",timeout
);
84 Sleep((timeout
)?timeout
:1);
87 /*********************************************************************
90 void* CDECL
_lfind(const void* match
, const void* start
,
91 unsigned int* array_size
, unsigned int elem_size
,
92 int (CDECL
*cf
)(const void*,const void*) )
94 unsigned int size
= *array_size
;
98 if (cf(match
, start
) == 0)
99 return (void *)start
; /* found */
100 start
= (const char *)start
+ elem_size
;
105 /*********************************************************************
106 * _lfind_s (MSVCRT.@)
108 void* CDECL
_lfind_s(const void* match
, const void* start
,
109 unsigned int* array_size
, unsigned int elem_size
,
110 int (CDECL
*cf
)(void*,const void*,const void*),
114 if (!MSVCRT_CHECK_PMT(match
!= NULL
)) return NULL
;
115 if (!MSVCRT_CHECK_PMT(array_size
!= NULL
)) return NULL
;
116 if (!MSVCRT_CHECK_PMT(start
!= NULL
|| *array_size
== 0)) return NULL
;
117 if (!MSVCRT_CHECK_PMT(cf
!= NULL
)) return NULL
;
118 if (!MSVCRT_CHECK_PMT(elem_size
!= 0)) return NULL
;
124 if (cf(context
, match
, start
) == 0)
125 return (void *)start
; /* found */
126 start
= (const char *)start
+ elem_size
;
131 /*********************************************************************
132 * _lsearch (MSVCRT.@)
134 void* CDECL
_lsearch(const void* match
, void* start
,
135 unsigned int* array_size
, unsigned int elem_size
,
136 int (CDECL
*cf
)(const void*,const void*) )
138 unsigned int size
= *array_size
;
142 if (cf(match
, start
) == 0)
143 return start
; /* found */
144 start
= (char*)start
+ elem_size
;
147 /* not found, add to end */
148 memcpy(start
, match
, elem_size
);
153 /*********************************************************************
154 * bsearch_s (msvcrt.@)
156 void* CDECL
bsearch_s(const void *key
, const void *base
, size_t nmemb
, size_t size
,
157 int (__cdecl
*compare
)(void *, const void *, const void *), void *ctx
)
160 ssize_t max
= nmemb
- 1;
162 if (!MSVCRT_CHECK_PMT(size
!= 0)) return NULL
;
163 if (!MSVCRT_CHECK_PMT(compare
!= NULL
)) return NULL
;
167 ssize_t cursor
= min
+ (max
- min
) / 2;
168 int ret
= compare(ctx
, key
,(const char *)base
+(cursor
*size
));
170 return (char*)base
+(cursor
*size
);
179 static int CDECL
compare_wrapper(void *ctx
, const void *e1
, const void *e2
)
181 int (__cdecl
*compare
)(const void *, const void *) = ctx
;
182 return compare(e1
, e2
);
185 /*********************************************************************
188 void* CDECL
bsearch(const void *key
, const void *base
, size_t nmemb
,
189 size_t size
, int (__cdecl
*compar
)(const void *, const void *))
191 return bsearch_s(key
, base
, nmemb
, size
, compare_wrapper
, compar
);
193 /*********************************************************************
196 * Trap to a debugger if the value of the stack pointer has changed.
205 * This function is available for iX86 only.
207 * When VC++ generates debug code, it stores the value of the stack pointer
208 * before calling any external function, and checks the value following
209 * the call. It then calls this function, which will trap if the values are
210 * not the same. Usually this means that the prototype used to call
211 * the function is incorrect. It can also mean that the .spec entry has
212 * the wrong calling convention or parameters.
216 # if defined(__GNUC__) || defined(__clang__)
218 __ASM_GLOBAL_FUNC(_chkesp
,
222 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
223 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
225 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
230 "call " __ASM_NAME("chkesp_fail") "\n\t"
235 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
236 __ASM_CFI(".cfi_same_value %ebp\n\t")
239 void CDECL DECLSPEC_HIDDEN
chkesp_fail(void)
241 ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n");
245 # else /* __GNUC__ || __clang__ */
247 /**********************************************************************/
249 void CDECL
_chkesp(void)
253 # endif /* __GNUC__ || __clang__ */
255 #endif /* __i386__ */
257 static inline void swap(char *l
, char *r
, size_t size
)
268 static void small_sort(void *base
, size_t nmemb
, size_t size
,
269 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
274 for(e
=nmemb
; e
>1; e
--) {
277 p
= (char*)base
+ i
*size
;
278 if(compar(context
, p
, max
) > 0)
287 static void quick_sort(void *base
, size_t nmemb
, size_t size
,
288 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
290 size_t stack_lo
[8*sizeof(size_t)], stack_hi
[8*sizeof(size_t)];
291 size_t beg
, end
, lo
, hi
, med
;
295 stack_lo
[stack_pos
] = 0;
296 stack_hi
[stack_pos
] = nmemb
-1;
298 #define X(i) ((char*)base+size*(i))
299 while(stack_pos
>= 0) {
300 beg
= stack_lo
[stack_pos
];
301 end
= stack_hi
[stack_pos
--];
304 small_sort(X(beg
), end
-beg
+1, size
, compar
, context
);
310 med
= lo
+ (hi
-lo
+1)/2;
311 if(compar(context
, X(lo
), X(med
)) > 0)
312 swap(X(lo
), X(med
), size
);
313 if(compar(context
, X(lo
), X(hi
)) > 0)
314 swap(X(lo
), X(hi
), size
);
315 if(compar(context
, X(med
), X(hi
)) > 0)
316 swap(X(med
), X(hi
), size
);
322 if(lo
!=med
&& compar(context
, X(lo
), X(med
))>0)
328 if(compar(context
, X(hi
), X(med
)) <= 0)
336 swap(X(lo
), X(hi
), size
);
344 if(hi
!=med
&& compar(context
, X(hi
), X(med
))!=0)
349 if(hi
-beg
>= end
-lo
) {
350 stack_lo
[++stack_pos
] = beg
;
351 stack_hi
[stack_pos
] = hi
;
352 stack_lo
[++stack_pos
] = lo
;
353 stack_hi
[stack_pos
] = end
;
355 stack_lo
[++stack_pos
] = lo
;
356 stack_hi
[stack_pos
] = end
;
357 stack_lo
[++stack_pos
] = beg
;
358 stack_hi
[stack_pos
] = hi
;
364 /*********************************************************************
367 * This function is trying to sort data doing identical comparisons
368 * as native does. There are still cases where it behaves differently.
370 void CDECL
qsort_s(void *base
, size_t nmemb
, size_t size
,
371 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
373 const size_t total_size
= nmemb
*size
;
375 if (!MSVCRT_CHECK_PMT(base
!= NULL
|| (base
== NULL
&& nmemb
== 0))) return;
376 if (!MSVCRT_CHECK_PMT(size
> 0)) return;
377 if (!MSVCRT_CHECK_PMT(compar
!= NULL
)) return;
378 if (total_size
/ size
!= nmemb
) return;
380 if (nmemb
< 2) return;
382 quick_sort(base
, nmemb
, size
, compar
, context
);
385 /*********************************************************************
388 void CDECL
qsort(void *base
, size_t nmemb
, size_t size
,
389 int (CDECL
*compar
)(const void*, const void*))
391 qsort_s(base
, nmemb
, size
, compare_wrapper
, compar
);
394 /*********************************************************************
395 * _get_output_format (MSVCRT.@)
397 unsigned int CDECL
_get_output_format(void)
399 return output_format
;
402 /*********************************************************************
403 * _set_output_format (MSVCRT.@)
405 unsigned int CDECL
_set_output_format(unsigned int new_output_format
)
407 unsigned int ret
= output_format
;
409 if(!MSVCRT_CHECK_PMT(new_output_format
==0 || new_output_format
==_TWO_DIGIT_EXPONENT
))
412 output_format
= new_output_format
;
416 /*********************************************************************
417 * _resetstkoflw (MSVCRT.@)
419 int CDECL
_resetstkoflw(void)
424 /* causes stack fault that updates NtCurrentTeb()->Tib.StackLimit */
425 return VirtualProtect(&stack_addr
, 1, PAGE_GUARD
|PAGE_READWRITE
, &oldprot
);
428 #if _MSVCR_VER>=80 && _MSVCR_VER<=90
430 /*********************************************************************
431 * _decode_pointer (MSVCR80.@)
433 void * CDECL
_decode_pointer(void * ptr
)
435 return DecodePointer(ptr
);
438 /*********************************************************************
439 * _encode_pointer (MSVCR80.@)
441 void * CDECL
_encode_pointer(void * ptr
)
443 return EncodePointer(ptr
);
446 #endif /* _MSVCR_VER>=80 && _MSVCR_VER<=90 */
448 #if _MSVCR_VER>=80 && _MSVCR_VER<=100
449 /*********************************************************************
450 * _encoded_null (MSVCR80.@)
452 void * CDECL
_encoded_null(void)
456 return EncodePointer(NULL
);
461 /*********************************************************************
462 * _CRT_RTC_INIT (MSVCR70.@)
464 void* CDECL
_CRT_RTC_INIT(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
466 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
473 /*********************************************************************
474 * _CRT_RTC_INITW (MSVCR80.@)
476 void* CDECL
_CRT_RTC_INITW(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
478 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
482 /*********************************************************************
483 * _byteswap_ushort (MSVCR80.@)
485 unsigned short CDECL
_byteswap_ushort(unsigned short s
)
487 return (s
<<8) + (s
>>8);
490 /*********************************************************************
491 * _byteswap_ulong (MSVCR80.@)
493 __msvcrt_ulong CDECL
_byteswap_ulong(__msvcrt_ulong l
)
495 return (l
<<24) + ((l
<<8)&0xFF0000) + ((l
>>8)&0xFF00) + (l
>>24);
498 /*********************************************************************
499 * _byteswap_uint64 (MSVCR80.@)
501 unsigned __int64 CDECL
_byteswap_uint64(unsigned __int64 i
)
503 return (i
<<56) + ((i
&0xFF00)<<40) + ((i
&0xFF0000)<<24) + ((i
&0xFF000000)<<8) +
504 ((i
>>8)&0xFF000000) + ((i
>>24)&0xFF0000) + ((i
>>40)&0xFF00) + (i
>>56);
507 #endif /* _MSVCR_VER>=80 */
511 /*********************************************************************
512 * __crtGetShowWindowMode (MSVCR110.@)
514 int CDECL
__crtGetShowWindowMode(void)
518 GetStartupInfoW(&si
);
519 TRACE("flags=%lx window=%d\n", si
.dwFlags
, si
.wShowWindow
);
520 return si
.dwFlags
& STARTF_USESHOWWINDOW
? si
.wShowWindow
: SW_SHOWDEFAULT
;
523 /*********************************************************************
524 * __crtInitializeCriticalSectionEx (MSVCR110.@)
526 BOOL CDECL
__crtInitializeCriticalSectionEx(
527 CRITICAL_SECTION
*cs
, DWORD spin_count
, DWORD flags
)
529 TRACE("(%p %lx %lx)\n", cs
, spin_count
, flags
);
530 return InitializeCriticalSectionEx(cs
, spin_count
, flags
);
533 #endif /* _MSVCR_VER>=110 */
536 /*********************************************************************
537 * _vacopy (MSVCR120.@)
539 void CDECL
_vacopy(va_list *dest
, va_list src
)
546 /*********************************************************************
547 * _crt_debugger_hook (MSVCR80.@)
549 void CDECL
_crt_debugger_hook(int reserved
)
551 WARN("(%x)\n", reserved
);
556 /*********************************************************************
557 * __crtUnhandledException (MSVCR110.@)
559 LONG CDECL
__crtUnhandledException(EXCEPTION_POINTERS
*ep
)
562 SetUnhandledExceptionFilter(NULL
);
563 return UnhandledExceptionFilter(ep
);
568 /*********************************************************************
569 * __crtSleep (MSVCR120.@)
571 void CDECL
__crtSleep(DWORD timeout
)
573 TRACE("(%lu)\n", timeout
);
577 /*********************************************************************
578 * _SetWinRTOutOfMemoryExceptionCallback (MSVCR120.@)
580 void CDECL
_SetWinRTOutOfMemoryExceptionCallback(void *callback
)
582 FIXME("(%p): stub\n", callback
);