Commit 2d139562 authored by Alexandre Julliard's avatar Alexandre Julliard

The "Path" value of the "App Paths" entry should be handled in

ShellExecute by changing PATH in the new process, instead of being done in SearchPath.
parent 8b255842
...@@ -218,7 +218,7 @@ inline static void __SHCloneStrWtoA(char ** target, const WCHAR * source) ...@@ -218,7 +218,7 @@ inline static void __SHCloneStrWtoA(char ** target, const WCHAR * source)
#define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16)) #define HINSTANCE_32(h16) ((HINSTANCE)(ULONG_PTR)(h16))
#define HINSTANCE_16(h32) (LOWORD(h32)) #define HINSTANCE_16(h32) (LOWORD(h32))
typedef UINT (*SHELL_ExecuteA1632)(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait); typedef UINT (*SHELL_ExecuteA1632)(char *lpCmd, void *env, LPSHELLEXECUTEINFOA sei, BOOL shWait);
BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execfunc); BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execfunc);
#endif #endif
...@@ -123,7 +123,7 @@ static BOOL argify(char* res, int len, const char* fmt, const char* lpFile) ...@@ -123,7 +123,7 @@ static BOOL argify(char* res, int len, const char* fmt, const char* lpFile)
* SHELL_ExecuteA [Internal] * SHELL_ExecuteA [Internal]
* *
*/ */
static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait) static UINT SHELL_ExecuteA(char *lpCmd, void *env, LPSHELLEXECUTEINFOA sei, BOOL shWait)
{ {
STARTUPINFOA startup; STARTUPINFOA startup;
PROCESS_INFORMATION info; PROCESS_INFORMATION info;
...@@ -135,7 +135,7 @@ static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait) ...@@ -135,7 +135,7 @@ static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait)
startup.dwFlags = STARTF_USESHOWWINDOW; startup.dwFlags = STARTF_USESHOWWINDOW;
startup.wShowWindow = sei->nShow; startup.wShowWindow = sei->nShow;
if (CreateProcessA(NULL, lpCmd, NULL, NULL, FALSE, 0, if (CreateProcessA(NULL, lpCmd, NULL, NULL, FALSE, 0,
NULL, sei->lpDirectory, &startup, &info)) env, sei->lpDirectory, &startup, &info))
{ {
/* Give 30 seconds to the app to come up, if desired. Probably only needed /* Give 30 seconds to the app to come up, if desired. Probably only needed
when starting app immediately before making a DDE connection. */ when starting app immediately before making a DDE connection. */
...@@ -159,6 +159,64 @@ static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait) ...@@ -159,6 +159,64 @@ static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait)
return retval; return retval;
} }
/***********************************************************************
* build_env
*
* Build the environment for the new process, adding the specified
* path to the PATH variable. Returned pointer must be freed by caller.
*/
static void *build_env( const char *path )
{
char *strings, *new_env;
char *p, *p2;
int total = strlen(path) + 1;
BOOL got_path = FALSE;
if (!(strings = GetEnvironmentStringsA())) return NULL;
p = strings;
while (*p)
{
int len = strlen(p) + 1;
if (!strncasecmp( p, "PATH=", 5 )) got_path = TRUE;
total += len;
p += len;
}
if (!got_path) total += 5; /* we need to create PATH */
total++; /* terminating null */
if (!(new_env = HeapAlloc( GetProcessHeap(), 0, total )))
{
FreeEnvironmentStringsA( strings );
return NULL;
}
p = strings;
p2 = new_env;
while (*p)
{
int len = strlen(p) + 1;
memcpy( p2, p, len );
if (!strncasecmp( p, "PATH=", 5 ))
{
p2[len - 1] = ';';
strcpy( p2 + len, path );
p2 += strlen(path) + 1;
}
p += len;
p2 += len;
}
if (!got_path)
{
strcpy( p2, "PATH=" );
strcat( p2, path );
p2 += strlen(p2) + 1;
}
*p2 = 0;
FreeEnvironmentStringsA( strings );
return new_env;
}
/*********************************************************************** /***********************************************************************
* SHELL_TryAppPath * SHELL_TryAppPath
* *
...@@ -167,30 +225,31 @@ static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait) ...@@ -167,30 +225,31 @@ static UINT SHELL_ExecuteA(char *lpCmd, LPSHELLEXECUTEINFOA sei, BOOL shWait)
* On entry: szName is a filename (probably without path separators). * On entry: szName is a filename (probably without path separators).
* On exit: if szName found in "App Path", place full path in lpResult, and return true * On exit: if szName found in "App Path", place full path in lpResult, and return true
*/ */
static BOOL SHELL_TryAppPath( LPCSTR szName, LPSTR lpResult) static BOOL SHELL_TryAppPath( LPCSTR szName, LPSTR lpResult, void**env)
{ {
HKEY hkApp = 0; HKEY hkApp = 0;
char szAppKey[256]; char buffer[256];
LONG len; LONG len;
LONG res; LONG res;
BOOL found = FALSE; BOOL found = FALSE;
sprintf(szAppKey, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s", szName); if (env) *env = NULL;
res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, szAppKey, 0, KEY_READ, &hkApp); sprintf(buffer, "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\%s", szName);
if (res) { res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, buffer, 0, KEY_READ, &hkApp);
/*TRACE("RegOpenKeyExA(HKEY_LOCAL_MACHINE, %s,) returns %ld\n", szAppKey, res);*/ if (res) goto end;
goto end;
}
len = MAX_PATH; len = MAX_PATH;
res = RegQueryValueA(hkApp, NULL, lpResult, &len); res = RegQueryValueA(hkApp, NULL, lpResult, &len);
if (res) { if (res) goto end;
/*TRACE("RegQueryValueA(hkApp, NULL,) returns %ld\n", res);*/
goto end;
}
/*TRACE("%s -> %s\n", szName, lpResult);*/
found = TRUE; found = TRUE;
if (env)
{
DWORD count = sizeof(buffer);
if (!RegQueryValueExA(hkApp, "Path", NULL, NULL, buffer, &count) && buffer[0])
*env = build_env( buffer );
}
end: end:
if (hkApp) RegCloseKey(hkApp); if (hkApp) RegCloseKey(hkApp);
return found; return found;
...@@ -211,7 +270,7 @@ end: ...@@ -211,7 +270,7 @@ end:
* on the operation) * on the operation)
*/ */
static UINT SHELL_FindExecutable(LPCSTR lpPath, LPCSTR lpFile, LPCSTR lpOperation, static UINT SHELL_FindExecutable(LPCSTR lpPath, LPCSTR lpFile, LPCSTR lpOperation,
LPSTR lpResult, LPSTR key) LPSTR lpResult, LPSTR key, void **env)
{ {
char *extension = NULL; /* pointer to file extension */ char *extension = NULL; /* pointer to file extension */
char tmpext[5]; /* local copy to mung as we please */ char tmpext[5]; /* local copy to mung as we please */
...@@ -237,7 +296,7 @@ static UINT SHELL_FindExecutable(LPCSTR lpPath, LPCSTR lpFile, LPCSTR lpOperatio ...@@ -237,7 +296,7 @@ static UINT SHELL_FindExecutable(LPCSTR lpPath, LPCSTR lpFile, LPCSTR lpOperatio
return 2; /* File not found. Close enough, I guess. */ return 2; /* File not found. Close enough, I guess. */
} }
if (SHELL_TryAppPath( lpFile, lpResult )) if (SHELL_TryAppPath( lpFile, lpResult, env ))
{ {
TRACE("found %s via App Paths\n", lpResult); TRACE("found %s via App Paths\n", lpResult);
return 33; return 33;
...@@ -401,7 +460,7 @@ static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv, ...@@ -401,7 +460,7 @@ static HDDEDATA CALLBACK dde_cb(UINT uType, UINT uFmt, HCONV hConv,
* *
*/ */
static unsigned dde_connect(char* key, char* start, char* ddeexec, static unsigned dde_connect(char* key, char* start, char* ddeexec,
const char* lpFile, const char* lpFile, void *env,
LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execfunc) LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execfunc)
{ {
char* endkey = key + strlen(key); char* endkey = key + strlen(key);
...@@ -442,7 +501,7 @@ static unsigned dde_connect(char* key, char* start, char* ddeexec, ...@@ -442,7 +501,7 @@ static unsigned dde_connect(char* key, char* start, char* ddeexec,
if (!hConv) if (!hConv)
{ {
TRACE("Launching '%s'\n", start); TRACE("Launching '%s'\n", start);
ret = execfunc(start, sei, TRUE); ret = execfunc(start, env, sei, TRUE);
if (ret < 32) if (ret < 32)
{ {
TRACE("Couldn't launch\n"); TRACE("Couldn't launch\n");
...@@ -477,7 +536,8 @@ static unsigned dde_connect(char* key, char* start, char* ddeexec, ...@@ -477,7 +536,8 @@ static unsigned dde_connect(char* key, char* start, char* ddeexec,
/************************************************************************* /*************************************************************************
* execute_from_key [Internal] * execute_from_key [Internal]
*/ */
static UINT execute_from_key(LPSTR key, LPCSTR lpFile, LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execfunc) static UINT execute_from_key(LPSTR key, LPCSTR lpFile, void *env,
LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execfunc)
{ {
char cmd[1024] = ""; char cmd[1024] = "";
LONG cmdlen = sizeof(cmd); LONG cmdlen = sizeof(cmd);
...@@ -499,14 +559,14 @@ static UINT execute_from_key(LPSTR key, LPCSTR lpFile, LPSHELLEXECUTEINFOA sei, ...@@ -499,14 +559,14 @@ static UINT execute_from_key(LPSTR key, LPCSTR lpFile, LPSHELLEXECUTEINFOA sei,
if (RegQueryValueA(HKEY_CLASSES_ROOT, key, param, &paramlen) == ERROR_SUCCESS) if (RegQueryValueA(HKEY_CLASSES_ROOT, key, param, &paramlen) == ERROR_SUCCESS)
{ {
TRACE("Got ddeexec %s => %s\n", key, param); TRACE("Got ddeexec %s => %s\n", key, param);
retval = dde_connect(key, cmd, param, lpFile, sei, execfunc); retval = dde_connect(key, cmd, param, lpFile, env, sei, execfunc);
} }
else else
{ {
/* Is there a replace() function anywhere? */ /* Is there a replace() function anywhere? */
cmd[cmdlen] = '\0'; cmd[cmdlen] = '\0';
argify(param, sizeof(param), cmd, lpFile); argify(param, sizeof(param), cmd, lpFile);
retval = execfunc(param, sei, FALSE); retval = execfunc(param, env, sei, FALSE);
} }
} }
else TRACE("ooch\n"); else TRACE("ooch\n");
...@@ -540,7 +600,7 @@ HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResu ...@@ -540,7 +600,7 @@ HINSTANCE WINAPI FindExecutableA(LPCSTR lpFile, LPCSTR lpDirectory, LPSTR lpResu
SetCurrentDirectoryA(lpDirectory); SetCurrentDirectoryA(lpDirectory);
} }
retval = SHELL_FindExecutable(lpDirectory, lpFile, "open", lpResult, NULL); retval = SHELL_FindExecutable(lpDirectory, lpFile, "open", lpResult, NULL, NULL);
TRACE("returning %s\n", lpResult); TRACE("returning %s\n", lpResult);
if (lpDirectory) if (lpDirectory)
...@@ -564,6 +624,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf ...@@ -564,6 +624,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf
{ {
CHAR szApplicationName[MAX_PATH],szCommandline[MAX_PATH],szPidl[20],fileName[MAX_PATH]; CHAR szApplicationName[MAX_PATH],szCommandline[MAX_PATH],szPidl[20],fileName[MAX_PATH];
LPSTR pos; LPSTR pos;
void *env;
int gap, len; int gap, len;
char lpstrProtocol[256]; char lpstrProtocol[256];
LPCSTR lpFile,lpOperation; LPCSTR lpFile,lpOperation;
...@@ -644,7 +705,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf ...@@ -644,7 +705,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf
strcat(cmd, " "); strcat(cmd, " ");
strcat(cmd, szApplicationName); strcat(cmd, szApplicationName);
} }
retval = execfunc(cmd, sei, FALSE); retval = execfunc(cmd, NULL, sei, FALSE);
if (retval > 32) if (retval > 32)
return TRUE; return TRUE;
else else
...@@ -668,13 +729,13 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf ...@@ -668,13 +729,13 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf
strcat(szApplicationName, szCommandline); strcat(szApplicationName, szCommandline);
} }
retval = execfunc(szApplicationName, sei, FALSE); retval = execfunc(szApplicationName, NULL, sei, FALSE);
if (retval > 32) if (retval > 32)
return TRUE; return TRUE;
/* Else, try to find the executable */ /* Else, try to find the executable */
cmd[0] = '\0'; cmd[0] = '\0';
retval = SHELL_FindExecutable(sei->lpDirectory, lpFile, lpOperation, cmd, lpstrProtocol); retval = SHELL_FindExecutable(sei->lpDirectory, lpFile, lpOperation, cmd, lpstrProtocol, &env);
if (retval > 32) /* Found */ if (retval > 32) /* Found */
{ {
CHAR szQuotedCmd[MAX_PATH+2]; CHAR szQuotedCmd[MAX_PATH+2];
...@@ -687,9 +748,10 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf ...@@ -687,9 +748,10 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf
sprintf(szQuotedCmd, "\"%s\"", cmd); sprintf(szQuotedCmd, "\"%s\"", cmd);
TRACE("%s/%s => %s/%s\n", szApplicationName, lpOperation, szQuotedCmd, lpstrProtocol); TRACE("%s/%s => %s/%s\n", szApplicationName, lpOperation, szQuotedCmd, lpstrProtocol);
if (*lpstrProtocol) if (*lpstrProtocol)
retval = execute_from_key(lpstrProtocol, szApplicationName, sei, execfunc); retval = execute_from_key(lpstrProtocol, szApplicationName, env, sei, execfunc);
else else
retval = execfunc(szQuotedCmd, sei, FALSE); retval = execfunc(szQuotedCmd, env, sei, FALSE);
if (env) HeapFree( GetProcessHeap(), 0, env );
} }
else if (PathIsURLA((LPSTR)lpFile)) /* File not found, check for URL */ else if (PathIsURLA((LPSTR)lpFile)) /* File not found, check for URL */
{ {
...@@ -717,7 +779,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf ...@@ -717,7 +779,7 @@ BOOL WINAPI ShellExecuteExA32 (LPSHELLEXECUTEINFOA sei, SHELL_ExecuteA1632 execf
lpFile += iSize; lpFile += iSize;
while (*lpFile == ':') lpFile++; while (*lpFile == ':') lpFile++;
} }
retval = execute_from_key(lpstrProtocol, lpFile, sei, execfunc); retval = execute_from_key(lpstrProtocol, lpFile, NULL, sei, execfunc);
} }
/* Check if file specified is in the form www.??????.*** */ /* Check if file specified is in the form www.??????.*** */
else if (!strncasecmp(lpFile, "www", 3)) else if (!strncasecmp(lpFile, "www", 3))
......
...@@ -795,64 +795,6 @@ static BOOL DIR_TryModulePath( LPCWSTR name, DOS_FULL_NAME *full_name, BOOL win3 ...@@ -795,64 +795,6 @@ static BOOL DIR_TryModulePath( LPCWSTR name, DOS_FULL_NAME *full_name, BOOL win3
/*********************************************************************** /***********************************************************************
* DIR_TryAppPath
*
* Helper function for DIR_SearchPath.
*/
static BOOL DIR_TryAppPath( LPCWSTR name, DOS_FULL_NAME *full_name )
{
HKEY hkAppPaths = 0, hkApp = 0;
WCHAR buffer[MAX_PATHNAME_LEN], *lpAppPaths;
LPWSTR lpFileName;
BOOL res = FALSE;
DWORD count;
OBJECT_ATTRIBUTES attr;
UNICODE_STRING nameW;
KEY_VALUE_PARTIAL_INFORMATION *info;
static const WCHAR PathW[] = {'P','a','t','h',0};
static const WCHAR AppPathsW[] = {'M','a','c','h','i','n','e','\\',
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'A','p','p',' ','P','a','t','h','s',0};
attr.Length = sizeof(attr);
attr.RootDirectory = 0;
attr.ObjectName = &nameW;
attr.Attributes = 0;
attr.SecurityDescriptor = NULL;
attr.SecurityQualityOfService = NULL;
RtlInitUnicodeString( &nameW, AppPathsW );
if (NtOpenKey( &hkAppPaths, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) return FALSE;
if (!GetModuleFileNameW(0, buffer, MAX_PATHNAME_LEN))
{
WARN("huh, module not found ??\n");
goto end;
}
lpFileName = strrchrW(buffer, '\\');
if (!lpFileName) lpFileName = buffer;
else lpFileName++; /* skip '\\' */
attr.RootDirectory = hkAppPaths;
RtlInitUnicodeString( &nameW, lpFileName );
if (NtOpenKey( &hkApp, KEY_ALL_ACCESS, &attr ) != STATUS_SUCCESS) goto end;
RtlInitUnicodeString( &nameW, PathW );
if (NtQueryValueKey( hkApp, &nameW, KeyValuePartialInformation,
buffer, sizeof(buffer)-sizeof(WCHAR), &count )) goto end;
info = (KEY_VALUE_PARTIAL_INFORMATION *)buffer;
lpAppPaths = (WCHAR *)info->Data;
lpAppPaths[info->DataLength/sizeof(WCHAR)] = 0;
res = DIR_SearchSemicolonedPaths(name, full_name, lpAppPaths);
end:
if (hkApp) NtClose(hkApp);
if (hkAppPaths) NtClose(hkAppPaths);
return res;
}
/***********************************************************************
* DIR_SearchPath * DIR_SearchPath
* *
* Implementation of SearchPathA. 'win32' specifies whether the search * Implementation of SearchPathA. 'win32' specifies whether the search
...@@ -929,10 +871,6 @@ DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext, ...@@ -929,10 +871,6 @@ DWORD DIR_SearchPath( LPCWSTR path, LPCWSTR name, LPCWSTR ext,
if (!win32 && DIR_TryModulePath( name, full_name, win32 )) goto done; if (!win32 && DIR_TryModulePath( name, full_name, win32 )) goto done;
/* Try the "App Paths" entry if existing (undocumented ??) */
if (DIR_TryAppPath(name, full_name))
goto done;
/* Try all directories in path */ /* Try all directories in path */
ret = DIR_TryEnvironmentPath( name, full_name, NULL ); ret = DIR_TryEnvironmentPath( name, full_name, NULL );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment