From: "Erich E. Hoover" erich.e.hoover@gmail.com
Signed-off-by: Erich E. Hoover erich.e.hoover@gmail.com --- dlls/kernel32/tests/path.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/dlls/kernel32/tests/path.c b/dlls/kernel32/tests/path.c index ca1cbf30ec..ce75f99b63 100644 --- a/dlls/kernel32/tests/path.c +++ b/dlls/kernel32/tests/path.c @@ -1806,10 +1806,11 @@ static void test_SearchPathA(void) static const CHAR testdeprelA[] = "./testdep.dll"; static const CHAR kernel32A[] = "kernel32.dll"; static const CHAR fileA[] = ""; - CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH]; - CHAR *ptrA = NULL; + CHAR pathA[MAX_PATH], buffA[MAX_PATH], path2A[MAX_PATH], path3A[MAX_PATH], curdirA[MAX_PATH]; + CHAR tmpdirA[MAX_PATH], *ptrA = NULL; ULONG_PTR cookie; HANDLE handle; + BOOL bret; DWORD ret;
if (!pSearchPathA) @@ -1883,6 +1884,28 @@ static void test_SearchPathA(void) ret = pDeactivateActCtx(0, cookie); ok(ret, "failed to deactivate context, %u\n", GetLastError()); pReleaseActCtx(handle); + + /* test the search path priority of the working directory */ + GetTempPathA(sizeof(tmpdirA), tmpdirA); + ret = GetCurrentDirectoryA(MAX_PATH, curdirA); + ok(ret, "failed to obtain working directory.\n"); + sprintf(pathA, "%s\%s", tmpdirA, kernel32A); + ret = pSearchPathA(NULL, kernel32A, NULL, sizeof(path2A)/sizeof(CHAR), path2A, NULL); + ok(ret && ret == strlen(path2A), "got %d\n", ret); + bret = CopyFileA(path2A, pathA, FALSE); + ok(bret != 0, "failed to copy test executable to temp directory, %u\n", GetLastError()); + sprintf(path3A, "%s%s%s", curdirA, curdirA[strlen(curdirA)-1] != '\' ? "\" : "", kernel32A); + bret = CopyFileA(path2A, path3A, FALSE); + ok(bret != 0, "failed to copy test executable to launch directory, %u\n", GetLastError()); + bret = SetCurrentDirectoryA(tmpdirA); + ok(bret, "failed to change working directory\n"); + ret = pSearchPathA(NULL, kernel32A, ".exe", sizeof(buffA), buffA, NULL); + ok(ret && ret == strlen(buffA), "got %d\n", ret); + ok(strcmp(buffA, path3A) == 0, "expected %s, got %s\n", path3A, buffA); + bret = SetCurrentDirectoryA(curdirA); + ok(bret, "failed to reset working directory\n"); + DeleteFileA(path3A); + DeleteFileA(pathA); }
static void test_SearchPathW(void)
From: "Erich E. Hoover" erich.e.hoover@gmail.com
NeedCurrentDirectoryForExePath does not use the registry, it only uses the environment variable. MSDN is warning not to use the registry for this feature because the registry location may change or be out of date for the current process.
Signed-off-by: Erich E. Hoover erich.e.hoover@gmail.com --- dlls/kernel32/path.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/kernel32/path.c b/dlls/kernel32/path.c index a389743171..68fd672964 100644 --- a/dlls/kernel32/path.c +++ b/dlls/kernel32/path.c @@ -1948,8 +1948,7 @@ BOOL WINAPI NeedCurrentDirectoryForExePathW( LPCWSTR name ) 'I','n','E','x','e','P','a','t','h',0}; WCHAR env_val;
- /* MSDN mentions some 'registry location'. We do not use registry. */ - FIXME("(%s): partial stub\n", debugstr_w(name)); + TRACE("(%s)\n", debugstr_w(name));
if (strchrW(name, '\')) return TRUE;
From: "Erich E. Hoover" erich.e.hoover@gmail.com
MSDN specifically says that NeedCurrentDirectoryForExePath is used to determine whether to prioritize the current directory in the search.
Signed-off-by: Erich E. Hoover erich.e.hoover@gmail.com --- dlls/kernel32/process.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c index 4e6ba1118e..e335fb52bb 100644 --- a/dlls/kernel32/process.c +++ b/dlls/kernel32/process.c @@ -262,9 +262,17 @@ static HANDLE open_exe_file( const WCHAR *name, struct binary_info *binary_info static BOOL find_exe_file( const WCHAR *name, WCHAR *buffer, int buflen, HANDLE *handle, struct binary_info *binary_info ) { + WCHAR cur_dir[MAX_PATH]; + TRACE("looking for %s\n", debugstr_w(name) );
- if (!SearchPathW( NULL, name, exeW, buflen, buffer, NULL ) && + /* The working directory takes precedence over other locations for CreateProcess unless the + * 'NoDefaultCurrentDirectoryInExePath' environment variable is set (and the executable name + * does not contain a backslash). */ + if ((NeedCurrentDirectoryForExePathW( name ) && GetCurrentDirectoryW( MAX_PATH, cur_dir) && + !SearchPathW( cur_dir, name, exeW, buflen, buffer, NULL )) && + /* not found in the working directory, try the system search path */ + !SearchPathW( NULL, name, exeW, buflen, buffer, NULL ) && /* no builtin found, try native without extension in case it is a Unix app */ !SearchPathW( NULL, name, NULL, buflen, buffer, NULL )) return FALSE;