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"
32 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt
);
34 static unsigned int output_format
;
36 /*********************************************************************
39 void CDECL
MSVCRT__beep( unsigned int freq
, unsigned int duration
)
41 TRACE(":Freq %d, Duration %d\n",freq
,duration
);
45 /*********************************************************************
48 void CDECL
MSVCRT_srand( unsigned int seed
)
50 thread_data_t
*data
= msvcrt_get_thread_data();
51 data
->random_seed
= seed
;
54 /*********************************************************************
57 int CDECL
MSVCRT_rand(void)
59 thread_data_t
*data
= msvcrt_get_thread_data();
61 /* this is the algorithm used by MSVC, according to
62 * http://en.wikipedia.org/wiki/List_of_pseudorandom_number_generators */
63 data
->random_seed
= data
->random_seed
* 214013 + 2531011;
64 return (data
->random_seed
>> 16) & MSVCRT_RAND_MAX
;
67 /*********************************************************************
70 int CDECL
MSVCRT_rand_s(unsigned int *pval
)
72 if (!pval
|| !RtlGenRandom(pval
, sizeof(*pval
)))
74 *MSVCRT__errno() = MSVCRT_EINVAL
;
80 /*********************************************************************
83 void CDECL
MSVCRT__sleep(MSVCRT_ulong timeout
)
85 TRACE("_sleep for %d milliseconds\n",timeout
);
86 Sleep((timeout
)?timeout
:1);
89 /*********************************************************************
92 void* CDECL
_lfind(const void* match
, const void* start
,
93 unsigned int* array_size
, unsigned int elem_size
,
94 int (CDECL
*cf
)(const void*,const void*) )
96 unsigned int size
= *array_size
;
100 if (cf(match
, start
) == 0)
101 return (void *)start
; /* found */
102 start
= (const char *)start
+ elem_size
;
107 /*********************************************************************
108 * _lfind_s (MSVCRT.@)
110 void* CDECL
_lfind_s(const void* match
, const void* start
,
111 unsigned int* array_size
, unsigned int elem_size
,
112 int (CDECL
*cf
)(void*,const void*,const void*),
116 if (!MSVCRT_CHECK_PMT(match
!= NULL
)) return NULL
;
117 if (!MSVCRT_CHECK_PMT(array_size
!= NULL
)) return NULL
;
118 if (!MSVCRT_CHECK_PMT(start
!= NULL
|| *array_size
== 0)) return NULL
;
119 if (!MSVCRT_CHECK_PMT(cf
!= NULL
)) return NULL
;
120 if (!MSVCRT_CHECK_PMT(elem_size
!= 0)) return NULL
;
126 if (cf(context
, match
, start
) == 0)
127 return (void *)start
; /* found */
128 start
= (const char *)start
+ elem_size
;
133 /*********************************************************************
134 * _lsearch (MSVCRT.@)
136 void* CDECL
_lsearch(const void* match
, void* start
,
137 unsigned int* array_size
, unsigned int elem_size
,
138 int (CDECL
*cf
)(const void*,const void*) )
140 unsigned int size
= *array_size
;
144 if (cf(match
, start
) == 0)
145 return start
; /* found */
146 start
= (char*)start
+ elem_size
;
149 /* not found, add to end */
150 memcpy(start
, match
, elem_size
);
155 /*********************************************************************
156 * bsearch_s (msvcrt.@)
158 void* CDECL
MSVCRT_bsearch_s(const void *key
, const void *base
,
159 MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
160 int (__cdecl
*compare
)(void *, const void *, const void *), void *ctx
)
163 ssize_t max
= nmemb
- 1;
165 if (!MSVCRT_CHECK_PMT(size
!= 0)) return NULL
;
166 if (!MSVCRT_CHECK_PMT(compare
!= NULL
)) return NULL
;
170 ssize_t cursor
= min
+ (max
- min
) / 2;
171 int ret
= compare(ctx
, key
,(const char *)base
+(cursor
*size
));
173 return (char*)base
+(cursor
*size
);
182 static int CDECL
compare_wrapper(void *ctx
, const void *e1
, const void *e2
)
184 int (__cdecl
*compare
)(const void *, const void *) = ctx
;
185 return compare(e1
, e2
);
188 /*********************************************************************
191 void* CDECL
MSVCRT_bsearch(const void *key
, const void *base
, MSVCRT_size_t nmemb
,
192 MSVCRT_size_t size
, int (__cdecl
*compar
)(const void *, const void *))
194 return MSVCRT_bsearch_s(key
, base
, nmemb
, size
, compare_wrapper
, compar
);
196 /*********************************************************************
199 * Trap to a debugger if the value of the stack pointer has changed.
208 * This function is available for iX86 only.
210 * When VC++ generates debug code, it stores the value of the stack pointer
211 * before calling any external function, and checks the value following
212 * the call. It then calls this function, which will trap if the values are
213 * not the same. Usually this means that the prototype used to call
214 * the function is incorrect. It can also mean that the .spec entry has
215 * the wrong calling convention or parameters.
221 __ASM_GLOBAL_FUNC(_chkesp
,
225 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
226 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
228 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
233 "call " __ASM_NAME("MSVCRT_chkesp_fail") "\n\t"
238 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
239 __ASM_CFI(".cfi_same_value %ebp\n\t")
242 void CDECL DECLSPEC_HIDDEN
MSVCRT_chkesp_fail(void)
244 ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n");
248 # else /* __GNUC__ */
250 /**********************************************************************/
252 void CDECL
_chkesp(void)
256 # endif /* __GNUC__ */
258 #endif /* __i386__ */
260 static inline void swap(char *l
, char *r
, MSVCRT_size_t size
)
271 static void small_sort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
272 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
277 for(e
=nmemb
; e
>1; e
--) {
280 p
= (char*)base
+ i
*size
;
281 if(compar(context
, p
, max
) > 0)
290 static void quick_sort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
291 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
293 MSVCRT_size_t stack_lo
[8*sizeof(MSVCRT_size_t
)], stack_hi
[8*sizeof(MSVCRT_size_t
)];
294 MSVCRT_size_t beg
, end
, lo
, hi
, med
;
298 stack_lo
[stack_pos
] = 0;
299 stack_hi
[stack_pos
] = nmemb
-1;
301 #define X(i) ((char*)base+size*(i))
302 while(stack_pos
>= 0) {
303 beg
= stack_lo
[stack_pos
];
304 end
= stack_hi
[stack_pos
--];
307 small_sort(X(beg
), end
-beg
+1, size
, compar
, context
);
313 med
= lo
+ (hi
-lo
+1)/2;
314 if(compar(context
, X(lo
), X(med
)) > 0)
315 swap(X(lo
), X(med
), size
);
316 if(compar(context
, X(lo
), X(hi
)) > 0)
317 swap(X(lo
), X(hi
), size
);
318 if(compar(context
, X(med
), X(hi
)) > 0)
319 swap(X(med
), X(hi
), size
);
325 if(lo
!=med
&& compar(context
, X(lo
), X(med
))>0)
331 if(compar(context
, X(hi
), X(med
)) <= 0)
339 swap(X(lo
), X(hi
), size
);
347 if(hi
!=med
&& compar(context
, X(hi
), X(med
))!=0)
352 if(hi
-beg
>= end
-lo
) {
353 stack_lo
[++stack_pos
] = beg
;
354 stack_hi
[stack_pos
] = hi
;
355 stack_lo
[++stack_pos
] = lo
;
356 stack_hi
[stack_pos
] = end
;
358 stack_lo
[++stack_pos
] = lo
;
359 stack_hi
[stack_pos
] = end
;
360 stack_lo
[++stack_pos
] = beg
;
361 stack_hi
[stack_pos
] = hi
;
367 /*********************************************************************
370 * This function is trying to sort data doing identical comparisons
371 * as native does. There are still cases where it behaves differently.
373 void CDECL
MSVCRT_qsort_s(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
374 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
376 const MSVCRT_size_t total_size
= nmemb
*size
;
378 if (!MSVCRT_CHECK_PMT(base
!= NULL
|| (base
== NULL
&& nmemb
== 0))) return;
379 if (!MSVCRT_CHECK_PMT(size
> 0)) return;
380 if (!MSVCRT_CHECK_PMT(compar
!= NULL
)) return;
381 if (total_size
/ size
!= nmemb
) return;
383 if (nmemb
< 2) return;
385 quick_sort(base
, nmemb
, size
, compar
, context
);
388 /*********************************************************************
391 void CDECL
MSVCRT_qsort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
392 int (CDECL
*compar
)(const void*, const void*))
394 MSVCRT_qsort_s(base
, nmemb
, size
, compare_wrapper
, compar
);
397 /*********************************************************************
398 * _get_output_format (MSVCRT.@)
400 unsigned int CDECL
MSVCRT__get_output_format(void)
402 return output_format
;
405 /*********************************************************************
406 * _set_output_format (MSVCRT.@)
408 unsigned int CDECL
MSVCRT__set_output_format(unsigned int new_output_format
)
410 unsigned int ret
= output_format
;
412 if(!MSVCRT_CHECK_PMT(new_output_format
==0 || new_output_format
==MSVCRT__TWO_DIGIT_EXPONENT
))
415 output_format
= new_output_format
;
419 /*********************************************************************
420 * _resetstkoflw (MSVCRT.@)
422 int CDECL
MSVCRT__resetstkoflw(void)
427 /* causes stack fault that updates NtCurrentTeb()->Tib.StackLimit */
428 return VirtualProtect(&stack_addr
, 1, PAGE_GUARD
|PAGE_READWRITE
, &oldprot
);
431 #if _MSVCR_VER>=80 && _MSVCR_VER<=90
433 /*********************************************************************
434 * _decode_pointer (MSVCR80.@)
436 void * CDECL
MSVCRT_decode_pointer(void * ptr
)
438 return DecodePointer(ptr
);
441 /*********************************************************************
442 * _encode_pointer (MSVCR80.@)
444 void * CDECL
MSVCRT_encode_pointer(void * ptr
)
446 return EncodePointer(ptr
);
449 #endif /* _MSVCR_VER>=80 && _MSVCR_VER<=90 */
451 #if _MSVCR_VER>=80 && _MSVCR_VER<=100
452 /*********************************************************************
453 * _encoded_null (MSVCR80.@)
455 void * CDECL
_encoded_null(void)
459 return EncodePointer(NULL
);
464 /*********************************************************************
465 * _CRT_RTC_INIT (MSVCR70.@)
467 void* CDECL
_CRT_RTC_INIT(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
469 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
476 /*********************************************************************
477 * _CRT_RTC_INITW (MSVCR80.@)
479 void* CDECL
_CRT_RTC_INITW(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
481 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
485 /*********************************************************************
486 * _byteswap_ushort (MSVCR80.@)
488 unsigned short CDECL
_byteswap_ushort(unsigned short s
)
490 return (s
<<8) + (s
>>8);
493 /*********************************************************************
494 * _byteswap_ulong (MSVCR80.@)
496 ULONG CDECL
MSVCRT__byteswap_ulong(ULONG l
)
498 return (l
<<24) + ((l
<<8)&0xFF0000) + ((l
>>8)&0xFF00) + (l
>>24);
501 /*********************************************************************
502 * _byteswap_uint64 (MSVCR80.@)
504 unsigned __int64 CDECL
_byteswap_uint64(unsigned __int64 i
)
506 return (i
<<56) + ((i
&0xFF00)<<40) + ((i
&0xFF0000)<<24) + ((i
&0xFF000000)<<8) +
507 ((i
>>8)&0xFF000000) + ((i
>>24)&0xFF0000) + ((i
>>40)&0xFF00) + (i
>>56);
510 #endif /* _MSVCR_VER>=80 */
514 /*********************************************************************
515 * __crtGetShowWindowMode (MSVCR110.@)
517 int CDECL
MSVCR110__crtGetShowWindowMode(void)
521 GetStartupInfoW(&si
);
522 TRACE("flags=%x window=%d\n", si
.dwFlags
, si
.wShowWindow
);
523 return si
.dwFlags
& STARTF_USESHOWWINDOW
? si
.wShowWindow
: SW_SHOWDEFAULT
;
526 /*********************************************************************
527 * __crtInitializeCriticalSectionEx (MSVCR110.@)
529 BOOL CDECL
MSVCR110__crtInitializeCriticalSectionEx(
530 CRITICAL_SECTION
*cs
, DWORD spin_count
, DWORD flags
)
532 TRACE("(%p %x %x)\n", cs
, spin_count
, flags
);
533 return InitializeCriticalSectionEx(cs
, spin_count
, flags
);
536 #endif /* _MSVCR_VER>=110 */
539 /*********************************************************************
540 * _vacopy (MSVCR120.@)
542 void CDECL
MSVCR120__vacopy(__ms_va_list
*dest
, __ms_va_list src
)
544 __ms_va_copy(*dest
, src
);
549 /*********************************************************************
550 * _crt_debugger_hook (MSVCR80.@)
552 void CDECL
MSVCRT__crt_debugger_hook(int reserved
)
554 WARN("(%x)\n", reserved
);
559 /*********************************************************************
560 * __crtUnhandledException (MSVCR110.@)
562 LONG CDECL
MSVCRT__crtUnhandledException(EXCEPTION_POINTERS
*ep
)
565 SetUnhandledExceptionFilter(NULL
);
566 return UnhandledExceptionFilter(ep
);
569 /* ?_Trace_agents@Concurrency@@YAXW4Agents_EventType@1@_JZZ */
570 void WINAPIV
_Trace_agents(/*enum Concurrency::Agents_EventType*/int type
, __int64 id
, ...)
572 FIXME("(%d %s)\n", type
, wine_dbgstr_longlong(id
));
577 /*********************************************************************
578 * __crtSleep (MSVCR120.@)
580 void CDECL
MSVCRT__crtSleep(DWORD timeout
)
582 TRACE("(%u)\n", timeout
);
586 /*********************************************************************
587 * _SetWinRTOutOfMemoryExceptionCallback (MSVCR120.@)
589 void CDECL
MSVCR120__SetWinRTOutOfMemoryExceptionCallback(void *callback
)
591 FIXME("(%p): stub\n", callback
);