/********************************************************************* * wcsftime (MSVCRT.@) */ MSVCRT_size_t CDECL MSVCRT_wcsftime( MSVCRT_wchar_t *str, MSVCRT_size_t max, const MSVCRT_wchar_t *format, const struct MSVCRT_tm *mstm ) { char *s, *fmt; MSVCRT_size_t len; TRACE("%p %ld %s %p\n", str, max, debugstr_w(format), mstm ); len = WideCharToMultiByte( CP_UNIXCP, 0, format, -1, NULL, 0, NULL, NULL ); if (!(fmt = MSVCRT_malloc( len ))) return 0; WideCharToMultiByte( CP_UNIXCP, 0, format, -1, fmt, len, NULL, NULL ); if ((s = MSVCRT_malloc( max*4 ))) { struct tm tm; msvcrt_tm_to_unix( &tm, mstm ); if (!strftime( s, max*4, fmt, &tm )) s[0] = 0; len = MultiByteToWideChar( CP_UNIXCP, 0, s, -1, str, max ); if (len) len--; MSVCRT_free( s ); } else len = 0; MSVCRT_free( fmt ); return len; }
/********************************************************************* * _cprintf (MSVCRT.@) */ int CDECL _cprintf(const char* format, ...) { char buf[2048], *mem = buf; int written, resize = sizeof(buf), retval; __ms_va_list valist; __ms_va_start( valist, format ); /* There are two conventions for snprintf failing: * Return -1 if we truncated, or * Return the number of bytes that would have been written * The code below handles both cases */ while ((written = MSVCRT_vsnprintf( mem, resize, format, valist )) == -1 || written > resize) { resize = (written == -1 ? resize * 2 : written + 1); if (mem != buf) MSVCRT_free (mem); if (!(mem = MSVCRT_malloc(resize))) return MSVCRT_EOF; __ms_va_start( valist, format ); } __ms_va_end(valist); LOCK_CONSOLE; retval = _cputs( mem ); UNLOCK_CONSOLE; if (mem != buf) MSVCRT_free (mem); return retval; }
/********************************************************************* * _spawnlpe (MSVCRT.@) */ MSVCRT_intptr_t CDECL _spawnlpe(int flags, const char* name, const char* arg0, ...) { va_list ap; MSVCRT_wchar_t *nameW, *args, *envs = NULL; const char * const *envp; MSVCRT_intptr_t ret; if (!(nameW = msvcrt_wstrdupa(name))) return -1; va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); va_end(ap); va_start(ap, arg0); while (va_arg( ap, char * ) != NULL) /*nothing*/; envp = va_arg( ap, const char * const * ); if (envp) envs = msvcrt_argvtos_aw(envp, 0); va_end(ap); ret = msvcrt_spawn(flags, nameW, args, envs, 1); MSVCRT_free(nameW); MSVCRT_free(args); MSVCRT_free(envs); return ret; }
static MSVCRT_intptr_t msvcrt_spawn(int flags, const MSVCRT_wchar_t* exe, MSVCRT_wchar_t* cmdline, MSVCRT_wchar_t* env, int use_path) { STARTUPINFOW si; PROCESS_INFORMATION pi; MSVCRT_wchar_t fullname[MAX_PATH]; TRACE("%x %s %s %s %d\n", flags, debugstr_w(exe), debugstr_w(cmdline), debugstr_w(env), use_path); if ((unsigned)flags > MSVCRT__P_DETACH) { *MSVCRT__errno() = MSVCRT_EINVAL; return -1; } msvcrt_search_executable(exe, fullname, use_path); memset(&si, 0, sizeof(si)); si.cb = sizeof(si); msvcrt_create_io_inherit_block(&si.cbReserved2, &si.lpReserved2); if (!CreateProcessW(fullname, cmdline, NULL, NULL, TRUE, flags == MSVCRT__P_DETACH ? DETACHED_PROCESS : 0, env, NULL, &si, &pi)) { msvcrt_set_errno(GetLastError()); MSVCRT_free(si.lpReserved2); return -1; } MSVCRT_free(si.lpReserved2); switch(flags) { case MSVCRT__P_WAIT: WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess,&pi.dwProcessId); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return pi.dwProcessId; case MSVCRT__P_DETACH: CloseHandle(pi.hProcess); pi.hProcess = 0; /* fall through */ case MSVCRT__P_NOWAIT: case MSVCRT__P_NOWAITO: CloseHandle(pi.hThread); return (MSVCRT_intptr_t)pi.hProcess; case MSVCRT__P_OVERLAY: MSVCRT__exit(0); } return -1; /* can't reach here */ }
/********************************************************************* * _wspawnve (MSVCRT.@) * * Unicode version of _spawnve */ MSVCRT_intptr_t CDECL _wspawnve(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* const* argv, const MSVCRT_wchar_t* const* envv) { MSVCRT_wchar_t *args, *envs; MSVCRT_intptr_t ret; args = msvcrt_argvtos(argv, ' '); envs = msvcrt_argvtos(envv, 0); ret = msvcrt_spawn(flags, name, args, envs, 0); MSVCRT_free(args); MSVCRT_free(envs); return ret; }
/********************************************************************* * _kbhit (MSVCRT.@) */ int CDECL _kbhit(void) { int retval = 0; LOCK_CONSOLE; if (__MSVCRT_console_buffer != MSVCRT_EOF) retval = 1; else { /* FIXME: There has to be a faster way than this in Win32.. */ INPUT_RECORD *ir = NULL; DWORD count = 0, i; GetNumberOfConsoleInputEvents(MSVCRT_console_in, &count); if (count && (ir = MSVCRT_malloc(count * sizeof(INPUT_RECORD))) && PeekConsoleInputA(MSVCRT_console_in, ir, count, &count)) for(i = 0; i < count - 1; i++) { if (ir[i].EventType == KEY_EVENT && ir[i].Event.KeyEvent.bKeyDown && ir[i].Event.KeyEvent.uChar.AsciiChar) { retval = 1; break; } } MSVCRT_free(ir); } UNLOCK_CONSOLE; return retval; }
/********************************************************************* * realloc (MSVCRT.@) */ void* CDECL MSVCRT_realloc(void* ptr, MSVCRT_size_t size) { if (!ptr) return MSVCRT_malloc(size); if (size) return HeapReAlloc(GetProcessHeap(), 0, ptr, size); MSVCRT_free(ptr); return NULL; }
const char * __thiscall MSVCRT_type_info_name(type_info * _this) { if (!_this->name) { /* Create and set the demangled name */ /* Note: mangled name in type_info struct always starts with a '.', while * it isn't valid for mangled name. * Is this '.' really part of the mangled name, or has it some other meaning ? */ char* name = __unDName(0, _this->mangled + 1, 0, MSVCRT_malloc, MSVCRT_free, UNDNAME_NO_ARGUMENTS | UNDNAME_32_BIT_DECODE); if (name) { unsigned int len = strlen(name); /* It seems _unDName may leave blanks at the end of the demangled name */ while (len && name[--len] == ' ') name[len] = '\0'; if (InterlockedCompareExchangePointer((void**)&_this->name, name, NULL)) { /* Another thread set this member since we checked above - use it */ MSVCRT_free(name); } } } TRACE("(%p) returning %s\n", _this, _this->name); return _this->name; }
/********************************************************************* * realloc (MSVCRT.@) */ void* CDECL DECLSPEC_HOTPATCH MSVCRT_realloc(void* ptr, MSVCRT_size_t size) { if (!ptr) return MSVCRT_malloc(size); if (size) return msvcrt_heap_realloc(0, ptr, size); MSVCRT_free(ptr); return NULL; }
/********************************************************************* * _spawnlp (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces * or double-quotes. */ MSVCRT_intptr_t CDECL _spawnlp(int flags, const char* name, const char* arg0, ...) { va_list ap; MSVCRT_wchar_t *nameW, *args; MSVCRT_intptr_t ret; if (!(nameW = msvcrt_wstrdupa(name))) return -1; va_start(ap, arg0); args = msvcrt_valisttos_aw(arg0, ap, ' '); va_end(ap); ret = msvcrt_spawn(flags, nameW, args, NULL, 1); MSVCRT_free(nameW); MSVCRT_free(args); return ret; }
/********************************************************************* * __std_exception_destroy (MSVCRT.@) */ void CDECL MSVCRT___std_exception_destroy(struct __std_exception_data *data) { TRACE("(%p)\n", data); if(data->dofree) MSVCRT_free(data->what); data->what = NULL; data->dofree = 0; }
/********************************************************************* * _spawnvpe (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces * or double-quotes. */ MSVCRT_intptr_t CDECL _spawnvpe(int flags, const char* name, const char* const* argv, const char* const* envv) { MSVCRT_wchar_t *nameW, *args, *envs; MSVCRT_intptr_t ret; if (!(nameW = msvcrt_wstrdupa(name))) return -1; args = msvcrt_argvtos_aw(argv, ' '); envs = msvcrt_argvtos_aw(envv, 0); ret = msvcrt_spawn(flags, nameW, args, envs, 1); MSVCRT_free(nameW); MSVCRT_free(args); MSVCRT_free(envs); return ret; }
/********************************************************************* * _aligned_free (MSVCRT.@) */ void CDECL _aligned_free(void *memblock) { TRACE("(%p)\n", memblock); if (memblock) { void **saved = SAVED_PTR(memblock); MSVCRT_free(*saved); } }
/********************************************************************* * _wperror (MSVCRT.@) */ void CDECL MSVCRT__wperror(const MSVCRT_wchar_t* str) { MSVCRT_size_t size; char *buffer = NULL; if (str && *str) { size = MSVCRT_wcstombs(NULL, str, 0); if (size == -1) return; size++; buffer = MSVCRT_malloc(size); if (!buffer) return; if (MSVCRT_wcstombs(buffer, str, size) == -1) { MSVCRT_free(buffer); return; } } MSVCRT_perror(buffer); MSVCRT_free(buffer); }
/********************************************************************* * _beginthread_trampoline */ static DWORD CALLBACK _beginthread_trampoline(LPVOID arg) { _beginthread_trampoline_t local_trampoline; /* Maybe it's just being paranoid, but freeing arg right * away seems safer. */ memcpy(&local_trampoline,arg,sizeof(local_trampoline)); MSVCRT_free(arg); local_trampoline.start_address(local_trampoline.arglist); return 0; }
/********************************************************************* * _beginthread_trampoline */ static DWORD CALLBACK _beginthread_trampoline(LPVOID arg) { _beginthread_trampoline_t local_trampoline; thread_data_t *data = msvcrt_get_thread_data(); memcpy(&local_trampoline,arg,sizeof(local_trampoline)); data->handle = local_trampoline.thread; MSVCRT_free(arg); local_trampoline.start_address(local_trampoline.arglist); _endthread(); return 0; }
/********************************************************************* * _wspawnlpe (MSVCRT.@) * * Unicode version of _spawnlpe */ MSVCRT_intptr_t CDECL _wspawnlpe(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...) { va_list ap; MSVCRT_wchar_t *args, *envs = NULL; const MSVCRT_wchar_t * const *envp; MSVCRT_intptr_t ret; va_start(ap, arg0); args = msvcrt_valisttos(arg0, ap, ' '); va_end(ap); va_start(ap, arg0); while (va_arg( ap, MSVCRT_wchar_t * ) != NULL) /*nothing*/; envp = va_arg( ap, const MSVCRT_wchar_t * const * ); if (envp) envs = msvcrt_argvtos(envp, 0); va_end(ap); ret = msvcrt_spawn(flags, name, args, envs, 1); MSVCRT_free(args); MSVCRT_free(envs); return ret; }
/********************************************************************* * _wexecl (MSVCRT.@) * * Unicode version of _execl */ MSVCRT_intptr_t CDECL _wexecl(const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...) { va_list ap; MSVCRT_wchar_t *args; MSVCRT_intptr_t ret; va_start(ap, arg0); args = msvcrt_valisttos(arg0, ap, ' '); va_end(ap); ret = msvcrt_spawn(MSVCRT__P_OVERLAY, name, args, NULL, 0); MSVCRT_free(args); return ret; }
/********************************************************************* * _wspawnlp (MSVCRT.@) * * Unicode version of _spawnlp */ MSVCRT_intptr_t CDECL _wspawnlp(int flags, const MSVCRT_wchar_t* name, const MSVCRT_wchar_t* arg0, ...) { va_list ap; MSVCRT_wchar_t *args; MSVCRT_intptr_t ret; va_start(ap, arg0); args = msvcrt_valisttos(arg0, ap, ' '); va_end(ap); ret = msvcrt_spawn(flags, name, args, NULL, 1); MSVCRT_free(args); return ret; }
/********************************************************************* * _beginthread (MSVCRT.@) */ MSVCRT_uintptr_t CDECL _beginthread( MSVCRT__beginthread_start_routine_t start_address, /* [in] Start address of routine that begins execution of new thread */ unsigned int stack_size, /* [in] Stack size for new thread or 0 */ void *arglist) /* [in] Argument list to be passed to new thread or NULL */ { _beginthread_trampoline_t* trampoline; HANDLE thread; TRACE("(%p, %d, %p)\n", start_address, stack_size, arglist); trampoline = MSVCRT_malloc(sizeof(*trampoline)); if(!trampoline) { *MSVCRT__errno() = MSVCRT_EAGAIN; return -1; } thread = CreateThread(NULL, stack_size, _beginthread_trampoline, trampoline, CREATE_SUSPENDED, NULL); if(!thread) { MSVCRT_free(trampoline); *MSVCRT__errno() = MSVCRT_EAGAIN; return -1; } trampoline->thread = thread; trampoline->start_address = start_address; trampoline->arglist = arglist; if(ResumeThread(thread) == -1) { MSVCRT_free(trampoline); *MSVCRT__errno() = MSVCRT_EAGAIN; return -1; } return (MSVCRT_uintptr_t)thread; }
/********************************************************************* * qsort_s (MSVCRT.@) * * Based on NTDLL_qsort in dlls/ntdll/misc.c */ void CDECL MSVCRT_qsort_s(void *base, MSVCRT_size_t nmemb, MSVCRT_size_t size, int (CDECL *compar)(void *, const void *, const void *), void *context) { void *secondarr; const size_t total_size = nmemb*size; if (!MSVCRT_CHECK_PMT(base != NULL || (base == NULL && nmemb == 0))) return; if (!MSVCRT_CHECK_PMT(size > 0)) return; if (!MSVCRT_CHECK_PMT(compar != NULL)) return; if (total_size / size != nmemb) return; if (nmemb < 2) return; secondarr = MSVCRT_malloc(total_size); if (!secondarr) return; MSVCRT_mergesort(base, secondarr, size, compar, 0, nmemb-1, context); MSVCRT_free(secondarr); }
static inline void msvcrt_free_tls_mem(void) { thread_data_t *tls = TlsGetValue(msvcrt_tls_index); if (tls) { CloseHandle(tls->handle); MSVCRT_free(tls->efcvt_buffer); MSVCRT_free(tls->asctime_buffer); MSVCRT_free(tls->wasctime_buffer); MSVCRT_free(tls->strerror_buffer); MSVCRT_free(tls->wcserror_buffer); MSVCRT_free(tls->time_buffer); MSVCRT_free(tls->tmpnam_buffer); MSVCRT_free(tls->wtmpnam_buffer); if(tls->have_locale) { free_locinfo(tls->locinfo); free_mbcinfo(tls->mbcinfo); } } HeapFree(GetProcessHeap(), 0, tls); }
/********************************************************************* * _fullpath (MSVCRT.@) * * Create an absolute path from a relative path. * * PARAMS * absPath [O] Destination for absolute path * relPath [I] Relative path to convert to absolute * size [I] Length of absPath in characters. * * RETURNS * Success: If absPath is NULL, returns an allocated string containing the path. * Otherwise populates absPath with the path and returns it. * Failure: NULL. errno indicates the error. */ char * CDECL MSVCRT__fullpath(char * absPath, const char* relPath, unsigned int size) { DWORD rc; char* lastpart; char* buffer; BOOL alloced = FALSE; if (!relPath || !*relPath) return MSVCRT__getcwd(absPath, size); if (absPath == NULL) { buffer = MSVCRT_malloc(MAX_PATH); size = MAX_PATH; alloced = TRUE; } else buffer = absPath; if (size < 4) { *MSVCRT__errno() = MSVCRT_ERANGE; return NULL; } TRACE(":resolving relative path '%s'\n",relPath); rc = GetFullPathNameA(relPath,size,buffer,&lastpart); if (rc > 0 && rc <= size) return buffer; else { if (alloced) MSVCRT_free(buffer); return NULL; } }
/********************************************************************* * _wfullpath (MSVCRT.@) * * Unicode version of _fullpath. */ MSVCRT_wchar_t * CDECL MSVCRT__wfullpath(MSVCRT_wchar_t * absPath, const MSVCRT_wchar_t* relPath, MSVCRT_size_t size) { DWORD rc; WCHAR* buffer; WCHAR* lastpart; BOOL alloced = FALSE; if (!relPath || !*relPath) return MSVCRT__wgetcwd(absPath, size); if (absPath == NULL) { buffer = MSVCRT_malloc(MAX_PATH * sizeof(WCHAR)); size = MAX_PATH; alloced = TRUE; } else buffer = absPath; if (size < 4) { *MSVCRT__errno() = MSVCRT_ERANGE; return NULL; } TRACE(":resolving relative path %s\n",debugstr_w(relPath)); rc = GetFullPathNameW(relPath,size,buffer,&lastpart); if (rc > 0 && rc <= size ) return buffer; else { if (alloced) MSVCRT_free(buffer); return NULL; } }
const char * __stdcall MSVCRT_type_info_name(type_info * _this) { if (!_this->name) { /* Create and set the demangled name */ /* Nota: mangled name in type_info struct always start with a '.', while * it isn't valid for mangled name. * Is this '.' really part of the mangled name, or has it some other meaning ? */ char* name = __unDName(0, _this->mangled + 1, 0, MSVCRT_malloc, MSVCRT_free, 0x2800); if (name) { unsigned int len = strlen(name); /* It seems _unDName may leave blanks at the end of the demangled name */ while (len && name[--len] == ' ') name[len] = '\0'; _mlock(_EXIT_LOCK2); if (_this->name) { /* Another thread set this member since we checked above - use it */ MSVCRT_free(name); } else _this->name = name; _munlock(_EXIT_LOCK2); } } TRACE("(%p) returning %s\n", _this, _this->name); return _this->name; }
void __thiscall MSVCRT_type_info_dtor(type_info * _this) { TRACE("(%p)\n", _this); MSVCRT_free(_this->name); }
void __thiscall MSVCRT_exception_dtor(exception * _this) { TRACE("(%p)\n", _this); _this->vtable = &MSVCRT_exception_vtable; if (_this->do_free) MSVCRT_free(_this->name); }