/********************************************************************* * _wsearchenv (MSVCRT.@) * * Unicode version of _searchenv */ void CDECL MSVCRT__wsearchenv(const MSVCRT_wchar_t* file, const MSVCRT_wchar_t* env, MSVCRT_wchar_t *buf) { MSVCRT_wchar_t *envVal, *penv; MSVCRT_wchar_t curPath[MAX_PATH]; *buf = '\0'; /* Try CWD first */ if (GetFileAttributesW( file ) != INVALID_FILE_ATTRIBUTES) { GetFullPathNameW( file, MAX_PATH, buf, NULL ); /* Sigh. This error is *always* set, regardless of success */ msvcrt_set_errno(ERROR_FILE_NOT_FOUND); return; } /* Search given environment variable */ envVal = MSVCRT__wgetenv(env); if (!envVal) { msvcrt_set_errno(ERROR_FILE_NOT_FOUND); return; } penv = envVal; TRACE(":searching for %s in paths %s\n", debugstr_w(file), debugstr_w(envVal)); do { MSVCRT_wchar_t *end = penv; while(*end && *end != ';') end++; /* Find end of next path */ if (penv == end || !*penv) { msvcrt_set_errno(ERROR_FILE_NOT_FOUND); return; } memcpy(curPath, penv, (end - penv) * sizeof(MSVCRT_wchar_t)); if (curPath[end - penv] != '/' && curPath[end - penv] != '\\') { curPath[end - penv] = '\\'; curPath[end - penv + 1] = '\0'; } else curPath[end - penv] = '\0'; strcatW(curPath, file); TRACE("Checking for file %s\n", debugstr_w(curPath)); if (GetFileAttributesW( curPath ) != INVALID_FILE_ATTRIBUTES) { strcpyW(buf, curPath); msvcrt_set_errno(ERROR_FILE_NOT_FOUND); return; /* Found */ } penv = *end ? end + 1 : end; } while(1); }
/********************************************************************* * _mkdir (MSVCRT.@) * * Create a directory. * * PARAMS * newdir [I] Name of directory to create. * * RETURNS * Success: 0. The directory indicated by newdir is created. * Failure: -1. errno indicates the error. * * NOTES * See CreateDirectoryA. */ int CDECL _mkdir(const char * newdir) { if (CreateDirectoryA(newdir,NULL)) return 0; msvcrt_set_errno(GetLastError()); return -1; }
/********************************************************************* * _cwait (MSVCRT.@) */ MSVCRT_intptr_t CDECL _cwait(int *status, MSVCRT_intptr_t pid, int action) { HANDLE hPid = (HANDLE)pid; int doserrno; action = action; /* Remove warning */ if (!WaitForSingleObject(hPid, INFINITE)) { if (status) { DWORD stat; GetExitCodeProcess(hPid, &stat); *status = (int)stat; } return pid; } doserrno = GetLastError(); if (doserrno == ERROR_INVALID_HANDLE) { *MSVCRT__errno() = MSVCRT_ECHILD; *MSVCRT___doserrno() = doserrno; } else msvcrt_set_errno(doserrno); return status ? *status = -1 : -1; }
/********************************************************************* * _wrmdir (MSVCRT.@) * * Unicode version of _rmdir. */ int CDECL MSVCRT__wrmdir(const MSVCRT_wchar_t * dir) { if (RemoveDirectoryW(dir)) return 0; msvcrt_set_errno(GetLastError()); return -1; }
/********************************************************************* * _wmkdir (MSVCRT.@) * * Unicode version of _mkdir. */ int CDECL MSVCRT__wmkdir(const MSVCRT_wchar_t* newdir) { if (CreateDirectoryW(newdir,NULL)) return 0; msvcrt_set_errno(GetLastError()); return -1; }
/********************************************************************* * _rmdir (MSVCRT.@) * * Delete a directory. * * PARAMS * dir [I] Name of directory to delete. * * RETURNS * Success: 0. The directory indicated by newdir is deleted. * Failure: -1. errno indicates the error. * * NOTES * See RemoveDirectoryA. */ int CDECL MSVCRT__rmdir(const char * dir) { if (RemoveDirectoryA(dir)) return 0; msvcrt_set_errno(GetLastError()); return -1; }
/********************************************************************* * _chdir (MSVCRT.@) * * Change the current working directory. * * PARAMS * newdir [I] Directory to change to * * RETURNS * Success: 0. The current working directory is set to newdir. * Failure: -1. errno indicates the error. * * NOTES * See SetCurrentDirectoryA. */ int CDECL _chdir(const char * newdir) { if (!SetCurrentDirectoryA(newdir)) { msvcrt_set_errno(newdir?GetLastError():0); return -1; } return 0; }
/********************************************************************* * _wchdir (MSVCRT.@) * * Unicode version of _chdir. */ int CDECL MSVCRT__wchdir(const MSVCRT_wchar_t * newdir) { if (!SetCurrentDirectoryW(newdir)) { msvcrt_set_errno(newdir?GetLastError():0); return -1; } return 0; }
/********************************************************************* * _heapchk (MSVCRT.@) */ int CDECL _heapchk(void) { if (!HeapValidate( GetProcessHeap(), 0, NULL)) { msvcrt_set_errno(GetLastError()); return MSVCRT__HEAPBADNODE; } return MSVCRT__HEAPOK; }
/********************************************************************* * _heapmin (MSVCRT.@) */ int CDECL _heapmin(void) { if (!HeapCompact( GetProcessHeap(), 0 )) { if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) msvcrt_set_errno(GetLastError()); return -1; } return 0; }
/********************************************************************* * _heapchk (MSVCRT.@) */ int CDECL _heapchk(void) { if (!HeapValidate(heap, 0, NULL) || (sb_heap && !HeapValidate(sb_heap, 0, NULL))) { msvcrt_set_errno(GetLastError()); return MSVCRT__HEAPBADNODE; } return MSVCRT__HEAPOK; }
/********************************************************************* * _findclose (MSVCRT.@) * * Close a handle returned by _findfirst(). * * PARAMS * hand [I] Handle to close * * RETURNS * Success: 0. All resources associated with hand are freed. * Failure: -1. errno indicates the error. * * NOTES * See FindClose. */ int CDECL MSVCRT__findclose(MSVCRT_intptr_t hand) { TRACE(":handle %ld\n",hand); if (!FindClose((HANDLE)hand)) { msvcrt_set_errno(GetLastError()); return -1; } return 0; }
/********************************************************************* * _unloaddll (MSVCRT.@) */ int CDECL _unloaddll(MSVCRT_intptr_t dll) { if (FreeLibrary((HMODULE)dll)) return 0; else { int err = GetLastError(); msvcrt_set_errno(err); return err; } }
/********************************************************************* * _heapmin (MSVCRT.@) */ int CDECL _heapmin(void) { if (!HeapCompact( heap, 0 ) || (sb_heap && !HeapCompact( sb_heap, 0 ))) { if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) msvcrt_set_errno(GetLastError()); return -1; } return 0; }
/********************************************************************* * _heapwalk (MSVCRT.@) */ int CDECL _heapwalk(struct MSVCRT__heapinfo* next) { PROCESS_HEAP_ENTRY phe; if (sb_heap) FIXME("small blocks heap not supported\n"); LOCK_HEAP; phe.lpData = next->_pentry; phe.cbData = next->_size; phe.wFlags = next->_useflag == MSVCRT__USEDENTRY ? PROCESS_HEAP_ENTRY_BUSY : 0; if (phe.lpData && phe.wFlags & PROCESS_HEAP_ENTRY_BUSY && !HeapValidate( heap, 0, phe.lpData )) { UNLOCK_HEAP; msvcrt_set_errno(GetLastError()); return MSVCRT__HEAPBADNODE; } do { if (!HeapWalk( heap, &phe )) { UNLOCK_HEAP; if (GetLastError() == ERROR_NO_MORE_ITEMS) return MSVCRT__HEAPEND; msvcrt_set_errno(GetLastError()); if (!phe.lpData) return MSVCRT__HEAPBADBEGIN; return MSVCRT__HEAPBADNODE; } } while (phe.wFlags & (PROCESS_HEAP_REGION|PROCESS_HEAP_UNCOMMITTED_RANGE)); UNLOCK_HEAP; next->_pentry = phe.lpData; next->_size = phe.cbData; next->_useflag = phe.wFlags & PROCESS_HEAP_ENTRY_BUSY ? MSVCRT__USEDENTRY : MSVCRT__FREEENTRY; return MSVCRT__HEAPOK; }
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 */ }
/********************************************************************* * _chdrive (MSVCRT.@) * * Change the current drive. * * PARAMS * newdrive [I] Drive number to change to (1 = 'A', 2 = 'B', ...) * * RETURNS * Success: 0. The current drive is set to newdrive. * Failure: -1. errno indicates the error. * * NOTES * See SetCurrentDirectoryA. */ int CDECL MSVCRT__chdrive(int newdrive) { WCHAR buffer[] = {'A', ':', 0}; buffer[0] += newdrive - 1; if (!SetCurrentDirectoryW( buffer )) { msvcrt_set_errno(GetLastError()); if (newdrive <= 0) *MSVCRT__errno() = MSVCRT_EACCES; return -1; } return 0; }
/********************************************************************* * _wfindfirsti64 (MSVCRT.@) * * Unicode version of _findfirsti64. */ MSVCRT_intptr_t CDECL MSVCRT__wfindfirsti64(const MSVCRT_wchar_t * fspec, struct MSVCRT__wfinddatai64_t* ft) { WIN32_FIND_DATAW find_data; HANDLE hfind; hfind = FindFirstFileW(fspec, &find_data); if (hfind == INVALID_HANDLE_VALUE) { msvcrt_set_errno(GetLastError()); return -1; } msvcrt_wfttofdi64(&find_data,ft); TRACE(":got handle %p\n",hfind); return (MSVCRT_intptr_t)hfind; }
/********************************************************************* * _findfirst64i32 (MSVCRT.@) * * 64-bit/32-bit version of _findfirst. */ MSVCRT_intptr_t CDECL MSVCRT__findfirst64i32(const char * fspec, struct MSVCRT__finddata64i32_t* ft) { WIN32_FIND_DATAA find_data; HANDLE hfind; hfind = FindFirstFileA(fspec, &find_data); if (hfind == INVALID_HANDLE_VALUE) { msvcrt_set_errno(GetLastError()); return -1; } msvcrt_fttofd64i32(&find_data,ft); TRACE(":got handle %p\n",hfind); return (MSVCRT_intptr_t)hfind; }
/********************************************************************* * _getdiskfree (MSVCRT.@) * * Get information about the free space on a drive. * * PARAMS * disk [I] Drive number to get information about (1 = 'A', 2 = 'B', ...) * info [O] Destination for the resulting information. * * RETURNS * Success: 0. info is updated with the free space information. * Failure: An error code from GetLastError(). * * NOTES * See GetLastError(). */ unsigned int CDECL MSVCRT__getdiskfree(unsigned int disk, struct MSVCRT__diskfree_t * d) { WCHAR drivespec[] = {'@', ':', '\\', 0}; DWORD ret[4]; unsigned int err; if (disk > 26) return ERROR_INVALID_PARAMETER; /* MSVCRT doesn't set errno here */ drivespec[0] += disk; /* make a drive letter */ if (GetDiskFreeSpaceW(disk==0?NULL:drivespec,ret,ret+1,ret+2,ret+3)) { d->sectors_per_cluster = ret[0]; d->bytes_per_sector = ret[1]; d->avail_clusters = ret[2]; d->total_clusters = ret[3]; return 0; } err = GetLastError(); msvcrt_set_errno(err); return err; }
/********************************************************************* * _wsearchenv_s (MSVCRT.@) */ int CDECL MSVCRT__wsearchenv_s(const MSVCRT_wchar_t* file, const MSVCRT_wchar_t* env, MSVCRT_wchar_t *buf, MSVCRT_size_t count) { MSVCRT_wchar_t* envVal, *penv; MSVCRT_wchar_t curPath[MAX_PATH]; if (!MSVCRT_CHECK_PMT(file != NULL)) return MSVCRT_EINVAL; if (!MSVCRT_CHECK_PMT(buf != NULL)) return MSVCRT_EINVAL; if (!MSVCRT_CHECK_PMT(count > 0)) return MSVCRT_EINVAL; *buf = '\0'; /* Try CWD first */ if (GetFileAttributesW( file ) != INVALID_FILE_ATTRIBUTES) { if (GetFullPathNameW( file, count, buf, NULL )) return 0; msvcrt_set_errno(GetLastError()); return 0; } /* Search given environment variable */ envVal = MSVCRT__wgetenv(env); if (!envVal) { *MSVCRT__errno() = MSVCRT_ENOENT; return MSVCRT_ENOENT; } penv = envVal; TRACE(":searching for %s in paths %s\n", debugstr_w(file), debugstr_w(envVal)); do { MSVCRT_wchar_t *end = penv; while(*end && *end != ';') end++; /* Find end of next path */ if (penv == end || !*penv) { *MSVCRT__errno() = MSVCRT_ENOENT; return MSVCRT_ENOENT; } memcpy(curPath, penv, (end - penv) * sizeof(MSVCRT_wchar_t)); if (curPath[end - penv] != '/' && curPath[end - penv] != '\\') { curPath[end - penv] = '\\'; curPath[end - penv + 1] = '\0'; } else curPath[end - penv] = '\0'; strcatW(curPath, file); TRACE("Checking for file %s\n", debugstr_w(curPath)); if (GetFileAttributesW( curPath ) != INVALID_FILE_ATTRIBUTES) { if (strlenW(curPath) + 1 > count) { MSVCRT_INVALID_PMT("buf[count] is too small", MSVCRT_ERANGE); return MSVCRT_ERANGE; } strcpyW(buf, curPath); return 0; } penv = *end ? end + 1 : end; } while(1); }
static void msvcrt_search_executable(const MSVCRT_wchar_t *name, MSVCRT_wchar_t *fullname, int use_path) { static const MSVCRT_wchar_t path[] = {'P','A','T','H',0}; static const MSVCRT_wchar_t suffix[][5] = {{'.','c','o','m',0}, {'.','e','x','e',0}, {'.','b','a','t',0}, {'.','c','m','d',0}}; MSVCRT_wchar_t buffer[MAX_PATH]; const MSVCRT_wchar_t *env, *p; unsigned int i, name_len, path_len; int extension = 1; *fullname = '\0'; msvcrt_set_errno(ERROR_FILE_NOT_FOUND); p = memchrW(name, '\0', MAX_PATH); if (!p) p = name + MAX_PATH - 1; name_len = p - name; /* FIXME extra-long names are silently truncated */ memcpy(buffer, name, name_len * sizeof(MSVCRT_wchar_t)); buffer[name_len] = '\0'; /* try current dir first */ if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } for (p--; p >= name; p--) if (*p == '\\' || *p == '/' || *p == ':' || *p == '.') break; /* if there's no extension, try some well-known extensions */ if ((p < name || *p != '.') && name_len <= MAX_PATH - 5) { for (i = 0; i < 4; i++) { memcpy(buffer + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t)); if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } } extension = 0; } if (!use_path || !(env = _wgetenv(path))) return; /* now try search path */ do { p = env; while (*p && *p != ';') p++; if (p == env) return; path_len = p - env; if (path_len + name_len <= MAX_PATH - 2) { memcpy(buffer, env, path_len * sizeof(MSVCRT_wchar_t)); if (buffer[path_len] != '/' || buffer[path_len] != '\\') { buffer[path_len++] = '\\'; buffer[path_len] = '\0'; } else buffer[path_len] = '\0'; strcatW(buffer, name); if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } } /* again, if there's no extension, try some well-known extensions */ if (!extension && path_len + name_len <= MAX_PATH - 5) { for (i = 0; i < 4; i++) { memcpy(buffer + path_len + name_len, suffix[i], 5 * sizeof(MSVCRT_wchar_t)); if (GetFileAttributesW(buffer) != INVALID_FILE_ATTRIBUTES) { strcpyW(fullname, buffer); return; } } } env = *p ? p + 1 : p; } while(1); }