Implementation of the above functions, basically just "ports" of their ASCII equivalents. License: LGPL Changelog: * dlls/msvcrt/msvcrt.spec, dlls/msvcrt/dir.c, dlls/msvcrt/process.c: Jaco Greeff <jaco@puxedo.org> - Implementation of _wsearchenv - Implementation of _wexecl and _wexeclp - Implementation of _wspawnl and _wspawnlp
diff -aurN msvcrt-B08/dlls/msvcrt/dir.c msvcrt-B09/dlls/msvcrt/dir.c --- msvcrt-B08/dlls/msvcrt/dir.c Fri Oct 25 05:12:01 2002 +++ msvcrt-B09/dlls/msvcrt/dir.c Tue Nov 5 17:23:24 2002 @@ -5,6 +5,7 @@ * Copyright 1996 Jukka Iivonen * Copyright 1997,2000 Uwe Bonnes * Copyright 2000 Jon Griffiths + * Copyright 2002 Jaco Greeff * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -812,6 +813,71 @@ if (GetFileAttributesA( curPath ) != 0xFFFFFFFF) { strcpy(buf, curPath); + MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); + return; /* Found */ + } + penv = *end ? end + 1 : end; + } while(1); +} + +/********************************************************************* + * _wsearchenv (MSVCRT.@) + * (This is a straight "port" to Unicode of the _searchenv function) + */ +void _wsearchenv(const WCHAR* file, const WCHAR* env, WCHAR *buf) +{ + WCHAR *envVal, *penv; + WCHAR curPath[MAX_PATH]; + + *buf = '\0'; + + /* Try CWD first */ + if (GetFileAttributesW(file) != 0xFFFFFFFF) + { + 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 = _wgetenv(env); + if (!envVal) + { + MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); + return; + } + + penv = envVal; + do + { + WCHAR *end = penv; + int len; + + len = 0; + while (*end && *end != ';') + { + end++; /* Find end of next path */ + len++; + } + if (penv == end || !*penv) + { + MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); + return; + } + strncpyW(curPath, penv, len); + if (curPath[len] != '/' || curPath[len] != '\\') + { + curPath[len] = '\\'; + curPath[len + 1] = '\0'; + } + else + curPath[len] = '\0'; + + strcatW(curPath, file); + if (GetFileAttributesW(curPath) != 0xFFFFFFFF) + { + strcpyW(buf, curPath); MSVCRT__set_errno(ERROR_FILE_NOT_FOUND); return; /* Found */ } diff -aurN msvcrt-B08/dlls/msvcrt/msvcrt.spec msvcrt-B09/dlls/msvcrt/msvcrt.spec --- msvcrt-B08/dlls/msvcrt/msvcrt.spec Tue Nov 5 14:05:40 2002 +++ msvcrt-B09/dlls/msvcrt/msvcrt.spec Tue Nov 5 17:11:33 2002 @@ -505,9 +505,9 @@ @ forward -noimport _wcsupr ntdll._wcsupr @ stub _wctime #(ptr) @ extern _wenviron MSVCRT__wenviron -@ stub _wexecl #(wstr wstr) varargs +@ varargs _wexecl(wstr wstr) _wexecl @ stub _wexecle #(wstr wstr) varargs -@ stub _wexeclp #(wstr wstr) varargs +@ varargs _wexeclp(wstr wstr) _wexeclp @ stub _wexeclpe #(wstr wstr) varargs @ stub _wexecv #(wstr wstr) @ stub _wexecve #(wstr wstr wstr) @@ -540,12 +540,12 @@ @ cdecl _wrename(wstr wstr) _wrename @ cdecl _write(long ptr long) _write @ cdecl _wrmdir(wstr) _wrmdir -@ stub _wsearchenv #(wstr wstr wstr) +@ cdecl _wsearchenv(wstr wstr wstr) _wsearchenv @ stub _wsetlocale #(long wstr) -@ varargs _wsopen (wstr long long) MSVCRT__wsopen -@ stub _wspawnl #(long wstr wstr) varargs +@ varargs _wsopen(wstr long long) MSVCRT__wsopen +@ varargs _wspawnl(long wstr wstr) _wspawnl @ stub _wspawnle #(long wstr wstr) varargs -@ stub _wspawnlp #(long wstr wstr) varargs +@ varargs _wspawnlp(long wstr wstr) _wspawnlp @ stub _wspawnlpe #(long wstr wstr) varargs @ stub _wspawnv #(long wstr wstr) @ stub _wspawnve #(long wstr wstr wstr) @@ -556,7 +556,7 @@ @ stub _wstati64 #(wstr ptr) @ stub _wstrdate #(wstr) @ stub _wstrtime #(wstr) -@ cdecl _wsystem(wstr) +@ cdecl _wsystem(wstr) MSVCRT__wsystem @ cdecl _wtempnam(wstr wstr) _wtempnam @ stub _wtmpnam #(wstr) @ forward -noimport _wtoi NTDLL._wtoi diff -aurN msvcrt-B08/dlls/msvcrt/process.c msvcrt-B09/dlls/msvcrt/process.c --- msvcrt-B08/dlls/msvcrt/process.c Tue Nov 5 15:32:50 2002 +++ msvcrt-B09/dlls/msvcrt/process.c Tue Nov 5 17:00:53 2002 @@ -50,6 +50,9 @@ static const char szCOMSPEC[] = "COMSPEC"; static const WCHAR wszCOMSPEC[] = {'C','O','M','S','P','E','C', 0}; +static const char szENV_PATH[] = "PATH"; +static const WCHAR wszENV_PATH[] = {'P','A','T','H', 0}; + /* FIXME: Check file extensions for app to run */ static const unsigned int EXE = 'e' << 16 | 'x' << 8 | 'e'; static const unsigned int BAT = 'b' << 16 | 'a' << 8 | 't'; @@ -260,6 +263,59 @@ return ret; } +/* INTERNAL: Convert va_list to a single 'delim'-separated string, with an + * extra '\0' to terminate it (Unicode "port" of the msvcrt_valisttos + * function + */ +static WCHAR *msvcrt_valisttows(const WCHAR* arg0, va_list alist, WCHAR delim) +{ + va_list alist2; + long size; + const WCHAR *arg; + WCHAR *p; + WCHAR *ret; + +#if HAVE_VA_COPY + va_copy(alist2,alist); +#else +# if HAVE___VA_COPY + __va_copy(alist2,alist); +# else + alist2 = alist; +# endif +#endif + + /* Return NULL for an empty environment list */ + if (!arg0 && !delim) + return NULL; + + /* get length */ + arg = arg0; + size = 0; + do + { + size += strlenW(arg)+1; /* +1 for length of delim */ + arg = va_arg(alist, WCHAR *); + } while (arg != NULL); + + ret = (WCHAR *)MSVCRT_malloc((size+1)*sizeof(WCHAR)); + if (!ret) + return NULL; + + /* fill string */ + arg = arg0; + p = ret; + do { + int len = strlenW(arg); + memcpy(p, arg, len*sizeof(WCHAR)); + p += len; + *p++ = delim; + arg = va_arg(alist2, WCHAR *); + } while (arg != NULL); + *p = 0; + return ret; +} + /********************************************************************* * _cwait (MSVCRT.@) */ @@ -316,6 +372,28 @@ } /********************************************************************* + * _wexecl (MSVCRT.@) + * + * Like on Windows, this function does not handle arguments with spaces + * or double-quotes. (Unicode version of _execl) + */ +int _wexecl(const WCHAR *name, const WCHAR* arg0, ...) +{ + va_list ap; + WCHAR *args; + int ret; + + va_start(ap, arg0); + args = msvcrt_valisttows(arg0, ap, ' '); + va_end(ap); + + ret = msvcrt_spawnW(_P_OVERLAY, name, args, NULL); + MSVCRT_free(args); + + return ret; +} + +/********************************************************************* * _execlp (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -328,7 +406,7 @@ int ret; char fullname[MAX_PATH]; - _searchenv(name, "PATH", fullname); + _searchenv(name, szENV_PATH, fullname); va_start(ap, arg0); args = msvcrt_valisttos(arg0, ap, ' '); @@ -341,6 +419,31 @@ } /********************************************************************* + * _wexeclp (MSVCRT.@) + * + * Like on Windows, this function does not handle arguments with spaces + * or double-quotes. (Unicode version of _execlp) + */ +int _wexeclp(const WCHAR* name, const WCHAR* arg0, ...) +{ + va_list ap; + WCHAR *args; + int ret; + WCHAR fullname[MAX_PATH]; + + _wsearchenv(name, wszENV_PATH, fullname); + + va_start(ap, arg0); + args = msvcrt_valisttows(arg0, ap, ' '); + va_end(ap); + + ret = msvcrt_spawnW(_P_OVERLAY, fullname[0] ? fullname : name, args, NULL); + MSVCRT_free(args); + + return ret; +} + +/********************************************************************* * _execv (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -372,7 +475,7 @@ { char fullname[MAX_PATH]; - _searchenv(name, "PATH", fullname); + _searchenv(name, szENV_PATH, fullname); return _spawnve(_P_OVERLAY, fullname[0] ? fullname : name, (const char* const*) argv, envv); } @@ -411,6 +514,28 @@ } /********************************************************************* + * _wspawnl (MSVCRT.@) + * + * Like on Windows, this function does not handle arguments with spaces + * or double-quotes. (Unicode version of the _spawnl function) + */ +int _wspawnl(int flags, const WCHAR *name, const WCHAR* arg0, ...) +{ + va_list ap; + WCHAR *args; + int ret; + + va_start(ap, arg0); + args = msvcrt_valisttows(arg0, ap, ' '); + va_end(ap); + + ret = msvcrt_spawnW(flags, name, args, NULL); + MSVCRT_free(args); + + return ret; +} + +/********************************************************************* * _spawnlp (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -423,7 +548,7 @@ int ret; char fullname[MAX_PATH]; - _searchenv(name, "PATH", fullname); + _searchenv(name, szENV_PATH, fullname); va_start(ap, arg0); args = msvcrt_valisttos(arg0, ap, ' '); @@ -436,6 +561,31 @@ } /********************************************************************* + * _wspawnlp (MSVCRT.@) + * + * Like on Windows, this function does not handle arguments with spaces + * or double-quotes. (Unicode version of _spawnlp) + */ +int _wspawnlp(int flags, const WCHAR *name, const WCHAR *arg0, ...) +{ + va_list ap; + WCHAR *args; + int ret; + WCHAR fullname[MAX_PATH]; + + _wsearchenv(name, wszENV_PATH, fullname); + + va_start(ap, arg0); + args = msvcrt_valisttows(arg0, ap, ' '); + va_end(ap); + + ret = msvcrt_spawnW(flags, fullname[0] ? fullname : name, args, NULL); + MSVCRT_free(args); + + return ret; +} + +/********************************************************************* * _spawnve (MSVCRT.@) * * Like on Windows, this function does not handle arguments with spaces @@ -484,7 +634,7 @@ const char* const* envv) { char fullname[MAX_PATH]; - _searchenv(name, "PATH", fullname); + _searchenv(name, szENV_PATH, fullname); return _spawnve(flags, fullname[0] ? fullname : name, argv, envv); }