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 * _lsearch (MSVCRT.@)
108 void* CDECL
_lsearch(const void* match
, void* start
,
109 unsigned int* array_size
, unsigned int elem_size
,
110 int (CDECL
*cf
)(const void*,const void*) )
112 unsigned int size
= *array_size
;
116 if (cf(match
, start
) == 0)
117 return start
; /* found */
118 start
= (char*)start
+ elem_size
;
121 /* not found, add to end */
122 memcpy(start
, match
, elem_size
);
127 /*********************************************************************
128 * bsearch_s (msvcrt.@)
130 void* CDECL
MSVCRT_bsearch_s(const void *key
, const void *base
,
131 MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
132 int (__cdecl
*compare
)(void *, const void *, const void *), void *ctx
)
135 ssize_t max
= nmemb
- 1;
137 if (!MSVCRT_CHECK_PMT(size
!= 0)) return NULL
;
138 if (!MSVCRT_CHECK_PMT(compare
!= NULL
)) return NULL
;
142 ssize_t cursor
= min
+ (max
- min
) / 2;
143 int ret
= compare(ctx
, key
,(const char *)base
+(cursor
*size
));
145 return (char*)base
+(cursor
*size
);
154 static int CDECL
compare_wrapper(void *ctx
, const void *e1
, const void *e2
)
156 int (__cdecl
*compare
)(const void *, const void *) = ctx
;
157 return compare(e1
, e2
);
160 /*********************************************************************
163 void* CDECL
MSVCRT_bsearch(const void *key
, const void *base
, MSVCRT_size_t nmemb
,
164 MSVCRT_size_t size
, int (__cdecl
*compar
)(const void *, const void *))
166 return MSVCRT_bsearch_s(key
, base
, nmemb
, size
, compare_wrapper
, compar
);
168 /*********************************************************************
171 * Trap to a debugger if the value of the stack pointer has changed.
180 * This function is available for iX86 only.
182 * When VC++ generates debug code, it stores the value of the stack pointer
183 * before calling any external function, and checks the value following
184 * the call. It then calls this function, which will trap if the values are
185 * not the same. Usually this means that the prototype used to call
186 * the function is incorrect. It can also mean that the .spec entry has
187 * the wrong calling convention or parameters.
193 __ASM_GLOBAL_FUNC(_chkesp
,
197 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
198 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
200 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
205 "call " __ASM_NAME("MSVCRT_chkesp_fail") "\n\t"
210 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
211 __ASM_CFI(".cfi_same_value %ebp\n\t")
214 void CDECL
MSVCRT_chkesp_fail(void)
216 ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n");
220 # else /* __GNUC__ */
222 /**********************************************************************/
224 void CDECL
_chkesp(void)
228 # endif /* __GNUC__ */
230 #endif /* __i386__ */
232 static inline void swap(char *l
, char *r
, MSVCRT_size_t size
)
243 static void small_sort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
244 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
249 for(e
=nmemb
; e
>1; e
--) {
252 p
= (char*)base
+ i
*size
;
253 if(compar(context
, p
, max
) > 0)
262 static void quick_sort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
263 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
265 MSVCRT_size_t stack_lo
[8*sizeof(MSVCRT_size_t
)], stack_hi
[8*sizeof(MSVCRT_size_t
)];
266 MSVCRT_size_t beg
, end
, lo
, hi
, med
;
270 stack_lo
[stack_pos
] = 0;
271 stack_hi
[stack_pos
] = nmemb
-1;
273 #define X(i) ((char*)base+size*(i))
274 while(stack_pos
>= 0) {
275 beg
= stack_lo
[stack_pos
];
276 end
= stack_hi
[stack_pos
--];
279 small_sort(X(beg
), end
-beg
+1, size
, compar
, context
);
285 med
= lo
+ (hi
-lo
+1)/2;
286 if(compar(context
, X(lo
), X(med
)) > 0)
287 swap(X(lo
), X(med
), size
);
288 if(compar(context
, X(lo
), X(hi
)) > 0)
289 swap(X(lo
), X(hi
), size
);
290 if(compar(context
, X(med
), X(hi
)) > 0)
291 swap(X(med
), X(hi
), size
);
297 if(lo
!=med
&& compar(context
, X(lo
), X(med
))>0)
303 if(compar(context
, X(hi
), X(med
)) <= 0)
311 swap(X(lo
), X(hi
), size
);
319 if(hi
!=med
&& compar(context
, X(hi
), X(med
))!=0)
324 if(hi
-beg
>= end
-lo
) {
325 stack_lo
[++stack_pos
] = beg
;
326 stack_hi
[stack_pos
] = hi
;
327 stack_lo
[++stack_pos
] = lo
;
328 stack_hi
[stack_pos
] = end
;
330 stack_lo
[++stack_pos
] = lo
;
331 stack_hi
[stack_pos
] = end
;
332 stack_lo
[++stack_pos
] = beg
;
333 stack_hi
[stack_pos
] = hi
;
339 /*********************************************************************
342 * This function is trying to sort data doing identical comparisons
343 * as native does. There are still cases where it behaves differently.
345 void CDECL
MSVCRT_qsort_s(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
346 int (CDECL
*compar
)(void *, const void *, const void *), void *context
)
348 const MSVCRT_size_t total_size
= nmemb
*size
;
350 if (!MSVCRT_CHECK_PMT(base
!= NULL
|| (base
== NULL
&& nmemb
== 0))) return;
351 if (!MSVCRT_CHECK_PMT(size
> 0)) return;
352 if (!MSVCRT_CHECK_PMT(compar
!= NULL
)) return;
353 if (total_size
/ size
!= nmemb
) return;
355 if (nmemb
< 2) return;
357 quick_sort(base
, nmemb
, size
, compar
, context
);
360 /*********************************************************************
363 void CDECL
MSVCRT_qsort(void *base
, MSVCRT_size_t nmemb
, MSVCRT_size_t size
,
364 int (CDECL
*compar
)(const void*, const void*))
366 MSVCRT_qsort_s(base
, nmemb
, size
, compare_wrapper
, compar
);
369 /*********************************************************************
370 * _get_output_format (MSVCRT.@)
372 unsigned int CDECL
MSVCRT__get_output_format(void)
374 return output_format
;
377 /*********************************************************************
378 * _set_output_format (MSVCRT.@)
380 unsigned int CDECL
_set_output_format(unsigned int new_output_format
)
382 unsigned int ret
= output_format
;
384 if(!MSVCRT_CHECK_PMT(new_output_format
==0 || new_output_format
==MSVCRT__TWO_DIGIT_EXPONENT
))
387 output_format
= new_output_format
;
391 /*********************************************************************
392 * _resetstkoflw (MSVCRT.@)
394 int CDECL
MSVCRT__resetstkoflw(void)
399 /* causes stack fault that updates NtCurrentTeb()->Tib.StackLimit */
400 return VirtualProtect(&stack_addr
, 1, PAGE_GUARD
|PAGE_READWRITE
, &oldprot
);
403 /*********************************************************************
404 * _decode_pointer (MSVCR90.@)
406 void * CDECL
MSVCRT_decode_pointer(void * ptr
)
408 return DecodePointer(ptr
);
411 /*********************************************************************
412 * _encode_pointer (MSVCR90.@)
414 void * CDECL
MSVCRT_encode_pointer(void * ptr
)
416 return EncodePointer(ptr
);
419 /*********************************************************************
420 * _encoded_null (MSVCR100.@)
422 void * CDECL
_encoded_null(void)
426 return EncodePointer(NULL
);
429 /*********************************************************************
430 * _CRT_RTC_INIT (MSVCR100.@)
432 void* CDECL
_CRT_RTC_INIT(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
434 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
438 /*********************************************************************
439 * _CRT_RTC_INITW (MSVCR100.@)
441 void* CDECL
_CRT_RTC_INITW(void *unk1
, void *unk2
, int unk3
, int unk4
, int unk5
)
443 TRACE("%p %p %x %x %x\n", unk1
, unk2
, unk3
, unk4
, unk5
);
447 /*********************************************************************
448 * _byteswap_ushort (MSVCR100.@)
450 unsigned short CDECL
_byteswap_ushort(unsigned short s
)
452 return (s
<<8) + (s
>>8);
455 /*********************************************************************
456 * _byteswap_ulong (MSVCR100.@)
458 ULONG CDECL
MSVCRT__byteswap_ulong(ULONG l
)
460 return (l
<<24) + ((l
<<8)&0xFF0000) + ((l
>>8)&0xFF00) + (l
>>24);
463 /*********************************************************************
464 * _byteswap_uint64 (MSVCR100.@)
466 unsigned __int64 CDECL
_byteswap_uint64(unsigned __int64 i
)
468 return (i
<<56) + ((i
&0xFF00)<<40) + ((i
&0xFF0000)<<24) + ((i
&0xFF000000)<<8) +
469 ((i
>>8)&0xFF000000) + ((i
>>24)&0xFF0000) + ((i
>>40)&0xFF00) + (i
>>56);
472 /*********************************************************************
473 * __crtGetShowWindowMode (MSVCR110.@)
475 int CDECL
MSVCR110__crtGetShowWindowMode(void)
479 GetStartupInfoW(&si
);
480 TRACE("window=%d\n", si
.wShowWindow
);
481 return si
.wShowWindow
;
484 /*********************************************************************
485 * __crtInitializeCriticalSectionEx (MSVCR110.@)
487 BOOL CDECL
MSVCR110__crtInitializeCriticalSectionEx(
488 CRITICAL_SECTION
*cs
, DWORD spin_count
, DWORD flags
)
490 TRACE("(%p %x %x)\n", cs
, spin_count
, flags
);
491 return InitializeCriticalSectionEx(cs
, spin_count
, flags
);