mstask: Implement ITask::DeleteTrigger().
[wine.git] / dlls / msvcrt / misc.c
blobc197d69dd235bcd05c49c27ffc0a2e5e6b875faa
1 /*
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdlib.h>
26 #include "msvcrt.h"
27 #include "wine/debug.h"
28 #include "ntsecapi.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
32 static unsigned int output_format;
34 /*********************************************************************
35 * _beep (MSVCRT.@)
37 void CDECL MSVCRT__beep( unsigned int freq, unsigned int duration)
39 TRACE(":Freq %d, Duration %d\n",freq,duration);
40 Beep(freq, duration);
43 /*********************************************************************
44 * srand (MSVCRT.@)
46 void CDECL MSVCRT_srand( unsigned int seed )
48 thread_data_t *data = msvcrt_get_thread_data();
49 data->random_seed = seed;
52 /*********************************************************************
53 * rand (MSVCRT.@)
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 /*********************************************************************
66 * rand_s (MSVCRT.@)
68 int CDECL MSVCRT_rand_s(unsigned int *pval)
70 if (!pval || !RtlGenRandom(pval, sizeof(*pval)))
72 *MSVCRT__errno() = MSVCRT_EINVAL;
73 return MSVCRT_EINVAL;
75 return 0;
78 /*********************************************************************
79 * _sleep (MSVCRT.@)
81 void CDECL MSVCRT__sleep(MSVCRT_ulong timeout)
83 TRACE("_sleep for %d milliseconds\n",timeout);
84 Sleep((timeout)?timeout:1);
87 /*********************************************************************
88 * _lfind (MSVCRT.@)
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;
95 if (size)
98 if (cf(match, start) == 0)
99 return (void *)start; /* found */
100 start = (const char *)start + elem_size;
101 } while (--size);
102 return NULL;
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*),
111 void* context)
113 unsigned int size;
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;
120 size = *array_size;
121 if (size)
124 if (cf(context, match, start) == 0)
125 return (void *)start; /* found */
126 start = (const char *)start + elem_size;
127 } while (--size);
128 return NULL;
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;
139 if (size)
142 if (cf(match, start) == 0)
143 return start; /* found */
144 start = (char*)start + elem_size;
145 } while (--size);
147 /* not found, add to end */
148 memcpy(start, match, elem_size);
149 array_size[0]++;
150 return start;
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)
160 ssize_t min = 0;
161 ssize_t max = nmemb - 1;
163 if (!MSVCRT_CHECK_PMT(size != 0)) return NULL;
164 if (!MSVCRT_CHECK_PMT(compare != NULL)) return NULL;
166 while (min <= max)
168 ssize_t cursor = min + (max - min) / 2;
169 int ret = compare(ctx, key,(const char *)base+(cursor*size));
170 if (!ret)
171 return (char*)base+(cursor*size);
172 if (ret < 0)
173 max = cursor - 1;
174 else
175 min = cursor + 1;
177 return NULL;
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 /*********************************************************************
187 * bsearch (msvcrt.@)
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 /*********************************************************************
195 * _chkesp (MSVCRT.@)
197 * Trap to a debugger if the value of the stack pointer has changed.
199 * PARAMS
200 * None.
202 * RETURNS
203 * Does not return.
205 * NOTES
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.
215 #ifdef __i386__
217 # ifdef __GNUC__
219 __ASM_GLOBAL_FUNC(_chkesp,
220 "jnz 1f\n\t"
221 "ret\n"
222 "1:\tpushl %ebp\n\t"
223 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
224 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
225 "movl %esp,%ebp\n\t"
226 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
227 "subl $12,%esp\n\t"
228 "pushl %eax\n\t"
229 "pushl %ecx\n\t"
230 "pushl %edx\n\t"
231 "call " __ASM_NAME("MSVCRT_chkesp_fail") "\n\t"
232 "popl %edx\n\t"
233 "popl %ecx\n\t"
234 "popl %eax\n\t"
235 "leave\n\t"
236 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
237 __ASM_CFI(".cfi_same_value %ebp\n\t")
238 "ret")
240 void CDECL DECLSPEC_HIDDEN MSVCRT_chkesp_fail(void)
242 ERR("Stack pointer incorrect after last function call - Bad prototype/spec entry?\n");
243 DebugBreak();
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)
260 char tmp;
262 while(size--) {
263 tmp = *l;
264 *l++ = *r;
265 *r++ = tmp;
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)
272 MSVCRT_size_t e, i;
273 char *max, *p;
275 for(e=nmemb; e>1; e--) {
276 max = base;
277 for(i=1; i<e; i++) {
278 p = (char*)base + i*size;
279 if(compar(context, p, max) > 0)
280 max = p;
283 if(p != max)
284 swap(p, max, size);
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;
293 int stack_pos;
295 stack_pos = 0;
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--];
304 if(end-beg < 8) {
305 small_sort(X(beg), end-beg+1, size, compar, context);
306 continue;
309 lo = beg;
310 hi = end;
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);
319 lo++;
320 hi--;
321 while(1) {
322 while(lo <= hi) {
323 if(lo!=med && compar(context, X(lo), X(med))>0)
324 break;
325 lo++;
328 while(med != hi) {
329 if(compar(context, X(hi), X(med)) <= 0)
330 break;
331 hi--;
334 if(hi < lo)
335 break;
337 swap(X(lo), X(hi), size);
338 if(hi == med)
339 med = lo;
340 lo++;
341 hi--;
344 while(hi > beg) {
345 if(hi!=med && compar(context, X(hi), X(med))!=0)
346 break;
347 hi--;
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;
355 }else {
356 stack_lo[++stack_pos] = lo;
357 stack_hi[stack_pos] = end;
358 stack_lo[++stack_pos] = beg;
359 stack_hi[stack_pos] = hi;
362 #undef X
365 /*********************************************************************
366 * qsort_s (MSVCRT.@)
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 /*********************************************************************
387 * qsort (MSVCRT.@)
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))
411 return ret;
413 output_format = new_output_format;
414 return ret;
417 /*********************************************************************
418 * _resetstkoflw (MSVCRT.@)
420 int CDECL MSVCRT__resetstkoflw(void)
422 int stack_addr;
423 DWORD oldprot;
425 /* causes stack fault that updates NtCurrentTeb()->Tib.StackLimit */
426 return VirtualProtect(&stack_addr, 1, PAGE_GUARD|PAGE_READWRITE, &oldprot);
429 #if _MSVCR_VER>=80
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)
452 TRACE("\n");
454 return EncodePointer(NULL);
457 #endif /* _MSVCR_VER>=80 */
459 #if _MSVCR_VER>=70
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);
466 return NULL;
468 #endif
470 #if _MSVCR_VER>=80
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);
478 return NULL;
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 */
508 #if _MSVCR_VER>=110
510 /*********************************************************************
511 * __crtGetShowWindowMode (MSVCR110.@)
513 int CDECL MSVCR110__crtGetShowWindowMode(void)
515 STARTUPINFOW si;
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 */
534 #if _MSVCR_VER>=120
535 /*********************************************************************
536 * _vacopy (MSVCR120.@)
538 void CDECL MSVCR120__vacopy(__ms_va_list *dest, __ms_va_list src)
540 __ms_va_copy(*dest, src);
542 #endif
544 #if _MSVCR_VER>=80
545 /*********************************************************************
546 * _crt_debugger_hook (MSVCR80.@)
548 void CDECL MSVCRT__crt_debugger_hook(int reserved)
550 WARN("(%x)\n", reserved);
552 #endif
554 #if _MSVCR_VER>=110
555 /*********************************************************************
556 * __crtUnhandledException (MSVCR110.@)
558 LONG CDECL MSVCRT__crtUnhandledException(EXCEPTION_POINTERS *ep)
560 TRACE("(%p)\n", 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));
570 #endif
572 #if _MSVCR_VER>=120
573 /*********************************************************************
574 * __crtSleep (MSVCR120.@)
576 void CDECL MSVCRT__crtSleep(DWORD timeout)
578 TRACE("(%u)\n", timeout);
579 Sleep(timeout);
581 #endif