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 "wine/port.h"
27 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
32 static unsigned int output_format
;
34 /*********************************************************************
37 void CDECL
MSVCRT__beep( unsigned int freq
, unsigned int duration
)
39 TRACE(":Freq %d, Duration %d\n",freq
,duration
);
43 /*********************************************************************
46 void CDECL
MSVCRT_srand( unsigned int seed
)
48 thread_data_t
*data
= msvcrt_get_thread_data();
49 data
->random_seed
= seed
;
52 /*********************************************************************
55 int CDECL
MSVCRT_rand(void)
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) & MSVCRT_RAND_MAX
;
65 /*********************************************************************
68 int CDECL
MSVCRT_rand_s(unsigned int *pval
)
70 if (!pval
|| !RtlGenRandom(pval
, sizeof(*pval
)))
72 *MSVCRT__errno() = MSVCRT_EINVAL
;
78 /*********************************************************************
81 void CDECL
MSVCRT__sleep(MSVCRT_ulong timeout
)
83 TRACE("_sleep for %d 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
MSVCRT_bsearch_s(const void *key
, const void *base
,
157 MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
158 int (__cdecl
*compare
)(void *, const void *, const void *), void *ctx
)
161 ssize_t max
= nmemb
- 1;
163 if (!MSVCRT_CHECK_PMT(size
!= 0)) return NULL
;
164 if (!MSVCRT_CHECK_PMT(compare
!= NULL
)) return NULL
;
168 ssize_t cursor
= min
+ (max
- min
) / 2;
169 int ret
= compare(ctx
, key
,(const char *)base
+(cursor
*size
));
171 return (char*)base
+(cursor
*size
);
180 static int CDECL
compare_wrapper(void *ctx
, const void *e1
, const void *e2
)
182 int (__cdecl
*compare
)(const void *, const void *) = ctx
;
183 return compare(e1
, e2
);
186 /*********************************************************************
189 void* CDECL
MSVCRT_bsearch(const void *key
, const void *base
, MSVCRT_size_t nmemb
,
190 MSVCRT_size_t size
, int (__cdecl
*compar
)(const void *, const void *))
192 return MSVCRT_bsearch_s(key
, base
, nmemb
, size
, compare_wrapper
, compar
);
194 /*********************************************************************
197 * Trap to a debugger if the value of the stack pointer has changed.
206 * This function is available for iX86 only.
208 * When VC++ generates debug code, it stores the value of the stack pointer
209 * before calling any external function, and checks the value following
210 * the call. It then calls this function, which will trap if the values are
211 * not the same. Usually this means that the prototype used to call
212 * the function is incorrect. It can also mean that the .spec entry has
213 * the wrong calling convention or parameters.
219 __ASM_GLOBAL_FUNC(_chkesp
,
223 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
224 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
226 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
231 "call " __ASM_NAME("MSVCRT_chkesp_fail") "\n\t"
236 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
237 __ASM_CFI(".cfi_same_value %ebp\n\t")
240 void CDECL DECLSPEC_HIDDEN
MSVCRT_chkesp_fail(void)
242 ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n");
246 # else /* __GNUC__ */
248 /**********************************************************************/
250 void CDECL
_chkesp(void)
254 # endif /* __GNUC__ */
256 #endif /* __i386__ */
258 static inline void swap(char *l
, char *r
, MSVCRT_size_t size
)
269 static void small_sort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
270 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
275 for(e
=nmemb
; e
>1; e
--) {
278 p
= (char*)base
+ i
*size
;
279 if(compar(context
, p
, max
) > 0)
288 static void quick_sort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
289 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
291 MSVCRT_size_t stack_lo
[8*sizeof(MSVCRT_size_t
)], stack_hi
[8*sizeof(MSVCRT_size_t
)];
292 MSVCRT_size_t beg
, end
, lo
, hi
, med
;
296 stack_lo
[stack_pos
] = 0;
297 stack_hi
[stack_pos
] = nmemb
-1;
299 #define X(i) ((char*)base+size*(i))
300 while(stack_pos
>= 0) {
301 beg
= stack_lo
[stack_pos
];
302 end
= stack_hi
[stack_pos
--];
305 small_sort(X(beg
), end
-beg
+1, size
, compar
, context
);
311 med
= lo
+ (hi
-lo
+1)/2;
312 if(compar(context
, X(lo
), X(med
)) > 0)
313 swap(X(lo
), X(med
), size
);
314 if(compar(context
, X(lo
), X(hi
)) > 0)
315 swap(X(lo
), X(hi
), size
);
316 if(compar(context
, X(med
), X(hi
)) > 0)
317 swap(X(med
), X(hi
), size
);
323 if(lo
!=med
&& compar(context
, X(lo
), X(med
))>0)
329 if(compar(context
, X(hi
), X(med
)) <= 0)
337 swap(X(lo
), X(hi
), size
);
345 if(hi
!=med
&& compar(context
, X(hi
), X(med
))!=0)
350 if(hi
-beg
>= end
-lo
) {
351 stack_lo
[++stack_pos
] = beg
;
352 stack_hi
[stack_pos
] = hi
;
353 stack_lo
[++stack_pos
] = lo
;
354 stack_hi
[stack_pos
] = end
;
356 stack_lo
[++stack_pos
] = lo
;
357 stack_hi
[stack_pos
] = end
;
358 stack_lo
[++stack_pos
] = beg
;
359 stack_hi
[stack_pos
] = hi
;
365 /*********************************************************************
368 * This function is trying to sort data doing identical comparisons
369 * as native does. There are still cases where it behaves differently.
371 void CDECL
MSVCRT_qsort_s(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
372 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
374 const MSVCRT_size_t total_size
= nmemb
*size
;
376 if (!MSVCRT_CHECK_PMT(base
!= NULL
|| (base
== NULL
&& nmemb
== 0))) return;
377 if (!MSVCRT_CHECK_PMT(size
> 0)) return;
378 if (!MSVCRT_CHECK_PMT(compar
!= NULL
)) return;
379 if (total_size
/ size
!= nmemb
) return;
381 if (nmemb
< 2) return;
383 quick_sort(base
, nmemb
, size
, compar
, context
);
386 /*********************************************************************
389 void CDECL
MSVCRT_qsort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
390 int (CDECL
*compar
)(const void*, const void*))
392 MSVCRT_qsort_s(base
, nmemb
, size
, compare_wrapper
, compar
);
395 /*********************************************************************
396 * _get_output_format (MSVCRT.@)
398 unsigned int CDECL
MSVCRT__get_output_format(void)
400 return output_format
;
403 /*********************************************************************
404 * _set_output_format (MSVCRT.@)
406 unsigned int CDECL
MSVCRT__set_output_format(unsigned int new_output_format
)
408 unsigned int ret
= output_format
;
410 if(!MSVCRT_CHECK_PMT(new_output_format
==0 || new_output_format
==MSVCRT__TWO_DIGIT_EXPONENT
))
413 output_format
= new_output_format
;
417 /*********************************************************************
418 * _resetstkoflw (MSVCRT.@)
420 int CDECL
MSVCRT__resetstkoflw(void)
425 /* causes stack fault that updates NtCurrentTeb()->Tib.StackLimit */
426 return VirtualProtect(&stack_addr
, 1, PAGE_GUARD
|PAGE_READWRITE
, &oldprot
);
431 /*********************************************************************
432 * _decode_pointer (MSVCR80.@)
434 void * CDECL
MSVCRT_decode_pointer(void * ptr
)
436 return DecodePointer(ptr
);
439 /*********************************************************************
440 * _encode_pointer (MSVCR80.@)
442 void * CDECL
MSVCRT_encode_pointer(void * ptr
)
444 return EncodePointer(ptr
);
447 /*********************************************************************
448 * _encoded_null (MSVCR80.@)
450 void * CDECL
_encoded_null(void)
454 return EncodePointer(NULL
);
457 #endif /* _MSVCR_VER>=80 */
460 /*********************************************************************
461 * _CRT_RTC_INIT (MSVCR70.@)
463 void* CDECL
_CRT_RTC_INIT(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
465 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
472 /*********************************************************************
473 * _CRT_RTC_INITW (MSVCR80.@)
475 void* CDECL
_CRT_RTC_INITW(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
477 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
481 /*********************************************************************
482 * _byteswap_ushort (MSVCR80.@)
484 unsigned short CDECL
_byteswap_ushort(unsigned short s
)
486 return (s
<<8) + (s
>>8);
489 /*********************************************************************
490 * _byteswap_ulong (MSVCR80.@)
492 ULONG CDECL
MSVCRT__byteswap_ulong(ULONG l
)
494 return (l
<<24) + ((l
<<8)&0xFF0000) + ((l
>>8)&0xFF00) + (l
>>24);
497 /*********************************************************************
498 * _byteswap_uint64 (MSVCR80.@)
500 unsigned __int64 CDECL
_byteswap_uint64(unsigned __int64 i
)
502 return (i
<<56) + ((i
&0xFF00)<<40) + ((i
&0xFF0000)<<24) + ((i
&0xFF000000)<<8) +
503 ((i
>>8)&0xFF000000) + ((i
>>24)&0xFF0000) + ((i
>>40)&0xFF00) + (i
>>56);
506 #endif /* _MSVCR_VER>=80 */
510 /*********************************************************************
511 * __crtGetShowWindowMode (MSVCR110.@)
513 int CDECL
MSVCR110__crtGetShowWindowMode(void)
517 GetStartupInfoW(&si
);
518 TRACE("window=%d\n", si
.wShowWindow
);
519 return si
.wShowWindow
;
522 /*********************************************************************
523 * __crtInitializeCriticalSectionEx (MSVCR110.@)
525 BOOL CDECL
MSVCR110__crtInitializeCriticalSectionEx(
526 CRITICAL_SECTION
*cs
, DWORD spin_count
, DWORD flags
)
528 TRACE("(%p %x %x)\n", cs
, spin_count
, flags
);
529 return InitializeCriticalSectionEx(cs
, spin_count
, flags
);
532 #endif /* _MSVCR_VER>=110 */
535 /*********************************************************************
536 * _vacopy (MSVCR120.@)
538 void CDECL
MSVCR120__vacopy(__ms_va_list
*dest
, __ms_va_list src
)
540 __ms_va_copy(*dest
, src
);
545 /*********************************************************************
546 * _crt_debugger_hook (MSVCR80.@)
548 void CDECL
MSVCRT__crt_debugger_hook(int reserved
)
550 WARN("(%x)\n", reserved
);
555 /*********************************************************************
556 * __crtUnhandledException (MSVCR110.@)
558 LONG CDECL
MSVCRT__crtUnhandledException(EXCEPTION_POINTERS
*ep
)
561 SetUnhandledExceptionFilter(NULL
);
562 return UnhandledExceptionFilter(ep
);
565 /* ?_Trace_agents@Concurrency@@YAXW4Agents_EventType@1@_JZZ */
566 void WINAPIV
_Trace_agents(/*enum Concurrency::Agents_EventType*/int type
, __int64 id
, ...)
568 FIXME("(%d %s)\n", type
, wine_dbgstr_longlong(id
));
573 /*********************************************************************
574 * __crtSleep (MSVCR120.@)
576 void CDECL
MSVCRT__crtSleep(DWORD timeout
)
578 TRACE("(%u)\n", timeout
);