Author: akhaldi
Date: Wed Mar 9 08:43:20 2016
New Revision: 70977
URL:
http://svn.reactos.org/svn/reactos?rev=70977&view=rev
Log:
[SHELL32_WINETEST] Sync with Wine Staging 1.9.4. CORE-10912
Modified:
trunk/rostests/winetests/shell32/progman_dde.c
trunk/rostests/winetests/shell32/shellole.c
trunk/rostests/winetests/shell32/shlexec.c
trunk/rostests/winetests/shell32/shlfolder.c
Modified: trunk/rostests/winetests/shell32/progman_dde.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/progman…
==============================================================================
--- trunk/rostests/winetests/shell32/progman_dde.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/shell32/progman_dde.c [iso-8859-1] Wed Mar 9 08:43:20 2016
@@ -372,7 +372,13 @@
for (i = 0; window == NULL && i < PDDE_POLL_NUM; i++)
{
Sleep(PDDE_POLL_TIME);
- window = FindWindowA(NULL, winName);
+ /* Specify the window class name to make sure what we find is really an
+ * Explorer window. Explorer used two different window classes so try
+ * both.
+ */
+ window = FindWindowA("ExplorerWClass", winName);
+ if (!window)
+ window = FindWindowA("CabinetWClass", winName);
}
ok (window != NULL, "Window \"%s\" was not created in %i seconds -
assumed failure.%s\n",
winName, PDDE_POLL_NUM*PDDE_POLL_TIME/1000,
GetStringFromTestParams(testParams));
Modified: trunk/rostests/winetests/shell32/shellole.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shellol…
==============================================================================
--- trunk/rostests/winetests/shell32/shellole.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/shell32/shellole.c [iso-8859-1] Wed Mar 9 08:43:20 2016
@@ -74,6 +74,7 @@
static HRESULT (WINAPI *pSHPropStgWriteMultiple)(IPropertyStorage*, UINT*,
ULONG, const PROPSPEC*, PROPVARIANT*, PROPID);
static HRESULT (WINAPI *pSHCreateQueryCancelAutoPlayMoniker)(IMoniker**);
+static HRESULT (WINAPI *pSHCreateSessionKey)(REGSAM, HKEY*);
static void init(void)
{
@@ -83,6 +84,7 @@
pSHPropStgReadMultiple = (void*)GetProcAddress(hmod,
"SHPropStgReadMultiple");
pSHPropStgWriteMultiple = (void*)GetProcAddress(hmod,
"SHPropStgWriteMultiple");
pSHCreateQueryCancelAutoPlayMoniker = (void*)GetProcAddress(hmod,
"SHCreateQueryCancelAutoPlayMoniker");
+ pSHCreateSessionKey = (void*)GetProcAddress(hmod, (char*)723);
}
static HRESULT WINAPI PropertyStorage_QueryInterface(IPropertyStorage *This,
@@ -857,6 +859,36 @@
}
#undef DROPTEST_FILENAME
+static void test_SHCreateSessionKey(void)
+{
+ HKEY hkey, hkey2;
+ HRESULT hr;
+
+ if (!pSHCreateSessionKey)
+ {
+ skip("SHCreateSessionKey is not implemented\n");
+ return;
+ }
+
+if (0) /* crashes on native */
+ hr = pSHCreateSessionKey(KEY_READ, NULL);
+
+ hkey = (HKEY)0xdeadbeef;
+ hr = pSHCreateSessionKey(0, &hkey);
+ todo_wine ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr);
+ todo_wine ok(hkey == NULL, "got %p\n", hkey);
+
+ hr = pSHCreateSessionKey(KEY_READ, &hkey);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+
+ hr = pSHCreateSessionKey(KEY_READ, &hkey2);
+ ok(hr == S_OK, "got 0x%08x\n", hr);
+ ok(hkey != hkey2, "got %p, %p\n", hkey, hkey2);
+
+ RegCloseKey(hkey);
+ RegCloseKey(hkey2);
+}
+
START_TEST(shellole)
{
init();
@@ -864,4 +896,5 @@
test_SHPropStg_functions();
test_SHCreateQueryCancelAutoPlayMoniker();
test_DragQueryFile();
-}
+ test_SHCreateSessionKey();
+}
Modified: trunk/rostests/winetests/shell32/shlexec.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shlexec…
==============================================================================
--- trunk/rostests/winetests/shell32/shlexec.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/shell32/shlexec.c [iso-8859-1] Wed Mar 9 08:43:20 2016
@@ -1,7 +1,7 @@
/*
* Unit test of the ShellExecute function.
*
- * Copyright 2005 Francois Gouget for CodeWeavers
+ * Copyright 2005, 2016 Francois Gouget for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -26,8 +26,6 @@
* - ShellExecute("foo.shlexec") with no path should work if foo.shlexec is
* in the PATH
* - test associations that use %l, %L or "%1" instead of %1
- * - we may want to test ShellExecuteEx() instead of ShellExecute()
- * and then we could also check its return value
* - ShellExecuteEx() also calls SetLastError() with meaningful values which
* we could check
*/
@@ -64,18 +62,421 @@
/***
*
+ * Helpers to read from / write to the child process results file.
+ * (borrowed from dlls/kernel32/tests/process.c)
+ *
+ ***/
+
+static const char* encodeA(const char* str)
+{
+ static char encoded[2*1024+1];
+ char* ptr;
+ size_t len,i;
+
+ if (!str) return "";
+ len = strlen(str) + 1;
+ if (len >= sizeof(encoded)/2)
+ {
+ fprintf(stderr, "string is too long!\n");
+ assert(0);
+ }
+ ptr = encoded;
+ for (i = 0; i < len; i++)
+ sprintf(&ptr[i * 2], "%02x", (unsigned char)str[i]);
+ ptr[2 * len] = '\0';
+ return ptr;
+}
+
+static unsigned decode_char(char c)
+{
+ if (c >= '0' && c <= '9') return c - '0';
+ if (c >= 'a' && c <= 'f') return c - 'a' + 10;
+ assert(c >= 'A' && c <= 'F');
+ return c - 'A' + 10;
+}
+
+static char* decodeA(const char* str)
+{
+ static char decoded[1024];
+ char* ptr;
+ size_t len,i;
+
+ len = strlen(str) / 2;
+ if (!len--) return NULL;
+ if (len >= sizeof(decoded))
+ {
+ fprintf(stderr, "string is too long!\n");
+ assert(0);
+ }
+ ptr = decoded;
+ for (i = 0; i < len; i++)
+ ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
+ ptr[len] = '\0';
+ return ptr;
+}
+
+static void WINETEST_PRINTF_ATTR(2,3) childPrintf(HANDLE h, const char* fmt, ...)
+{
+ va_list valist;
+ char buffer[1024];
+ DWORD w;
+
+ va_start(valist, fmt);
+ vsprintf(buffer, fmt, valist);
+ va_end(valist);
+ WriteFile(h, buffer, strlen(buffer), &w, NULL);
+}
+
+static char* getChildString(const char* sect, const char* key)
+{
+ char buf[1024];
+ char* ret;
+
+ GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), child_file);
+ if (buf[0] == '\0' || (buf[0] == '-' && buf[1] ==
'\0')) return NULL;
+ assert(!(strlen(buf) & 1));
+ ret = decodeA(buf);
+ return ret;
+}
+
+
+/***
+ *
+ * Child code
+ *
+ ***/
+
+#define CHILD_DDE_TIMEOUT 2500
+static DWORD ddeInst;
+static HSZ hszTopic;
+static char ddeExec[MAX_PATH], ddeApplication[MAX_PATH];
+static BOOL post_quit_on_execute;
+
+/* Handle DDE for doChild() and test_dde_default_app() */
+static HDDEDATA CALLBACK ddeCb(UINT uType, UINT uFmt, HCONV hConv,
+ HSZ hsz1, HSZ hsz2, HDDEDATA hData,
+ ULONG_PTR dwData1, ULONG_PTR dwData2)
+{
+ DWORD size = 0;
+
+ if (winetest_debug > 2)
+ trace("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
+ uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
+
+ switch (uType)
+ {
+ case XTYP_CONNECT:
+ if (!DdeCmpStringHandles(hsz1, hszTopic))
+ {
+ size = DdeQueryStringA(ddeInst, hsz2, ddeApplication, MAX_PATH,
CP_WINANSI);
+ ok(size < MAX_PATH, "got size %d\n", size);
+ assert(size < MAX_PATH);
+ return (HDDEDATA)TRUE;
+ }
+ return (HDDEDATA)FALSE;
+
+ case XTYP_EXECUTE:
+ size = DdeGetData(hData, (LPBYTE)ddeExec, MAX_PATH, 0);
+ ok(size < MAX_PATH, "got size %d\n", size);
+ assert(size < MAX_PATH);
+ DdeFreeDataHandle(hData);
+ if (post_quit_on_execute)
+ PostQuitMessage(0);
+ return (HDDEDATA)DDE_FACK;
+
+ default:
+ return NULL;
+ }
+}
+
+static HANDLE hEvent;
+static void init_event(const char* child_file)
+{
+ char* event_name;
+ event_name=strrchr(child_file, '\\')+1;
+ hEvent=CreateEventA(NULL, FALSE, FALSE, event_name);
+}
+
+/*
+ * This is just to make sure the child won't run forever stuck in a
+ * GetMessage() loop when DDE fails for some reason.
+ */
+static void CALLBACK childTimeout(HWND wnd, UINT msg, UINT_PTR timer, DWORD time)
+{
+ trace("childTimeout called\n");
+
+ PostQuitMessage(0);
+}
+
+static void doChild(int argc, char** argv)
+{
+ char *filename, buffer[MAX_PATH];
+ HANDLE hFile, map;
+ int i;
+ UINT_PTR timer;
+
+ filename=argv[2];
+ hFile=CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return;
+
+ /* Arguments */
+ childPrintf(hFile, "[Child]\r\n");
+ if (winetest_debug > 2)
+ {
+ trace("cmdlineA='%s'\n", GetCommandLineA());
+ trace("argcA=%d\n", argc);
+ }
+ childPrintf(hFile, "cmdlineA=%s\r\n", encodeA(GetCommandLineA()));
+ childPrintf(hFile, "argcA=%d\r\n", argc);
+ for (i = 0; i < argc; i++)
+ {
+ if (winetest_debug > 2)
+ trace("argvA%d='%s'\n", i, argv[i]);
+ childPrintf(hFile, "argvA%d=%s\r\n", i, encodeA(argv[i]));
+ }
+ GetModuleFileNameA(GetModuleHandleA(NULL), buffer, sizeof(buffer));
+ childPrintf(hFile, "longPath=%s\r\n", encodeA(buffer));
+
+ /* Check environment variable inheritance */
+ *buffer = '\0';
+ SetLastError(0);
+ GetEnvironmentVariableA("ShlexecVar", buffer, sizeof(buffer));
+ childPrintf(hFile, "ShlexecVarLE=%d\r\n", GetLastError());
+ childPrintf(hFile, "ShlexecVar=%s\r\n", encodeA(buffer));
+
+ map = OpenFileMappingA(FILE_MAP_READ, FALSE, "winetest_shlexec_dde_map");
+ if (map != NULL)
+ {
+ HANDLE dde_ready;
+ char *shared_block = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 4096);
+ CloseHandle(map);
+ if (shared_block[0] != '\0' || shared_block[1] != '\0')
+ {
+ HDDEDATA hdde;
+ HSZ hszApplication;
+ MSG msg;
+ UINT rc;
+
+ post_quit_on_execute = TRUE;
+ ddeInst = 0;
+ rc = DdeInitializeA(&ddeInst, ddeCb, CBF_SKIP_ALLNOTIFICATIONS |
CBF_FAIL_ADVISES |
+ CBF_FAIL_POKES | CBF_FAIL_REQUESTS, 0);
+ ok(rc == DMLERR_NO_ERROR, "DdeInitializeA() returned %d\n", rc);
+ hszApplication = DdeCreateStringHandleA(ddeInst, shared_block, CP_WINANSI);
+ ok(hszApplication != NULL, "DdeCreateStringHandleA(%s) = NULL\n",
shared_block);
+ shared_block += strlen(shared_block) + 1;
+ hszTopic = DdeCreateStringHandleA(ddeInst, shared_block, CP_WINANSI);
+ ok(hszTopic != NULL, "DdeCreateStringHandleA(%s) = NULL\n",
shared_block);
+ hdde = DdeNameService(ddeInst, hszApplication, 0, DNS_REGISTER |
DNS_FILTEROFF);
+ ok(hdde != NULL, "DdeNameService() failed le=%u\n",
GetLastError());
+
+ timer = SetTimer(NULL, 0, CHILD_DDE_TIMEOUT, childTimeout);
+
+ dde_ready = OpenEventA(EVENT_MODIFY_STATE, FALSE,
"winetest_shlexec_dde_ready");
+ SetEvent(dde_ready);
+ CloseHandle(dde_ready);
+
+ while (GetMessageA(&msg, NULL, 0, 0))
+ {
+ if (winetest_debug > 2)
+ trace("msg %d lParam=%ld wParam=%lu\n", msg.message,
msg.lParam, msg.wParam);
+ DispatchMessageA(&msg);
+ }
+
+ Sleep(500);
+ KillTimer(NULL, timer);
+ hdde = DdeNameService(ddeInst, hszApplication, 0, DNS_UNREGISTER);
+ ok(hdde != NULL, "DdeNameService() failed le=%u\n",
GetLastError());
+ ok(DdeFreeStringHandle(ddeInst, hszTopic),
"DdeFreeStringHandle(topic)\n");
+ ok(DdeFreeStringHandle(ddeInst, hszApplication),
"DdeFreeStringHandle(application)\n");
+ ok(DdeUninitialize(ddeInst), "DdeUninitialize() failed\n");
+ }
+ else
+ {
+ dde_ready = OpenEventA(EVENT_MODIFY_STATE, FALSE,
"winetest_shlexec_dde_ready");
+ SetEvent(dde_ready);
+ CloseHandle(dde_ready);
+ }
+
+ UnmapViewOfFile(shared_block);
+
+ childPrintf(hFile, "ddeExec=%s\r\n", encodeA(ddeExec));
+ }
+
+ childPrintf(hFile, "Failures=%d\r\n", winetest_get_failures());
+ CloseHandle(hFile);
+
+ init_event(filename);
+ SetEvent(hEvent);
+ CloseHandle(hEvent);
+}
+
+static void dump_child_(const char* file, int line)
+{
+ if (winetest_debug > 1)
+ {
+ char key[18];
+ char* str;
+ int i, c;
+
+ str=getChildString("Child", "cmdlineA");
+ trace_(file, line)("cmdlineA='%s'\n", str);
+ c=GetPrivateProfileIntA("Child", "argcA", -1, child_file);
+ trace_(file, line)("argcA=%d\n",c);
+ for (i=0;i<c;i++)
+ {
+ sprintf(key, "argvA%d", i);
+ str=getChildString("Child", key);
+ trace_(file, line)("%s='%s'\n", key, str);
+ }
+
+ c=GetPrivateProfileIntA("Child", "ShlexecVarLE", -1,
child_file);
+ trace_(file, line)("ShlexecVarLE=%d\n", c);
+ str=getChildString("Child", "ShlexecVar");
+ trace_(file, line)("ShlexecVar='%s'\n", str);
+
+ c=GetPrivateProfileIntA("Child", "Failures", -1,
child_file);
+ trace_(file, line)("Failures=%d\n", c);
+ }
+}
+
+
+/***
+ *
+ * Helpers to check the ShellExecute() / child process results.
+ *
+ ***/
+
+static char shell_call[2048];
+static void WINETEST_PRINTF_ATTR(2,3) _okShell(int condition, const char *msg, ...)
+{
+ va_list valist;
+ char buffer[2048];
+
+ strcpy(buffer, shell_call);
+ strcat(buffer, " ");
+ va_start(valist, msg);
+ vsprintf(buffer+strlen(buffer), msg, valist);
+ va_end(valist);
+ winetest_ok(condition, "%s", buffer);
+}
+#define okShell_(file, line) (winetest_set_location(file, line), 0) ? (void)0 : _okShell
+#define okShell okShell_(__FILE__, __LINE__)
+
+static char assoc_desc[2048];
+void reset_association_description(void)
+{
+ *assoc_desc = '\0';
+}
+
+static void okChildString_(const char* file, int line, const char* key, const char*
expected, const char* bad)
+{
+ char* result;
+ result=getChildString("Child", key);
+ if (!result)
+ {
+ okShell_(file, line)(FALSE, "%s expected '%s', but key not found or
empty\n", key, expected);
+ return;
+ }
+ okShell_(file, line)(lstrcmpiA(result, expected) == 0 ||
+ broken(lstrcmpiA(result, bad) == 0),
+ "%s expected '%s', got '%s'\n", key,
expected, result);
+}
+#define okChildString(key, expected) okChildString_(__FILE__, __LINE__, (key),
(expected), (expected))
+#define okChildStringBroken(key, expected, broken) okChildString_(__FILE__, __LINE__,
(key), (expected), (broken))
+
+static int StrCmpPath(const char* s1, const char* s2)
+{
+ if (!s1 && !s2) return 0;
+ if (!s2) return 1;
+ if (!s1) return -1;
+ while (*s1)
+ {
+ if (!*s2)
+ {
+ if (*s1=='.')
+ s1++;
+ return (*s1-*s2);
+ }
+ if ((*s1=='/' || *s1=='\\') && (*s2=='/' ||
*s2=='\\'))
+ {
+ while (*s1=='/' || *s1=='\\')
+ s1++;
+ while (*s2=='/' || *s2=='\\')
+ s2++;
+ }
+ else if (toupper(*s1)==toupper(*s2))
+ {
+ s1++;
+ s2++;
+ }
+ else
+ {
+ return (*s1-*s2);
+ }
+ }
+ if (*s2=='.')
+ s2++;
+ if (*s2)
+ return -1;
+ return 0;
+}
+
+static void okChildPath_(const char* file, int line, const char* key, const char*
expected)
+{
+ char* result;
+ int equal, shortequal;
+ result=getChildString("Child", key);
+ if (!result)
+ {
+ okShell_(file,line)(FALSE, "%s expected '%s', but key not found or
empty\n", key, expected);
+ return;
+ }
+ shortequal = FALSE;
+ equal = (StrCmpPath(result, expected) == 0);
+ if (!equal)
+ {
+ char altpath[MAX_PATH];
+ DWORD rc = GetLongPathNameA(expected, altpath, sizeof(altpath));
+ if (0 < rc && rc < sizeof(altpath))
+ equal = (StrCmpPath(result, altpath) == 0);
+ if (!equal)
+ {
+ rc = GetShortPathNameA(expected, altpath, sizeof(altpath));
+ if (0 < rc && rc < sizeof(altpath))
+ shortequal = (StrCmpPath(result, altpath) == 0);
+ }
+ }
+ okShell_(file,line)(equal || broken(shortequal) /* XP SP1 */,
+ "%s expected '%s', got '%s'\n", key,
expected, result);
+}
+#define okChildPath(key, expected) okChildPath_(__FILE__, __LINE__, (key), (expected))
+
+static void okChildInt_(const char* file, int line, const char* key, int expected)
+{
+ INT result;
+ result=GetPrivateProfileIntA("Child", key, expected, child_file);
+ okShell_(file,line)(result == expected,
+ "%s expected %d, but got %d\n", key, expected,
result);
+}
+#define okChildInt(key, expected) okChildInt_(__FILE__, __LINE__, (key), (expected))
+
+static void okChildIntBroken_(const char* file, int line, const char* key, int expected)
+{
+ INT result;
+ result=GetPrivateProfileIntA("Child", key, expected, child_file);
+ okShell_(file,line)(result == expected || broken(result != expected),
+ "%s expected %d, but got %d\n", key, expected,
result);
+}
+#define okChildIntBroken(key, expected) okChildIntBroken_(__FILE__, __LINE__, (key),
(expected))
+
+
+/***
+ *
* ShellExecute wrappers
*
***/
-static void dump_child(void);
-
-static HANDLE hEvent;
-static void init_event(const char* child_file)
-{
- char* event_name;
- event_name=strrchr(child_file, '\\')+1;
- hEvent=CreateEventA(NULL, FALSE, FALSE, event_name);
-}
static void strcat_param(char* str, const char* name, const char* param)
{
@@ -93,23 +494,24 @@
static int _todo_wait = 0;
#define todo_wait for (_todo_wait = 1; _todo_wait; _todo_wait = 0)
-static char shell_call[2048]="";
static int bad_shellexecute = 0;
-static INT_PTR shell_execute(LPCSTR verb, LPCSTR file, LPCSTR parameters, LPCSTR
directory)
+
+static INT_PTR shell_execute_(const char* file, int line, LPCSTR verb, LPCSTR filename,
LPCSTR parameters, LPCSTR directory)
{
INT_PTR rc, rcEmpty = 0;
if(!verb)
- rcEmpty = shell_execute("", file, parameters, directory);
+ rcEmpty = shell_execute_(file, line, "", filename, parameters,
directory);
strcpy(shell_call, "ShellExecute(");
strcat_param(shell_call, "verb", verb);
- strcat_param(shell_call, "file", file);
+ strcat_param(shell_call, "file", filename);
strcat_param(shell_call, "params", parameters);
strcat_param(shell_call, "dir", directory);
strcat(shell_call, ")");
+ strcat(shell_call, assoc_desc);
if (winetest_debug > 1)
- trace("%s\n", shell_call);
+ trace_(file, line)("Called %s\n", shell_call);
DeleteFileA(child_file);
SetLastError(0xcafebabe);
@@ -118,7 +520,7 @@
* association it displays the 'Open With' dialog and I could not find
* a flag to prevent this.
*/
- rc=(INT_PTR)ShellExecuteA(NULL, verb, file, parameters, directory, SW_HIDE);
+ rc=(INT_PTR)ShellExecuteA(NULL, verb, filename, parameters, directory, SW_HIDE);
if (rc > 32)
{
@@ -137,58 +539,70 @@
rc = SE_ERR_NOASSOC;
}
}
- if (!_todo_wait)
- ok(wait_rc==WAIT_OBJECT_0 || rc <= 32, "%s WaitForSingleObject
returned %d\n", shell_call, wait_rc);
- else todo_wine
- ok(wait_rc==WAIT_OBJECT_0 || rc <= 32, "%s WaitForSingleObject
returned %d\n", shell_call, wait_rc);
+ todo_wine_if(_todo_wait)
+ okShell_(file, line)(wait_rc==WAIT_OBJECT_0 || rc <= 32,
+ "WaitForSingleObject returned %d\n",
wait_rc);
}
/* The child process may have changed the result file, so let profile
* functions know about it
*/
WritePrivateProfileStringA(NULL, NULL, NULL, child_file);
- if (rc > 32)
- dump_child();
+ if (GetFileAttributesA(child_file) != INVALID_FILE_ATTRIBUTES)
+ {
+ int c;
+ dump_child_(file, line);
+ c = GetPrivateProfileIntA("Child", "Failures", -1,
child_file);
+ if (c > 0)
+ winetest_add_failures(c);
+ okChildInt_(file, line, "ShlexecVarLE", 0);
+ okChildString_(file, line, "ShlexecVar", "Present",
"Present");
+ }
if(!verb)
{
if (rc != rcEmpty && rcEmpty == SE_ERR_NOASSOC) /* NT4 */
bad_shellexecute = 1;
- ok(rc == rcEmpty || broken(rc != rcEmpty && rcEmpty == SE_ERR_NOASSOC) /*
NT4 */,
- "%s Got different return value with empty string: %lu %lu\n",
shell_call, rc, rcEmpty);
+ okShell_(file, line)(rc == rcEmpty ||
+ broken(rc != rcEmpty && rcEmpty == SE_ERR_NOASSOC)
/* NT4 */,
+ "Got different return value with empty string: %lu
%lu\n", rc, rcEmpty);
}
return rc;
}
-
-static INT_PTR shell_execute_ex(DWORD mask, LPCSTR verb, LPCSTR file,
- LPCSTR parameters, LPCSTR directory,
- LPCSTR class)
-{
+#define shell_execute(verb, filename, parameters, directory) \
+ shell_execute_(__FILE__, __LINE__, verb, filename, parameters, directory)
+
+static INT_PTR shell_execute_ex_(const char* file, int line,
+ DWORD mask, LPCSTR verb, LPCSTR filename,
+ LPCSTR parameters, LPCSTR directory,
+ LPCSTR class)
+{
+ char smask[11];
SHELLEXECUTEINFOA sei;
BOOL success;
INT_PTR rc;
+ /* Add some flags so we can wait for the child process */
+ mask |= SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE;
+
strcpy(shell_call, "ShellExecuteEx(");
- if (mask)
- {
- char smask[11];
- sprintf(smask, "0x%x", mask);
- strcat_param(shell_call, "mask", smask);
- }
+ sprintf(smask, "0x%x", mask);
+ strcat_param(shell_call, "mask", smask);
strcat_param(shell_call, "verb", verb);
- strcat_param(shell_call, "file", file);
+ strcat_param(shell_call, "file", filename);
strcat_param(shell_call, "params", parameters);
strcat_param(shell_call, "dir", directory);
strcat_param(shell_call, "class", class);
strcat(shell_call, ")");
+ strcat(shell_call, assoc_desc);
if (winetest_debug > 1)
- trace("%s\n", shell_call);
+ trace_(file, line)("Called %s\n", shell_call);
sei.cbSize=sizeof(sei);
- sei.fMask=SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE | mask;
+ sei.fMask=mask;
sei.hwnd=NULL;
sei.lpVerb=verb;
- sei.lpFile=file;
+ sei.lpFile=filename;
sei.lpParameters=parameters;
sei.lpDirectory=directory;
sei.nShow=SW_SHOWNORMAL;
@@ -198,39 +612,70 @@
sei.hkeyClass=NULL;
sei.dwHotKey=0;
U(sei).hIcon=NULL;
- sei.hProcess=NULL; /* Out */
+ sei.hProcess=(HANDLE)0xdeadbeef; /* Out */
DeleteFileA(child_file);
SetLastError(0xcafebabe);
success=ShellExecuteExA(&sei);
rc=(INT_PTR)sei.hInstApp;
- ok((success && rc > 32) || (!success && rc <= 32),
- "%s rc=%d and hInstApp=%ld is not allowed\n", shell_call, success, rc);
+ okShell_(file, line)((success && rc > 32) || (!success && rc <=
32),
+ "rc=%d and hInstApp=%ld is not allowed\n",
+ success, rc);
if (rc > 32)
{
- int wait_rc;
+ DWORD wait_rc, rc;
if (sei.hProcess!=NULL)
{
wait_rc=WaitForSingleObject(sei.hProcess, 5000);
- ok(wait_rc==WAIT_OBJECT_0, "WaitForSingleObject(hProcess) returned
%d\n", wait_rc);
+ okShell_(file, line)(wait_rc==WAIT_OBJECT_0,
+ "WaitForSingleObject(hProcess) returned
%d\n",
+ wait_rc);
+ wait_rc = GetExitCodeProcess(sei.hProcess, &rc);
+ okShell_(file, line)(wait_rc, "GetExitCodeProcess() failed
le=%u\n", GetLastError());
+ todo_wine_if(_todo_wait)
+ okShell_(file, line)(rc == 0, "child returned %u\n", rc);
+ CloseHandle(sei.hProcess);
}
wait_rc=WaitForSingleObject(hEvent, 5000);
- if (!_todo_wait)
- ok(wait_rc==WAIT_OBJECT_0, "WaitForSingleObject returned %d\n",
wait_rc);
- else todo_wine
- ok(wait_rc==WAIT_OBJECT_0, "WaitForSingleObject returned %d\n",
wait_rc);
- }
+ todo_wine_if(_todo_wait)
+ okShell_(file, line)(wait_rc==WAIT_OBJECT_0,
+ "WaitForSingleObject returned %d\n",
wait_rc);
+ }
+ else
+ okShell_(file, line)(sei.hProcess==NULL,
+ "returned a process handle %p\n", sei.hProcess);
+
/* The child process may have changed the result file, so let profile
* functions know about it
*/
WritePrivateProfileStringA(NULL, NULL, NULL, child_file);
- if (rc > 32)
- dump_child();
+ if (GetFileAttributesA(child_file) != INVALID_FILE_ATTRIBUTES)
+ {
+ int c;
+ dump_child_(file, line);
+ c = GetPrivateProfileIntA("Child", "Failures", -1,
child_file);
+ if (c > 0)
+ winetest_add_failures(c);
+ /* When NOZONECHECKS is specified the environment variables are not
+ * inherited if the process does not have elevated privileges.
+ */
+ if ((mask & SEE_MASK_NOZONECHECKS) && skip_shlexec_tests)
+ {
+ okChildInt_(file, line, "ShlexecVarLE", 203);
+ okChildString_(file, line, "ShlexecVar", "",
"");
+ }
+ else
+ {
+ okChildInt_(file, line, "ShlexecVarLE", 0);
+ okChildString_(file, line, "ShlexecVar", "Present",
"Present");
+ }
+ }
return rc;
}
-
+#define shell_execute_ex(mask, verb, filename, parameters, directory, class) \
+ shell_execute_ex_(__FILE__, __LINE__, mask, verb, filename, parameters, directory,
class)
/***
@@ -248,6 +693,8 @@
sprintf(class, "shlexec%s", extension);
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=%d)\n", class, rc);
if (rc != ERROR_SUCCESS)
return FALSE;
@@ -355,6 +802,17 @@
char* cmd;
LONG rc;
+ strcpy(assoc_desc, " Assoc ");
+ strcat_param(assoc_desc, "ext", extension);
+ strcat_param(assoc_desc, "verb", verb);
+ sprintf(shell, "%d", rawcmd);
+ strcat_param(assoc_desc, "rawcmd", shell);
+ strcat_param(assoc_desc, "cmdtail", cmdtail);
+ strcat_param(assoc_desc, "ddeexec", ddeexec);
+ strcat_param(assoc_desc, "app", application);
+ strcat_param(assoc_desc, "topic", topic);
+ strcat_param(assoc_desc, "ifexec", ifexec);
+
sprintf(shell, "shlexec%s\\shell", extension);
rc=RegOpenKeyExA(HKEY_CLASSES_ROOT, shell, 0,
KEY_CREATE_SUB_KEY, &hkey_shell);
@@ -431,337 +889,18 @@
CloseHandle(hkey_cmd);
}
+/* Creates a class' non-DDE test verb.
+ * This function is meant to be used to create long term test verbs and thus
+ * does not trace them.
+ */
static void create_test_verb(const char* extension, const char* verb,
int rawcmd, const char* cmdtail)
{
create_test_verb_dde(extension, verb, rawcmd, cmdtail, NULL, NULL,
NULL, NULL);
-}
-
-/***
- *
- * Functions to check that the child process was started just right
- * (borrowed from dlls/kernel32/tests/process.c)
- *
- ***/
-
-static const char* encodeA(const char* str)
-{
- static char encoded[2*1024+1];
- char* ptr;
- size_t len,i;
-
- if (!str) return "";
- len = strlen(str) + 1;
- if (len >= sizeof(encoded)/2)
- {
- fprintf(stderr, "string is too long!\n");
- assert(0);
- }
- ptr = encoded;
- for (i = 0; i < len; i++)
- sprintf(&ptr[i * 2], "%02x", (unsigned char)str[i]);
- ptr[2 * len] = '\0';
- return ptr;
-}
-
-static unsigned decode_char(char c)
-{
- if (c >= '0' && c <= '9') return c - '0';
- if (c >= 'a' && c <= 'f') return c - 'a' + 10;
- assert(c >= 'A' && c <= 'F');
- return c - 'A' + 10;
-}
-
-static char* decodeA(const char* str)
-{
- static char decoded[1024];
- char* ptr;
- size_t len,i;
-
- len = strlen(str) / 2;
- if (!len--) return NULL;
- if (len >= sizeof(decoded))
- {
- fprintf(stderr, "string is too long!\n");
- assert(0);
- }
- ptr = decoded;
- for (i = 0; i < len; i++)
- ptr[i] = (decode_char(str[2 * i]) << 4) | decode_char(str[2 * i + 1]);
- ptr[len] = '\0';
- return ptr;
-}
-
-static void childPrintf(HANDLE h, const char* fmt, ...)
-{
- va_list valist;
- char buffer[1024];
- DWORD w;
-
- va_start(valist, fmt);
- vsprintf(buffer, fmt, valist);
- va_end(valist);
- WriteFile(h, buffer, strlen(buffer), &w, NULL);
-}
-
-static DWORD ddeInst;
-static HSZ hszTopic;
-static char ddeExec[MAX_PATH], ddeApplication[MAX_PATH];
-static BOOL post_quit_on_execute;
-
-static HDDEDATA CALLBACK ddeCb(UINT uType, UINT uFmt, HCONV hConv,
- HSZ hsz1, HSZ hsz2, HDDEDATA hData,
- ULONG_PTR dwData1, ULONG_PTR dwData2)
-{
- DWORD size = 0;
-
- if (winetest_debug > 2)
- trace("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
- uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
-
- switch (uType)
- {
- case XTYP_CONNECT:
- if (!DdeCmpStringHandles(hsz1, hszTopic))
- {
- size = DdeQueryStringA(ddeInst, hsz2, ddeApplication, MAX_PATH,
CP_WINANSI);
- ok(size < MAX_PATH, "got size %d\n", size);
- assert(size < MAX_PATH);
- return (HDDEDATA)TRUE;
- }
- return (HDDEDATA)FALSE;
-
- case XTYP_EXECUTE:
- size = DdeGetData(hData, (LPBYTE)ddeExec, MAX_PATH, 0);
- ok(size < MAX_PATH, "got size %d\n", size);
- assert(size < MAX_PATH);
- DdeFreeDataHandle(hData);
- if (post_quit_on_execute)
- PostQuitMessage(0);
- return (HDDEDATA)DDE_FACK;
-
- default:
- return NULL;
- }
-}
-
-/*
- * This is just to make sure the child won't run forever stuck in a GetMessage()
- * loop when DDE fails for some reason.
- */
-static void CALLBACK childTimeout(HWND wnd, UINT msg, UINT_PTR timer, DWORD time)
-{
- trace("childTimeout called\n");
-
- PostQuitMessage(0);
-}
-
-static void doChild(int argc, char** argv)
-{
- char *filename, longpath[MAX_PATH] = "";
- HANDLE hFile, map;
- int i;
- int rc;
- HSZ hszApplication;
- UINT_PTR timer;
- HANDLE dde_ready;
- MSG msg;
- char *shared_block;
-
- filename=argv[2];
- hFile=CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
- if (hFile == INVALID_HANDLE_VALUE)
- return;
-
- /* Arguments */
- childPrintf(hFile, "[Arguments]\r\n");
- if (winetest_debug > 2)
- {
- trace("cmdlineA='%s'\n", GetCommandLineA());
- trace("argcA=%d\n", argc);
- }
- childPrintf(hFile, "cmdlineA=%s\r\n", encodeA(GetCommandLineA()));
- childPrintf(hFile, "argcA=%d\r\n", argc);
- for (i = 0; i < argc; i++)
- {
- if (winetest_debug > 2)
- trace("argvA%d='%s'\n", i, argv[i]);
- childPrintf(hFile, "argvA%d=%s\r\n", i, encodeA(argv[i]));
- }
- GetModuleFileNameA(GetModuleHandleA(NULL), longpath, MAX_PATH);
- childPrintf(hFile, "longPath=%s\r\n", encodeA(longpath));
-
- map = OpenFileMappingA(FILE_MAP_READ, FALSE, "winetest_shlexec_dde_map");
- if (map != NULL)
- {
- shared_block = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 4096);
- CloseHandle(map);
- if (shared_block[0] != '\0' || shared_block[1] != '\0')
- {
- post_quit_on_execute = TRUE;
- ddeInst = 0;
- rc = DdeInitializeA(&ddeInst, ddeCb, CBF_SKIP_ALLNOTIFICATIONS |
CBF_FAIL_ADVISES |
- CBF_FAIL_POKES | CBF_FAIL_REQUESTS, 0);
- ok(rc == DMLERR_NO_ERROR, "got %d\n", rc);
- hszApplication = DdeCreateStringHandleA(ddeInst, shared_block, CP_WINANSI);
- hszTopic = DdeCreateStringHandleA(ddeInst, shared_block +
strlen(shared_block) + 1, CP_WINANSI);
- assert(hszApplication && hszTopic);
- assert(DdeNameService(ddeInst, hszApplication, 0, DNS_REGISTER |
DNS_FILTEROFF));
-
- timer = SetTimer(NULL, 0, 2500, childTimeout);
-
- dde_ready = OpenEventA(EVENT_MODIFY_STATE, FALSE,
"winetest_shlexec_dde_ready");
- SetEvent(dde_ready);
- CloseHandle(dde_ready);
-
- while (GetMessageA(&msg, NULL, 0, 0))
- DispatchMessageA(&msg);
-
- Sleep(500);
- KillTimer(NULL, timer);
- assert(DdeNameService(ddeInst, hszApplication, 0, DNS_UNREGISTER));
- assert(DdeFreeStringHandle(ddeInst, hszTopic));
- assert(DdeFreeStringHandle(ddeInst, hszApplication));
- assert(DdeUninitialize(ddeInst));
- }
- else
- {
- dde_ready = OpenEventA(EVENT_MODIFY_STATE, FALSE,
"winetest_shlexec_dde_ready");
- SetEvent(dde_ready);
- CloseHandle(dde_ready);
- }
-
- UnmapViewOfFile(shared_block);
-
- childPrintf(hFile, "ddeExec=%s\r\n", encodeA(ddeExec));
- }
-
- CloseHandle(hFile);
-
- init_event(filename);
- SetEvent(hEvent);
- CloseHandle(hEvent);
-}
-
-static char* getChildString(const char* sect, const char* key)
-{
- char buf[1024];
- char* ret;
-
- GetPrivateProfileStringA(sect, key, "-", buf, sizeof(buf), child_file);
- if (buf[0] == '\0' || (buf[0] == '-' && buf[1] ==
'\0')) return NULL;
- assert(!(strlen(buf) & 1));
- ret = decodeA(buf);
- return ret;
-}
-
-static void dump_child(void)
-{
- if (winetest_debug > 1)
- {
- char key[18];
- char* str;
- int i, c;
-
- str=getChildString("Arguments", "cmdlineA");
- trace("cmdlineA='%s'\n", str);
- c=GetPrivateProfileIntA("Arguments", "argcA", -1,
child_file);
- trace("argcA=%d\n",c);
- for (i=0;i<c;i++)
- {
- sprintf(key, "argvA%d", i);
- str=getChildString("Arguments", key);
- trace("%s='%s'\n", key, str);
- }
- }
-}
-
-static int StrCmpPath(const char* s1, const char* s2)
-{
- if (!s1 && !s2) return 0;
- if (!s2) return 1;
- if (!s1) return -1;
- while (*s1)
- {
- if (!*s2)
- {
- if (*s1=='.')
- s1++;
- return (*s1-*s2);
- }
- if ((*s1=='/' || *s1=='\\') && (*s2=='/' ||
*s2=='\\'))
- {
- while (*s1=='/' || *s1=='\\')
- s1++;
- while (*s2=='/' || *s2=='\\')
- s2++;
- }
- else if (toupper(*s1)==toupper(*s2))
- {
- s1++;
- s2++;
- }
- else
- {
- return (*s1-*s2);
- }
- }
- if (*s2=='.')
- s2++;
- if (*s2)
- return -1;
- return 0;
-}
-
-static void _okChildString(const char* file, int line, const char* key, const char*
expected, const char* bad)
-{
- char* result;
- result=getChildString("Arguments", key);
- if (!result)
- {
- ok_(file, line)(FALSE, "%s expected '%s', but key not found or
empty\n", key, expected);
- return;
- }
- ok_(file, line)(lstrcmpiA(result, expected) == 0 ||
- broken(lstrcmpiA(result, bad) == 0),
- "%s expected '%s', got '%s'\n", key,
expected, result);
-}
-
-static void _okChildPath(const char* file, int line, const char* key, const char*
expected)
-{
- char* result;
- result=getChildString("Arguments", key);
- if (!result)
- {
- ok_(file, line)(FALSE, "%s expected '%s', but key not found or
empty\n", key, expected);
- return;
- }
- ok_(file, line)(StrCmpPath(result, expected) == 0,
- "%s expected '%s', got '%s'\n", key,
expected, result);
-}
-
-static void _okChildInt(const char* file, int line, const char* key, int expected)
-{
- INT result;
- result=GetPrivateProfileIntA("Arguments", key, expected, child_file);
- ok_(file, line)(result == expected,
- "%s expected %d, but got %d\n", key, expected, result);
-}
-
-static void _okChildIntBroken(const char* file, int line, const char* key, int expected)
-{
- INT result;
- result=GetPrivateProfileIntA("Arguments", key, expected, child_file);
- ok_(file, line)(result == expected || broken(result != expected),
- "%s expected %d, but got %d\n", key, expected, result);
-}
-
-#define okChildString(key, expected) _okChildString(__FILE__, __LINE__, (key),
(expected), (expected))
-#define okChildStringBroken(key, expected, broken) _okChildString(__FILE__, __LINE__,
(key), (expected), (broken))
-#define okChildPath(key, expected) _okChildPath(__FILE__, __LINE__, (key), (expected))
-#define okChildInt(key, expected) _okChildInt(__FILE__, __LINE__, (key), (expected))
-#define okChildIntBroken(key, expected) _okChildIntBroken(__FILE__, __LINE__, (key),
(expected))
+ reset_association_description();
+}
+
/***
*
@@ -836,6 +975,7 @@
return tmplen;
}
+
/***
*
@@ -901,6 +1041,8 @@
{"QuotedLowerL", "%s\\test file.shlexec", 0x0, 33},
{"QuotedUpperL", "%s\\test file.shlexec", 0x0, 33},
+ {"notaverb", "%s\\test file.shlexec", 0x10,
SE_ERR_NOASSOC},
+
/* Test file masked due to space */
{NULL, "%s\\masked file.shlexec", 0x0, 33},
/* Test if quoting prevents the masking */
@@ -935,48 +1077,48 @@
/* existing "drawback_file.noassoc" prevents finding
"drawback_file.noassoc foo.shlexec" on wine */
sprintf(fileA, "%s\\drawback_file.noassoc foo.shlexec", tmpdir);
rc=shell_execute(NULL, fileA, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
+ okShell(rc > 32, "failed: rc=%lu\n", rc);
/* if quoted, existing "drawback_file.noassoc" not prevents finding
"drawback_file.noassoc foo.shlexec" on wine */
sprintf(fileA, "\"%s\\drawback_file.noassoc foo.shlexec\"",
tmpdir);
rc=shell_execute(NULL, fileA, NULL, NULL);
- ok(rc > 32 || broken(rc == SE_ERR_FNF) /* Win95/NT4 */,
- "%s failed: rc=%lu\n", shell_call, rc);
+ okShell(rc > 32 || broken(rc == SE_ERR_FNF) /* Win95/NT4 */,
+ "failed: rc=%lu\n", rc);
/* error should be SE_ERR_FNF, not SE_ERR_NOASSOC */
sprintf(fileA, "\"%s\\drawback_file.noassoc\" foo.shlexec",
tmpdir);
rc=shell_execute(NULL, fileA, NULL, NULL);
- ok(rc == SE_ERR_FNF, "%s succeeded: rc=%lu\n", shell_call, rc);
+ okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
/* ""command"" not works on wine (and real win9x and w2k) */
sprintf(fileA, "\"\"%s\\simple.shlexec\"\"", tmpdir);
rc=shell_execute(NULL, fileA, NULL, NULL);
- todo_wine ok(rc > 32 || broken(rc == SE_ERR_FNF) /* Win9x/2000 */,
- "%s failed: rc=%lu\n", shell_call, rc);
+ todo_wine okShell(rc > 32 || broken(rc == SE_ERR_FNF) /* Win9x/2000 */,
+ "failed: rc=%lu\n", rc);
/* nonexisting "drawback_nonexist.noassoc" not prevents finding
"drawback_nonexist.noassoc foo.shlexec" on wine */
sprintf(fileA, "%s\\drawback_nonexist.noassoc foo.shlexec", tmpdir);
rc=shell_execute(NULL, fileA, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
+ okShell(rc > 32, "failed: rc=%lu\n", rc);
/* is SEE_MASK_DOENVSUBST default flag? Should only be when XP emulates 9x (XP bug or
real 95 or ME behavior ?) */
rc=shell_execute(NULL, "%TMPDIR%\\simple.shlexec", NULL, NULL);
- todo_wine ok(rc == SE_ERR_FNF, "%s succeeded: rc=%lu\n", shell_call, rc);
+ todo_wine okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
/* quoted */
rc=shell_execute(NULL, "\"%TMPDIR%\\simple.shlexec\"", NULL,
NULL);
- todo_wine ok(rc == SE_ERR_FNF, "%s succeeded: rc=%lu\n", shell_call, rc);
+ todo_wine okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
/* test SEE_MASK_DOENVSUBST works */
rc=shell_execute_ex(SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI,
NULL, "%TMPDIR%\\simple.shlexec", NULL, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
+ okShell(rc > 32, "failed: rc=%lu\n", rc);
/* quoted lpFile does not work on real win95 and nt4 */
rc=shell_execute_ex(SEE_MASK_DOENVSUBST | SEE_MASK_FLAG_NO_UI,
NULL, "\"%TMPDIR%\\simple.shlexec\"", NULL,
NULL, NULL);
- ok(rc > 32 || broken(rc == SE_ERR_FNF) /* Win95/NT4 */,
- "%s failed: rc=%lu\n", shell_call, rc);
+ okShell(rc > 32 || broken(rc == SE_ERR_FNF) /* Win95/NT4 */,
+ "failed: rc=%lu\n", rc);
}
typedef struct
@@ -1169,24 +1311,18 @@
count = 0;
while (test->args[count])
count++;
- if ((test->todo & 0x1) == 0)
+ todo_wine_if(test->todo & 0x1)
ok(cl2a_count == count, "%s: expected %d arguments, but got %d\n",
test->cmd, count, cl2a_count);
- else todo_wine
- ok(cl2a_count == count, "%s: expected %d arguments, but got %d\n",
test->cmd, count, cl2a_count);
for (i = 0; i < cl2a_count; i++)
{
if (i < count)
{
MultiByteToWideChar(CP_ACP, 0, test->args[i], -1, argW,
sizeof(argW)/sizeof(*argW));
- if ((test->todo & (1 << (i+4))) == 0)
+ todo_wine_if(test->todo & (1 << (i+4)))
ok(!lstrcmpW(*argsW, argW), "%s: arg[%d] expected %s but got
%s\n", test->cmd, i, wine_dbgstr_w(argW), wine_dbgstr_w(*argsW));
- else todo_wine
- ok(!lstrcmpW(*argsW, argW), "%s: arg[%d] expected %s but got
%s\n", test->cmd, i, wine_dbgstr_w(argW), wine_dbgstr_w(*argsW));
- }
- else if ((test->todo & 0x1) == 0)
- ok(0, "%s: got extra arg[%d]=%s\n", test->cmd, i,
wine_dbgstr_w(*argsW));
- else todo_wine
+ }
+ else todo_wine_if(test->todo & 0x1)
ok(0, "%s: got extra arg[%d]=%s\n", test->cmd, i,
wine_dbgstr_w(*argsW));
argsW++;
}
@@ -1416,6 +1552,18 @@
const char* cmd;
unsigned i, count;
+ /* Test with a long parameter */
+ for (rc = 0; rc < MAX_PATH; rc++)
+ fileA[rc] = 'a' + rc % 26;
+ fileA[MAX_PATH-1] = '\0';
+ sprintf(params, "shlexec \"%s\" %s", child_file, fileA);
+
+ /* We need NOZONECHECKS on Win2003 to block a dialog */
+ rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, argv0, params, NULL, NULL);
+ okShell(rc > 32, "failed: rc=%lu\n", rc);
+ okChildInt("argcA", 4);
+ okChildPath("argvA3", fileA);
+
if (skip_shlexec_tests)
{
skip("No argify tests due to lack of .shlexec association\n");
@@ -1439,40 +1587,33 @@
/* trace("***** verb='%s' params='%s'\n",
test->verb, test->params); */
rc = shell_execute_ex(SEE_MASK_DOENVSUBST, test->verb, fileA, test->params,
NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
+ okShell(rc > 32, "failed: rc=%lu\n", rc);
count = 0;
while (test->cmd.args[count])
count++;
- if ((test->todo & 0x1) == 0)
- /* +4 for the shlexec arguments, -1 because of the added ""
- * argument for the CommandLineToArgvW() tests.
- */
+ /* +4 for the shlexec arguments, -1 because of the added ""
+ * argument for the CommandLineToArgvW() tests.
+ */
+ todo_wine_if(test->todo & 0x1)
okChildInt("argcA", 4 + count - 1);
- else todo_wine
- okChildInt("argcA", 4 + count - 1);
-
- cmd = getChildString("Arguments", "cmdlineA");
+
+ cmd = getChildString("Child", "cmdlineA");
/* Our commands are such that the verb immediately precedes the
* part we are interested in.
*/
if (cmd) cmd = strstr(cmd, test->verb);
if (cmd) cmd += strlen(test->verb);
if (!cmd) cmd = "(null)";
- if ((test->todo & 0x2) == 0)
- ok(!strcmp(cmd, test->cmd.cmd) || broken(!strcmp(cmd, bad->cmd)),
- "%s: the cmdline is '%s' instead of '%s'\n",
shell_call, cmd, test->cmd.cmd);
- else todo_wine
- ok(!strcmp(cmd, test->cmd.cmd) || broken(!strcmp(cmd, bad->cmd)),
- "%s: the cmdline is '%s' instead of '%s'\n",
shell_call, cmd, test->cmd.cmd);
+ todo_wine_if(test->todo & 0x2)
+ okShell(!strcmp(cmd, test->cmd.cmd) || broken(!strcmp(cmd, bad->cmd)),
+ "the cmdline is '%s' instead of '%s'\n",
cmd, test->cmd.cmd);
for (i = 0; i < count - 1; i++)
{
char argname[18];
sprintf(argname, "argvA%d", 4 + i);
- if ((test->todo & (1 << (i+4))) == 0)
- okChildStringBroken(argname, test->cmd.args[i+1], bad->args[i+1]);
- else todo_wine
+ todo_wine_if(test->todo & (1 << (i+4)))
okChildStringBroken(argname, test->cmd.args[i+1], bad->args[i+1]);
}
@@ -1480,18 +1621,6 @@
has_cl2a = test_one_cmdline(&(test->cmd));
test++;
}
-
- /* Test with a long parameter */
- for (rc = 0; rc < MAX_PATH; rc++)
- fileA[rc] = 'a' + rc % 26;
- fileA[MAX_PATH-1] = '\0';
- sprintf(params, "shlexec \"%s\" %s", child_file, fileA);
-
- /* We need NOZONECHECKS on Win2003 to block a dialog */
- rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, argv0, params, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
- okChildInt("argcA", 4);
- okChildString("argvA3", fileA);
}
static void test_filename(void)
@@ -1544,38 +1673,19 @@
}
if (rc > 32)
rc=33;
- ok(rc==test->rc ||
- broken(quotedfile && rc == SE_ERR_FNF), /* NT4 */
- "%s failed: rc=%ld err=%u\n", shell_call,
- rc, GetLastError());
+ okShell(rc==test->rc ||
+ broken(quotedfile && rc == SE_ERR_FNF), /* NT4 */
+ "failed: rc=%ld err=%u\n", rc, GetLastError());
if (rc == 33)
{
const char* verb;
- if ((test->todo & 0x2)==0)
- {
+ todo_wine_if(test->todo & 0x2)
okChildInt("argcA", 5);
- }
- else todo_wine
- {
- okChildInt("argcA", 5);
- }
verb=(test->verb ? test->verb : "Open");
- if ((test->todo & 0x4)==0)
- {
+ todo_wine_if(test->todo & 0x4)
okChildString("argvA3", verb);
- }
- else todo_wine
- {
- okChildString("argvA3", verb);
- }
- if ((test->todo & 0x8)==0)
- {
+ todo_wine_if(test->todo & 0x8)
okChildPath("argvA4", filename);
- }
- else todo_wine
- {
- okChildPath("argvA4", filename);
- }
}
test++;
}
@@ -1587,16 +1697,8 @@
rc=shell_execute(test->verb, filename, NULL, NULL);
if (rc > 32)
rc=33;
- if ((test->todo & 0x1)==0)
- {
- ok(rc==test->rc, "%s failed: rc=%ld err=%u\n", shell_call,
- rc, GetLastError());
- }
- else todo_wine
- {
- ok(rc==test->rc, "%s failed: rc=%ld err=%u\n", shell_call,
- rc, GetLastError());
- }
+ todo_wine_if(test->todo & 0x1)
+ okShell(rc==test->rc, "failed: rc=%ld err=%u\n", rc,
GetLastError());
if (rc==0)
{
int count;
@@ -1604,14 +1706,8 @@
char* str;
verb=(test->verb ? test->verb : "Open");
- if ((test->todo & 0x4)==0)
- {
+ todo_wine_if(test->todo & 0x4)
okChildString("argvA3", verb);
- }
- else todo_wine
- {
- okChildString("argvA3", verb);
- }
count=4;
str=filename;
@@ -1623,27 +1719,15 @@
if (space)
*space='\0';
sprintf(attrib, "argvA%d", count);
- if ((test->todo & 0x8)==0)
- {
+ todo_wine_if(test->todo & 0x8)
okChildPath(attrib, str);
- }
- else todo_wine
- {
- okChildPath(attrib, str);
- }
count++;
if (!space)
break;
str=space+1;
}
- if ((test->todo & 0x2)==0)
- {
+ todo_wine_if(test->todo & 0x2)
okChildInt("argcA", count);
- }
- else todo_wine
- {
- okChildInt("argcA", count);
- }
}
test++;
}
@@ -1658,8 +1742,7 @@
*/
sprintf(filename, "\"%s\\test file.shlexec\"", tmpdir);
rc=shell_execute(NULL, filename, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%ld err=%u\n", shell_call, rc,
- GetLastError());
+ okShell(rc > 32, "failed: rc=%ld err=%u\n", rc, GetLastError());
okChildInt("argcA", 5);
okChildString("argvA3", "Open");
sprintf(filename, "%s\\test file.shlexec", tmpdir);
@@ -1726,7 +1809,8 @@
return;
}
- rc = (INT_PTR)ShellExecuteA(NULL, NULL, "file:///nosuchfile.shlexec", NULL,
NULL, SW_SHOWNORMAL);
+ rc = shell_execute_ex(SEE_MASK_FLAG_NO_UI, NULL,
+ "file:///nosuchfile.shlexec", NULL, NULL, NULL);
if (rc > 32)
{
win_skip("shell32 is too old (likely < 4.72). Skipping the file URL
tests\n");
@@ -1769,37 +1853,23 @@
}
if (test->flags & URL_SUCCESS)
{
- if ((test->todo & 0x1) == 0)
- ok(rc > 32, "%s failed: bad rc=%lu\n", shell_call, rc);
- else todo_wine
- ok(rc > 32, "%s failed: bad rc=%lu\n", shell_call, rc);
+ todo_wine_if(test->todo & 0x1)
+ okShell(rc > 32, "failed: bad rc=%lu\n", rc);
}
else
{
- if ((test->todo & 0x1) == 0)
- ok(rc == SE_ERR_FNF || rc == SE_ERR_PNF ||
- broken(rc == SE_ERR_ACCESSDENIED) /* win2000 */,
- "%s failed: bad rc=%lu\n", shell_call, rc);
- else todo_wine
- ok(rc == SE_ERR_FNF || rc == SE_ERR_PNF ||
- broken(rc == SE_ERR_ACCESSDENIED) /* win2000 */,
- "%s failed: bad rc=%lu\n", shell_call, rc);
+ todo_wine_if(test->todo & 0x1)
+ okShell(rc == SE_ERR_FNF || rc == SE_ERR_PNF ||
+ broken(rc == SE_ERR_ACCESSDENIED) /* win2000 */,
+ "failed: bad rc=%lu\n", rc);
}
if (rc == 33)
{
- if ((test->todo & 0x2) == 0)
+ todo_wine_if(test->todo & 0x2)
okChildInt("argcA", 5);
- else todo_wine
- okChildInt("argcA", 5);
-
- if ((test->todo & 0x4) == 0)
+ todo_wine_if(test->todo & 0x4)
okChildString("argvA3", "Open");
- else todo_wine
- okChildString("argvA3", "Open");
-
- if ((test->todo & 0x8) == 0)
- okChildPath("argvA4", filename);
- else todo_wine
+ todo_wine_if(test->todo & 0x8)
okChildPath("argvA4", filename);
}
test++;
@@ -1922,30 +1992,17 @@
rc=(INT_PTR)FindExecutableA(filename, NULL, command);
if (rc > 32)
rc=33;
- if ((test->todo & 0x10)==0)
- {
+ todo_wine_if(test->todo & 0x10)
ok(rc==test->rc, "FindExecutable(%s) failed: rc=%ld\n",
filename, rc);
- }
- else todo_wine
- {
- ok(rc==test->rc, "FindExecutable(%s) failed: rc=%ld\n",
filename, rc);
- }
if (rc > 32)
{
BOOL equal;
equal=strcmp(command, argv0) == 0 ||
/* NT4 returns an extra 0x8 character! */
(strlen(command) == strlen(argv0)+1 && strncmp(command, argv0,
strlen(argv0)) == 0);
- if ((test->todo & 0x20)==0)
- {
+ todo_wine_if(test->todo & 0x20)
ok(equal, "FindExecutable(%s) returned command='%s' instead
of '%s'\n",
filename, command, argv0);
- }
- else todo_wine
- {
- ok(equal, "FindExecutable(%s) returned command='%s' instead
of '%s'\n",
- filename, command, argv0);
- }
}
test++;
}
@@ -1982,7 +2039,7 @@
/* Should open through our association */
sprintf(filename, "%s\\test_shortcut_shlexec.lnk", tmpdir);
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, NULL, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu err=%u\n", shell_call, rc,
GetLastError());
+ okShell(rc > 32, "failed: rc=%lu err=%u\n", rc, GetLastError());
okChildInt("argcA", 5);
okChildString("argvA3", "Open");
sprintf(params, "%s\\test file.shlexec", tmpdir);
@@ -1990,7 +2047,7 @@
okChildPath("argvA4", filename);
todo_wait rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_DOENVSUBST, NULL,
"%TMPDIR%\\test_shortcut_shlexec.lnk", NULL, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu err=%u\n", shell_call, rc,
GetLastError());
+ okShell(rc > 32, "failed: rc=%lu err=%u\n", rc, GetLastError());
okChildInt("argcA", 5);
todo_wine okChildString("argvA3", "Open");
sprintf(params, "%s\\test file.shlexec", tmpdir);
@@ -2001,15 +2058,19 @@
/* Should just run our executable */
sprintf(filename, "%s\\test_shortcut_exe.lnk", tmpdir);
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, NULL, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu err=%u\n", shell_call, rc,
GetLastError());
+ okShell(rc > 32, "failed: rc=%lu err=%u\n", rc, GetLastError());
okChildInt("argcA", 4);
okChildString("argvA3", "Lnk");
- /* Lnk's ContextMenuHandler has priority over an explicit class */
- rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, NULL, NULL,
"shlexec.shlexec");
- ok(rc > 32, "%s failed: rc=%lu err=%u\n", shell_call, rc,
GetLastError());
- okChildInt("argcA", 4);
- okChildString("argvA3", "Lnk");
+ if (!skip_shlexec_tests)
+ {
+ /* An explicit class overrides lnk's ContextMenuHandler */
+ rc=shell_execute_ex(SEE_MASK_CLASSNAME | SEE_MASK_NOZONECHECKS, NULL, filename,
NULL, NULL, "shlexec.shlexec");
+ okShell(rc > 32, "failed: rc=%lu err=%u\n", rc, GetLastError());
+ okChildInt("argcA", 5);
+ okChildString("argvA3", "Open");
+ okChildPath("argvA4", filename);
+ }
if (dllver.dwMajorVersion>=6)
{
@@ -2026,8 +2087,7 @@
c++;
}
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, NULL, NULL, NULL);
- ok(rc > 32, "%s failed: rc=%lu err=%u\n", shell_call, rc,
- GetLastError());
+ okShell(rc > 32, "failed: rc=%lu err=%u\n", rc, GetLastError());
okChildInt("argcA", 4);
okChildString("argvA3", "Lnk");
}
@@ -2043,43 +2103,16 @@
NULL, NULL);
if (rc > 32)
rc=33;
- if ((test->todo & 0x1)==0)
- {
- ok(rc==test->rc, "%s failed: rc=%lu err=%u\n", shell_call,
- rc, GetLastError());
- }
- else todo_wine
- {
- ok(rc==test->rc, "%s failed: rc=%lu err=%u\n", shell_call,
- rc, GetLastError());
- }
+ todo_wine_if(test->todo & 0x1)
+ okShell(rc==test->rc, "failed: rc=%lu err=%u\n", rc,
GetLastError());
if (rc==0)
{
- if ((test->todo & 0x2)==0)
- {
+ todo_wine_if(test->todo & 0x2)
okChildInt("argcA", 5);
- }
- else
- {
- okChildInt("argcA", 5);
- }
- if ((test->todo & 0x4)==0)
- {
+ todo_wine_if(test->todo & 0x4)
okChildString("argvA3", "Lnk");
- }
- else todo_wine
- {
- okChildString("argvA3", "Lnk");
- }
sprintf(params, test->basename, tmpdir);
- if ((test->todo & 0x8)==0)
- {
- okChildPath("argvA4", params);
- }
- else
- {
- okChildPath("argvA4", params);
- }
+ okChildPath("argvA4", params);
}
test++;
}
@@ -2097,7 +2130,7 @@
/* We need NOZONECHECKS on Win2003 to block a dialog */
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, argv0, params,
NULL, NULL);
- ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+ okShell(rc > 32, "returned %lu\n", rc);
okChildInt("argcA", 4);
okChildString("argvA3", "Exec");
@@ -2108,7 +2141,7 @@
{
rc=shell_execute(NULL, filename, params, NULL);
todo_wine {
- ok(rc==SE_ERR_NOASSOC, "%s succeeded: rc=%lu\n", shell_call,
rc);
+ okShell(rc==SE_ERR_NOASSOC, "returned %lu\n", rc);
}
}
}
@@ -2120,11 +2153,28 @@
/* test combining executable and parameters */
sprintf(filename, "%s shlexec \"%s\" Exec", argv0, child_file);
rc = shell_execute(NULL, filename, NULL, NULL);
- ok(rc == SE_ERR_FNF, "%s returned %lu\n", shell_call, rc);
+ okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
sprintf(filename, "\"%s\" shlexec \"%s\" Exec", argv0,
child_file);
rc = shell_execute(NULL, filename, NULL, NULL);
- ok(rc == SE_ERR_FNF, "%s returned %lu\n", shell_call, rc);
+ okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
+
+ /* A verb, even if invalid, overrides the normal handling of executables */
+ todo_wait rc = shell_execute_ex(SEE_MASK_FLAG_NO_UI,
+ "notaverb", argv0, NULL, NULL, NULL);
+ todo_wine okShell(rc == SE_ERR_NOASSOC, "returned %lu\n", rc);
+
+ if (!skip_shlexec_tests)
+ {
+ /* A class overrides the normal handling of executables too */
+ /* 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 %lu\n", rc);
+ okChildInt("argcA", 5);
+ todo_wine okChildString("argvA3", "Open");
+ todo_wine okChildPath("argvA4", argv0);
+ }
}
typedef struct
@@ -2143,32 +2193,37 @@
{
/* Test passing and not passing command-line
* argument, no DDE */
- {"", NULL, NULL, NULL, NULL, FALSE, ""},
- {"\"%1\"", NULL, NULL, NULL, NULL, TRUE, ""},
+ {"", NULL, NULL, NULL, NULL, 0, ""},
+ {"\"%1\"", NULL, NULL, NULL, NULL, 1, ""},
/* Test passing and not passing command-line
* argument, with DDE */
- {"", "[open(\"%1\")]", "shlexec",
"dde", NULL, FALSE, "[open(\"%s\")]"},
- {"\"%1\"", "[open(\"%1\")]",
"shlexec", "dde", NULL, TRUE, "[open(\"%s\")]"},
+ {"", "[open(\"%1\")]", "shlexec",
"dde", NULL, 0, "[open(\"%s\")]"},
+ {"\"%1\"", "[open(\"%1\")]",
"shlexec", "dde", NULL, 1, "[open(\"%s\")]"},
/* Test unquoted %1 in command and ddeexec
* (test filename has space) */
{"%1", "[open(%1)]", "shlexec", "dde", NULL,
2, "[open(%s)]", TRUE /* before vista */},
/* Test ifexec precedence over ddeexec */
- {"", "[open(\"%1\")]", "shlexec",
"dde", "[ifexec(\"%1\")]", FALSE,
"[ifexec(\"%s\")]"},
+ {"", "[open(\"%1\")]", "shlexec",
"dde", "[ifexec(\"%1\")]", 0,
"[ifexec(\"%s\")]"},
/* Test default DDE topic */
- {"", "[open(\"%1\")]", "shlexec", NULL, NULL,
FALSE, "[open(\"%s\")]"},
+ {"", "[open(\"%1\")]", "shlexec", NULL, NULL,
0, "[open(\"%s\")]"},
/* Test default DDE application */
- {"", "[open(\"%1\")]", NULL, "dde", NULL,
FALSE, "[open(\"%s\")]"},
+ {"", "[open(\"%1\")]", NULL, "dde", NULL, 0,
"[open(\"%s\")]"},
{NULL}
};
+static int waitforinputidle_count;
static DWORD WINAPI hooked_WaitForInputIdle(HANDLE process, DWORD timeout)
{
+ waitforinputidle_count++;
+ if (winetest_debug > 1)
+ trace("WaitForInputIdle() waiting for dde event timeout=min(%u,5s)\n",
timeout);
+ timeout = timeout < 5000 ? timeout : 5000;
return WaitForSingleObject(dde_ready_event, timeout);
}
@@ -2187,6 +2242,7 @@
PIMAGE_NT_HEADERS nt_headers;
DWORD import_directory_rva;
PIMAGE_IMPORT_DESCRIPTOR import_descriptor;
+ int hook_count = 0;
base = (char *) GetModuleHandleA("shell32.dll");
nt_headers = (PIMAGE_NT_HEADERS)(base + ((PIMAGE_DOS_HEADER) base)->e_lfanew);
@@ -2224,6 +2280,9 @@
VirtualProtect(&iat_entry->u1.Function, sizeof(ULONG_PTR),
PAGE_READWRITE, &old_prot);
iat_entry->u1.Function = (ULONG_PTR) new_func;
VirtualProtect(&iat_entry->u1.Function, sizeof(ULONG_PTR),
old_prot, &old_prot);
+ if (winetest_debug > 1)
+ trace("Hooked %s.WaitForInputIdle\n",
import_module_name);
+ hook_count++;
break;
}
}
@@ -2235,6 +2294,7 @@
import_descriptor++;
}
+ ok(hook_count, "Could not hook WaitForInputIdle()\n");
}
static void test_dde(void)
@@ -2245,6 +2305,7 @@
INT_PTR rc;
HANDLE map;
char *shared_block;
+ DWORD ddeflags;
hook_WaitForInputIdle(hooked_WaitForInputIdle);
@@ -2258,6 +2319,7 @@
4096, "winetest_shlexec_dde_map");
shared_block = MapViewOfFile(map, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 4096);
+ ddeflags = SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI;
test = dde_tests;
while (test->command)
{
@@ -2281,10 +2343,33 @@
}
ddeExec[0] = 0;
- dde_ready_event = CreateEventA(NULL, FALSE, FALSE,
"winetest_shlexec_dde_ready");
- rc = shell_execute_ex(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI, NULL,
filename, NULL, NULL, NULL);
+ waitforinputidle_count = 0;
+ dde_ready_event = CreateEventA(NULL, TRUE, FALSE,
"winetest_shlexec_dde_ready");
+ rc = shell_execute_ex(ddeflags, NULL, filename, NULL, NULL, NULL);
CloseHandle(dde_ready_event);
- ok(32 < rc, "%s failed: rc=%lu err=%u\n", shell_call, rc,
GetLastError());
+ if (!(ddeflags & SEE_MASK_WAITFORINPUTIDLE) && rc == SE_ERR_DDEFAIL
&&
+ GetLastError() == ERROR_FILE_NOT_FOUND &&
+ strcmp(winetest_platform, "windows") == 0)
+ {
+ /* Windows 10 does not call WaitForInputIdle() for DDE which creates
+ * a race condition as the DDE server may not have time to start up.
+ * When that happens the test fails with the above results and we
+ * compensate by forcing the WaitForInputIdle() call.
+ */
+ trace("Adding SEE_MASK_WAITFORINPUTIDLE for Windows 10\n");
+ ddeflags |= SEE_MASK_WAITFORINPUTIDLE;
+ delete_test_association(".sde");
+ Sleep(CHILD_DDE_TIMEOUT);
+ continue;
+ }
+ okShell(32 < rc, "failed: rc=%lu err=%u\n", rc, GetLastError());
+ if (test->ddeexec)
+ okShell(waitforinputidle_count == 1 ||
+ broken(waitforinputidle_count == 0) /* Win10 race */,
+ "WaitForInputIdle() was called %u times\n",
+ waitforinputidle_count);
+ else
+ okShell(waitforinputidle_count == 0, "WaitForInputIdle() was called %u
times for a non-DDE case\n", waitforinputidle_count);
if (32 < rc)
{
@@ -2298,6 +2383,7 @@
sprintf(params, test->expectedDdeExec, filename);
okChildPath("ddeExec", params);
}
+ reset_association_description();
delete_test_association(".sde");
test++;
@@ -2308,7 +2394,7 @@
hook_WaitForInputIdle((void *) WaitForInputIdle);
}
-#define DDE_DEFAULT_APP_VARIANTS 2
+#define DDE_DEFAULT_APP_VARIANTS 3
typedef struct
{
const char* command;
@@ -2319,42 +2405,44 @@
static dde_default_app_tests_t dde_default_app_tests[] =
{
- /* Windows XP and 98 handle default DDE app names in different ways.
- * The application name we see in the first test determines the pattern
- * of application names and return codes we will look for. */
+ /* There are three possible sets of results: Windows <= 2000, XP SP1 and
+ * >= XP SP2. Use the first two tests to determine which results to expect.
+ */
/* Test unquoted existing filename with a space */
- {"%s\\test file.exe", {"test file", "test"}, 0x0, {33,
33}},
- {"%s\\test file.exe param", {"test file", "test"}, 0x0,
{33, 33}},
+ {"%s\\test file.exe", {"test file", "test file",
"test"}, 0x0, {33, 33, 33}},
+ {"%s\\test2 file.exe", {"test2", "",
"test2"}, 0x0, {33, 5, 33}},
+
+ /* Test unquoted existing filename with a space */
+ {"%s\\test file.exe param", {"test file", "test file",
"test"}, 0x0, {33, 33, 33}},
/* Test quoted existing filename with a space */
- {"\"%s\\test file.exe\"", {"test file", "test
file"}, 0x0, {33, 33}},
- {"\"%s\\test file.exe\" param", {"test file",
"test file"}, 0x0, {33, 33}},
+ {"\"%s\\test file.exe\"", {"test file", "test
file", "test file"}, 0x0, {33, 33, 33}},
+ {"\"%s\\test file.exe\" param", {"test file",
"test file", "test file"}, 0x0, {33, 33, 33}},
/* Test unquoted filename with a space that doesn't exist, but
* test2.exe does */
- {"%s\\test2 file.exe", {"test2", "test2"}, 0x0, {33,
33}},
- {"%s\\test2 file.exe param", {"test2", "test2"}, 0x0,
{33, 33}},
+ {"%s\\test2 file.exe param", {"test2", "",
"test2"}, 0x0, {33, 5, 33}},
/* Test quoted filename with a space that does not exist */
- {"\"%s\\test2 file.exe\"", {"", "test2
file"}, 0x0, {5, 33}},
- {"\"%s\\test2 file.exe\" param", {"", "test2
file"}, 0x0, {5, 33}},
+ {"\"%s\\test2 file.exe\"", {"", "",
"test2 file"}, 0x0, {5, 2, 33}},
+ {"\"%s\\test2 file.exe\" param", {"", "",
"test2 file"}, 0x0, {5, 2, 33}},
/* Test filename supplied without the extension */
- {"%s\\test2", {"test2", "test2"}, 0x0, {33, 33}},
- {"%s\\test2 param", {"test2", "test2"}, 0x0, {33,
33}},
+ {"%s\\test2", {"test2", "", "test2"}, 0x0,
{33, 5, 33}},
+ {"%s\\test2 param", {"test2", "", "test2"},
0x0, {33, 5, 33}},
/* Test an unquoted nonexistent filename */
- {"%s\\notexist.exe", {"", "notexist"}, 0x0, {5, 33}},
- {"%s\\notexist.exe param", {"", "notexist"}, 0x0, {5,
33}},
+ {"%s\\notexist.exe", {"", "", "notexist"},
0x0, {5, 2, 33}},
+ {"%s\\notexist.exe param", {"", "",
"notexist"}, 0x0, {5, 2, 33}},
/* Test an application that will be found on the path */
- {"cmd", {"cmd", "cmd"}, 0x0, {33, 33}},
- {"cmd param", {"cmd", "cmd"}, 0x0, {33, 33}},
+ {"cmd", {"cmd", "cmd", "cmd"}, 0x0, {33, 33,
33}},
+ {"cmd param", {"cmd", "cmd", "cmd"}, 0x0,
{33, 33, 33}},
/* Test an application that will not be found on the path */
- {"xyzwxyzwxyz", {"", "xyzwxyzwxyz"}, 0x0, {5, 33}},
- {"xyzwxyzwxyz param", {"", "xyzwxyzwxyz"}, 0x0, {5,
33}},
+ {"xyzwxyzwxyz", {"", "", "xyzwxyzwxyz"}, 0x0,
{5, 2, 33}},
+ {"xyzwxyzwxyz param", {"", "",
"xyzwxyzwxyz"}, 0x0, {5, 2, 33}},
{NULL, {NULL}, 0, {0}}
};
@@ -2431,47 +2519,36 @@
while (GetMessageA(&msg, NULL, 0, 0)) DispatchMessageA(&msg);
rc = msg.wParam > 32 ? 33 : msg.wParam;
- /* First test, find which set of test data we expect to see */
- if (test == dde_default_app_tests)
- {
- int i;
- for (i=0; i<DDE_DEFAULT_APP_VARIANTS; i++)
+ /* The first two tests determine which set of results to expect.
+ * First check the platform as only the first set of results is
+ * acceptable for Wine.
+ */
+ if (strcmp(winetest_platform, "wine"))
+ {
+ if (test == dde_default_app_tests)
{
- if (!strcmp(ddeApplication, test->expectedDdeApplication[i]))
- {
- which = i;
- break;
- }
+ if (strcmp(ddeApplication, test->expectedDdeApplication[0]))
+ which = 2;
}
- if (i == DDE_DEFAULT_APP_VARIANTS)
- skip("Default DDE application test does not match any available
results, using first expected data set.\n");
- }
-
- if ((test->todo & 0x1)==0)
- {
- ok(rc==test->rc[which], "%s failed: rc=%lu err=%u\n",
shell_call,
- rc, GetLastError());
- }
- else todo_wine
- {
- ok(rc==test->rc[which], "%s failed: rc=%lu err=%u\n",
shell_call,
- rc, GetLastError());
- }
+ else if (test == dde_default_app_tests + 1)
+ {
+ if (which == 0 && rc == test->rc[1])
+ which = 1;
+ trace("DDE result variant %d\n", which);
+ }
+ }
+
+ todo_wine_if(test->todo & 0x1)
+ okShell(rc==test->rc[which], "failed: rc=%lu err=%u\n",
+ rc, GetLastError());
if (rc == 33)
{
- if ((test->todo & 0x2)==0)
- {
+ todo_wine_if(test->todo & 0x2)
ok(!strcmp(ddeApplication, test->expectedDdeApplication[which]),
"Expected application '%s', got '%s'\n",
test->expectedDdeApplication[which], ddeApplication);
- }
- else todo_wine
- {
- ok(!strcmp(ddeApplication, test->expectedDdeApplication[which]),
- "Expected application '%s', got '%s'\n",
- test->expectedDdeApplication[which], ddeApplication);
- }
- }
+ }
+ reset_association_description();
delete_test_association(".sde");
test++;
@@ -2606,6 +2683,9 @@
create_test_verb(".shlexec", "QuotedLowerL", 0,
"QuotedLowerL \"%l\"");
create_test_verb(".shlexec", "UpperL", 0, "UpperL
%L");
create_test_verb(".shlexec", "QuotedUpperL", 0,
"QuotedUpperL \"%L\"");
+
+ /* Set an environment variable to see if it is inherited */
+ SetEnvironmentVariableA("ShlexecVar", "Present");
}
static void cleanup_test(void)
@@ -2650,7 +2730,7 @@
SetCurrentDirectoryA(tmpdir);
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, "test2.exe", params, NULL, NULL);
- ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+ okShell(rc > 32, "returned %lu\n", rc);
okChildInt("argcA", 4);
okChildString("argvA3", "Exec");
todo_wine okChildPath("longPath", path);
@@ -2658,12 +2738,12 @@
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, "test2.exe", params, NULL, NULL);
- ok(rc == SE_ERR_FNF, "%s returned %lu\n", shell_call, rc);
+ okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
/* Explicitly specify the directory to use */
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, "test2.exe", params, tmpdir, NULL);
- ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+ okShell(rc > 32, "returned %lu\n", rc);
okChildInt("argcA", 4);
okChildString("argvA3", "Exec");
todo_wine okChildPath("longPath", path);
@@ -2671,11 +2751,11 @@
/* Specify it through an environment variable */
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, "test2.exe", params, "%TMPDIR%",
NULL);
- todo_wine ok(rc == SE_ERR_FNF, "%s returned %lu\n", shell_call, rc);
+ todo_wine okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
rc=shell_execute_ex(SEE_MASK_DOENVSUBST|SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, "test2.exe", params, "%TMPDIR%",
NULL);
- ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+ okShell(rc > 32, "returned %lu\n", rc);
okChildInt("argcA", 4);
okChildString("argvA3", "Exec");
todo_wine okChildPath("longPath", path);
@@ -2684,7 +2764,7 @@
sprintf(dirpath, "%s:%s", curdir, tmpdir);
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, "test2.exe", params, dirpath, NULL);
- ok(rc == SE_ERR_FNF, "%s returned %lu\n", shell_call, rc);
+ okShell(rc == SE_ERR_FNF, "returned %lu\n", rc);
}
START_TEST(shlexec)
@@ -2694,7 +2774,8 @@
if (myARGC >= 3)
{
doChild(myARGC, myARGV);
- exit(0);
+ /* Skip the tests/failures trace for child processes */
+ ExitProcess(winetest_get_failures());
}
init_test();
Modified: trunk/rostests/winetests/shell32/shlfolder.c
URL:
http://svn.reactos.org/svn/reactos/trunk/rostests/winetests/shell32/shlfold…
==============================================================================
--- trunk/rostests/winetests/shell32/shlfolder.c [iso-8859-1] (original)
+++ trunk/rostests/winetests/shell32/shlfolder.c [iso-8859-1] Wed Mar 9 08:43:20 2016
@@ -388,6 +388,14 @@
SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM,
SFGAO_CAPABILITYMASK | SFGAO_FILESYSTEM,
};
+ static const ULONG full_attrs[5] =
+ {
+ SFGAO_CAPABILITYMASK | SFGAO_STORAGE | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSTEM |
SFGAO_FOLDER | SFGAO_FILESYSANCESTOR,
+ SFGAO_CAPABILITYMASK | SFGAO_STORAGE | SFGAO_STORAGEANCESTOR | SFGAO_FILESYSTEM |
SFGAO_FOLDER | SFGAO_FILESYSANCESTOR,
+ SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM,
+ SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM,
+ SFGAO_CAPABILITYMASK | SFGAO_STREAM | SFGAO_FILESYSTEM,
+ };
hr = IShellFolder_EnumObjects(iFolder, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS |
SHCONTF_INCLUDEHIDDEN, &iEnumList);
ok(hr == S_OK, "EnumObjects failed %08x\n", hr);
@@ -440,6 +448,11 @@
ok(flags == attrs[i] ||
flags == (attrs[i] & ~SFGAO_FILESYSANCESTOR), /* Win9x, NT4 */
"GetAttributesOf[%i] got %08x, expected %08x\n", i, flags,
attrs[i]);
+
+ flags = ~0u;
+ hr = IShellFolder_GetAttributesOf(iFolder, 1, (LPCITEMIDLIST*)(idlArr + i),
&flags);
+ ok(hr == S_OK, "GetAttributesOf returns %08x\n", hr);
+ ok((flags & ~SFGAO_HASSUBFOLDER) == full_attrs[i], "%d: got %08x
expected %08x\n", i, flags, full_attrs[i]);
}
for (i=0;i<5;i++)
@@ -1889,14 +1902,14 @@
if (!pIsWow64Process || !pIsWow64Process( GetCurrentProcess(), &is_wow64 ))
is_wow64 = FALSE;
hr = pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES, 0, SHGFP_TYPE_CURRENT, path );
- ok( !hr, "SHGetFolderPathA failed %x\n", hr );
+ ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr );
hr = pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILESX86, 0, SHGFP_TYPE_CURRENT, path_x86
);
if (hr == E_FAIL)
{
win_skip( "Program Files (x86) not supported\n" );
return;
}
- ok( !hr, "SHGetFolderPathA failed %x\n", hr );
+ ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr );
if (is_win64)
{
ok( lstrcmpiA( path, path_x86 ), "paths are identical '%s'\n",
path );
@@ -1924,14 +1937,14 @@
}
hr = pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMON, 0, SHGFP_TYPE_CURRENT, path
);
- ok( !hr, "SHGetFolderPathA failed %x\n", hr );
+ ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr );
hr = pSHGetFolderPathA( 0, CSIDL_PROGRAM_FILES_COMMONX86, 0, SHGFP_TYPE_CURRENT,
path_x86 );
if (hr == E_FAIL)
{
win_skip( "Common Files (x86) not supported\n" );
return;
}
- ok( !hr, "SHGetFolderPathA failed %x\n", hr );
+ ok( hr == S_OK, "SHGetFolderPathA failed %x\n", hr );
if (is_win64)
{
ok( lstrcmpiA( path, path_x86 ), "paths are identical '%s'\n",
path );
@@ -5256,6 +5269,63 @@
IShellFolder_Release(desktop);
}
+static void test_DataObject(void)
+{
+ IShellFolder *desktop;
+ IDataObject *data_obj;
+ HRESULT hres;
+ IEnumIDList *peidl;
+ LPITEMIDLIST apidl;
+ FORMATETC fmt;
+ DWORD cf_shellidlist;
+ STGMEDIUM medium;
+
+ SHGetDesktopFolder(&desktop);
+
+ hres = IShellFolder_EnumObjects(desktop, NULL,
+ SHCONTF_NONFOLDERS|SHCONTF_FOLDERS|SHCONTF_INCLUDEHIDDEN, &peidl);
+ ok(hres == S_OK, "got %x\n", hres);
+
+ if(IEnumIDList_Next(peidl, 1, &apidl, NULL) != S_OK) {
+ skip("no files on desktop - skipping GetDataObject tests\n");
+ IEnumIDList_Release(peidl);
+ IShellFolder_Release(desktop);
+ return;
+ }
+ IEnumIDList_Release(peidl);
+
+ hres = IShellFolder_GetUIObjectOf(desktop, NULL, 1, (LPCITEMIDLIST*)&apidl,
+ &IID_IDataObject, NULL, (void**)&data_obj);
+ ok(hres == S_OK, "got %x\n", hres);
+ pILFree(apidl);
+ IShellFolder_Release(desktop);
+
+ cf_shellidlist = RegisterClipboardFormatW(CFSTR_SHELLIDLISTW);
+ fmt.cfFormat = cf_shellidlist;
+ fmt.ptd = NULL;
+ fmt.dwAspect = DVASPECT_CONTENT;
+ fmt.lindex = -1;
+ fmt.tymed = TYMED_HGLOBAL;
+ hres = IDataObject_QueryGetData(data_obj, &fmt);
+ ok(hres == S_OK, "got %x\n", hres);
+
+ fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM;
+ hres = IDataObject_QueryGetData(data_obj, &fmt);
+ ok(hres == S_OK, "got %x\n", hres);
+
+ fmt.tymed = TYMED_ISTREAM;
+ hres = IDataObject_QueryGetData(data_obj, &fmt);
+ todo_wine ok(hres == S_FALSE, "got %x\n", hres);
+
+ fmt.tymed = TYMED_HGLOBAL | TYMED_ISTREAM;
+ hres = IDataObject_GetData(data_obj, &fmt, &medium);
+ ok(hres == S_OK, "got %x\n", hres);
+ ok(medium.tymed == TYMED_HGLOBAL, "medium.tymed = %x\n", medium.tymed);
+ ReleaseStgMedium(&medium);
+
+ IDataObject_Release(data_obj);
+}
+
START_TEST(shlfolder)
{
init_function_pointers();
@@ -5296,6 +5366,7 @@
test_SHCreateDefaultContextMenu();
test_SHCreateShellFolderView();
test_SHCreateShellFolderViewEx();
+ test_DataObject();
OleUninitialize();
}