From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/shell32/shlexec.c | 4 ---- dlls/shell32/tests/shlexec.c | 13 +++++++------ 2 files changed, 7 insertions(+), 10 deletions(-)
diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c index 8c7e3cf0808..fbf39e99fc6 100644 --- a/dlls/shell32/shlexec.c +++ b/dlls/shell32/shlexec.c @@ -110,8 +110,6 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp if (*fmt == '*') { used++; - if (used < len) - *res++ = '"'; while(*args) { used++; @@ -121,8 +119,6 @@ static BOOL SHELL_ArgifyW(WCHAR* out, int len, const WCHAR* fmt, const WCHAR* lp args++; } used++; - if (used < len) - *res++ = '"'; } else { diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c index 50c2e84578b..50de1eeb750 100644 --- a/dlls/shell32/tests/shlexec.c +++ b/dlls/shell32/tests/shlexec.c @@ -1418,11 +1418,11 @@ typedef struct
static const argify_tests_t argify_tests[] = { - /* Start with three simple parameters. Notice that one can reorder and - * duplicate the parameters. Also notice how %* take the raw input - * parameters string, including the trailing spaces, no matter what - * arguments have already been used. - */ + {"ParamsS", "p2 p3 "p4 ", FALSE, " p2 p3 "p4 "}, + + /* Notice that one can reorder and duplicate the parameters. + * Also notice how %* take the raw input parameters string, including + * the trailing spaces, no matter what arguments have already been used. */ {"Params232S", "p2 p3 p4 ", TRUE, " p2 p3 "p2" "p2 p3 p4 ""},
@@ -1567,6 +1567,7 @@ static void test_argify(void) return; }
+ create_test_verb("shlexec.shlexec", "ParamsS", 0, "ParamsS %*"); create_test_verb("shlexec.shlexec", "Params232S", 0, "Params232S %2 %3 "%2" "%*""); create_test_verb("shlexec.shlexec", "Params23456", 0, "Params23456 "%2" "%3" "%4" "%5" "%6""); create_test_verb("shlexec.shlexec", "Params23456789", 0, "Params23456789 "%2" "%3" "%4" "%5" "%6" "%7" "%8" "%9""); @@ -1594,7 +1595,7 @@ static void test_argify(void) if (!cmd) cmd = "(null)"; todo_wine_if(test->todo) okShell(!strcmp(cmd, test->cmd) || broken(!strcmp(cmd, bad)), - "expected '%s', got '%s'\n", cmd, test->cmd); + "expected '%s', got '%s'\n", test->cmd, cmd); test++; } }
From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/shell32/shlexec.c | 12 +++++++ dlls/shell32/tests/shlexec.c | 61 ++++++++++++++++++++++++++++++------ 2 files changed, 63 insertions(+), 10 deletions(-)
diff --git a/dlls/shell32/shlexec.c b/dlls/shell32/shlexec.c index fbf39e99fc6..da2b5fdc2b0 100644 --- a/dlls/shell32/shlexec.c +++ b/dlls/shell32/shlexec.c @@ -473,6 +473,18 @@ static UINT SHELL_FindExecutableByVerb(LPCWSTR lpVerb, LPWSTR key, LPWSTR classn HKEY hkeyClass; WCHAR verb[MAX_PATH];
+ if (*classname == '.') + { + /* Extension, default key value holds class name. Extension may also have + * empty class name and shell\verb\command subkey. */ + WCHAR class[MAX_PATH]; + LONG len; + + len = sizeof(class); + if (!RegQueryValueW(HKEY_CLASSES_ROOT, classname, class, &len) && *class) + wcscpy(classname, class); + } + if (RegOpenKeyExW(HKEY_CLASSES_ROOT, classname, 0, 0x02000000, &hkeyClass)) return SE_ERR_NOASSOC; if (!HCR_GetDefaultVerbW(hkeyClass, lpVerb, verb, ARRAY_SIZE(verb))) diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c index 50de1eeb750..4af4d735b68 100644 --- a/dlls/shell32/tests/shlexec.c +++ b/dlls/shell32/tests/shlexec.c @@ -708,23 +708,31 @@ static BOOL create_test_class(const char* class, BOOL protocol) return TRUE; }
-static BOOL create_test_association(const char* extension) +static BOOL create_test_association_key(const char* extension, const char *class) { HKEY hkey; - char class[MAX_PATH]; LONG rc;
- sprintf(class, "shlexec%s", extension); - rc=RegCreateKeyExA(HKEY_CLASSES_ROOT, extension, 0, NULL, 0, KEY_SET_VALUE, - NULL, &hkey, NULL); + rc = RegCreateKeyExA(HKEY_CLASSES_ROOT, extension, 0, NULL, 0, KEY_SET_VALUE, + NULL, &hkey, NULL); ok(rc == ERROR_SUCCESS || rc == ERROR_ACCESS_DENIED, "could not create association %s (rc=%ld)\n", class, rc); if (rc != ERROR_SUCCESS) return FALSE;
- rc=RegSetValueExA(hkey, NULL, 0, REG_SZ, (LPBYTE) class, strlen(class)+1); - ok(rc==ERROR_SUCCESS, "RegSetValueEx '%s' failed, expected ERROR_SUCCESS, got %ld\n", class, rc); + rc = RegSetValueExA(hkey, NULL, 0, REG_SZ, (LPBYTE) class, strlen(class)+1); + ok(rc == ERROR_SUCCESS, "RegSetValueEx '%s' failed, expected ERROR_SUCCESS, got %ld\n", class, rc); CloseHandle(hkey); + return TRUE; +} + +static BOOL create_test_association(const char* extension) +{ + char class[MAX_PATH]; + + sprintf(class, "shlexec%s", extension); + if (!create_test_association_key(extension, class)) + return FALSE;
return create_test_class(class, FALSE); } @@ -2216,6 +2224,39 @@ static void test_exes(void) okChildInt("argcA", 4); okChildString("argvA3", "Exec");
+ rc=shell_execute_ex(SEE_MASK_NOZONECHECKS | SEE_MASK_CLASSNAME | SEE_MASK_FLAG_NO_UI, NULL, argv0, params, + NULL, ".exe"); + okShell(rc > 32, "returned %Iu\n", rc); + okChildInt("argcA", 4); + okChildString("argvA3", "Exec"); + + if (create_test_association_key(".qqqq", "exefile")) + { + rc = shell_execute_ex(SEE_MASK_NOZONECHECKS | SEE_MASK_CLASSNAME | SEE_MASK_FLAG_NO_UI, NULL, argv0, params, + NULL, ".qqqq"); + okShell(rc > 32, "returned %Iu\n", rc); + okChildInt("argcA", 4); + okChildString("argvA3", "Exec"); + delete_test_association(".qqqq"); + } + else + { + skip("Could not create associtation.\n"); + } + + if (create_test_association_key("qqqq", "exefile")) + { + rc = shell_execute_ex(SEE_MASK_NOZONECHECKS | SEE_MASK_CLASSNAME | SEE_MASK_FLAG_NO_UI, NULL, argv0, params, + NULL, "qqqq"); + okShell(rc < 32, "returned %Iu\n", rc); + todo_wine okShell(rc == SE_ERR_NOASSOC, "returned %Iu\n", rc); + delete_test_association("qqqq"); + } + else + { + skip("Could not create associtation.\n"); + } + if (! skip_noassoc_tests) { sprintf(filename, "%s\test file.noassoc", tmpdir); @@ -2252,10 +2293,10 @@ static void test_exes(void) /* FIXME SEE_MASK_FLAG_NO_UI is only needed due to Wine's bug */ rc = shell_execute_ex(SEE_MASK_CLASSNAME | SEE_MASK_FLAG_NO_UI, NULL, argv0, NULL, NULL, ".shlexec"); - todo_wine okShell(rc > 32, "returned %Iu\n", rc); + okShell(rc > 32, "returned %Iu\n", rc); okChildInt("argcA", 5); - todo_wine okChildString("argvA3", "Open"); - todo_wine okChildPath("argvA4", argv0); + okChildString("argvA3", "Open"); + okChildPath("argvA4", argv0); } }
From: Paul Gofman pgofman@codeweavers.com
Signed-off-by: Paul Gofman pgofman@codeweavers.com --- dlls/shell32/tests/shlexec.c | 24 ++++++++++++++++++++++++ loader/wine.inf.in | 1 + 2 files changed, 25 insertions(+)
diff --git a/dlls/shell32/tests/shlexec.c b/dlls/shell32/tests/shlexec.c index 4af4d735b68..5096eef380f 100644 --- a/dlls/shell32/tests/shlexec.c +++ b/dlls/shell32/tests/shlexec.c @@ -54,6 +54,7 @@ static DLLVERSIONINFO dllver; static BOOL skip_shlexec_tests = FALSE; static BOOL skip_noassoc_tests = FALSE; static HANDLE dde_ready_event; +static BOOL is_elevated;
/*** @@ -2257,6 +2258,19 @@ static void test_exes(void) skip("Could not create associtation.\n"); }
+ if (is_elevated) + { + rc = shell_execute_ex(SEE_MASK_NOZONECHECKS | SEE_MASK_CLASSNAME | SEE_MASK_FLAG_NO_UI, "runas", argv0, params, + NULL, ".exe"); + okShell(rc > 32, "returned %Iu\n", rc); + okChildInt("argcA", 4); + okChildString("argvA3", "Exec"); + } + else + { + skip("No admin privileges, skipping runas test.\n"); + } + if (! skip_noassoc_tests) { sprintf(filename, "%s\test file.noassoc", tmpdir); @@ -2698,6 +2712,9 @@ static void init_test(void) lnk_desc_t desc; DWORD rc; HRESULT r; + TOKEN_ELEVATION elevation; + HANDLE token; + BOOL ret;
hdll=GetModuleHandleA("shell32.dll"); pDllGetVersion=(void*)GetProcAddress(hdll, "DllGetVersion"); @@ -2822,6 +2839,13 @@ static void init_test(void)
/* Set an environment variable to see if it is inherited */ SetEnvironmentVariableA("ShlexecVar", "Present"); + + ret = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token); + ok(ret, "OpenProcessToken failed.\n"); + ret = GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &rc); + ok(ret, "GetTokenInformation failed.\n"); + is_elevated = elevation.TokenIsElevated; + CloseHandle(token); }
static void cleanup_test(void) diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 58283e271de..e7b435ed0f0 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -272,6 +272,7 @@ HKCR,DirectShow,,16 HKCR,exefile,,2,"Application" HKCR,exefile\DefaultIcon,,2,"%1" HKCR,exefile\shell\open\command,,2,"""%1"" %*" +HKCR,exefile\shell\runas\command,,2,"""%1"" %*" HKCR,folder\shell\open\ddeexec,,2,"[ViewFolder("%l", %I, %S)]" HKCR,folder\shell\open\ddeexec,"NoActivateHandler",2,"" HKCR,folder\shell\open\ddeexec\application,,2,"Folders"