[SHELL32_WINETEST] Sync with Wine Staging 1.7.37. CORE-9246
authorAmine Khaldi <amine.khaldi@reactos.org>
Sun, 26 Apr 2015 11:27:59 +0000 (11:27 +0000)
committerAmine Khaldi <amine.khaldi@reactos.org>
Sun, 26 Apr 2015 11:27:59 +0000 (11:27 +0000)
svn path=/trunk/; revision=67432

rostests/winetests/shell32/assoc.c
rostests/winetests/shell32/ebrowser.c
rostests/winetests/shell32/recyclebin.c
rostests/winetests/shell32/shelllink.c
rostests/winetests/shell32/shellpath.c
rostests/winetests/shell32/shlexec.c
rostests/winetests/shell32/shlfileop.c
rostests/winetests/shell32/shlfolder.c
rostests/winetests/shell32/shlview.c

index ff999e9..0092081 100644 (file)
@@ -57,22 +57,12 @@ static void test_IQueryAssociations_QueryInterface(void)
 }
 
 
-static void test_IApplicationAssociationRegistration_QueryInterface(void)
+static void test_IApplicationAssociationRegistration_QueryInterface(IApplicationAssociationRegistration *appreg)
 {
-    IApplicationAssociationRegistration *appreg;
     IApplicationAssociationRegistration *appreg2;
     IUnknown *unk;
     HRESULT hr;
 
-    /* this works since Vista */
-    hr = CoCreateInstance(&CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC_SERVER,
-                          &IID_IApplicationAssociationRegistration, (LPVOID*)&appreg);
-
-    if (FAILED(hr)) {
-        skip("IApplicationAssociationRegistration not created: 0x%x\n", hr);
-        return;
-    }
-
     hr = IApplicationAssociationRegistration_QueryInterface(appreg, &IID_IApplicationAssociationRegistration,
        (void**)&appreg2);
     ok(hr == S_OK, "QueryInterface (IApplicationAssociationRegistration) returned 0x%x\n", hr);
@@ -88,8 +78,6 @@ static void test_IApplicationAssociationRegistration_QueryInterface(void)
 
     hr = IApplicationAssociationRegistration_QueryInterface(appreg, &IID_IUnknown, NULL);
     ok(hr == E_POINTER, "got 0x%x (expected E_POINTER)\n", hr);
-
-    IApplicationAssociationRegistration_Release(appreg);
 }
 
 struct assoc_getstring_test
@@ -103,7 +91,6 @@ struct assoc_getstring_test
 };
 
 static const WCHAR httpW[] = {'h','t','t','p',0};
-static const WCHAR httpsW[] = {'h','t','t','p','s',0};
 static const WCHAR badW[] = {'b','a','d','b','a','d',0};
 
 static struct assoc_getstring_test getstring_tests[] =
@@ -190,9 +177,48 @@ static void test_IQueryAssociations_Init(void)
     IQueryAssociations_Release(assoc);
 }
 
+static void test_IApplicationAssociationRegistration_QueryCurrentDefault(IApplicationAssociationRegistration *appreg)
+{
+    static const WCHAR emptyW[] = {0};
+    static const WCHAR txtW[] = {'.','t','x','t',0};
+    static const WCHAR spacetxtW[] = {' ','.','t','x','t',0};
+    HRESULT hr;
+    LPWSTR assocprog = NULL;
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, emptyW, AT_URLPROTOCOL, AL_EFFECTIVE, &assocprog);
+    ok(hr == E_INVALIDARG, "got 0x%x\n", hr);
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, emptyW, AT_FILEEXTENSION, AL_EFFECTIVE, &assocprog);
+    ok(hr == E_INVALIDARG, "got 0x%x\n", hr);
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, spacetxtW, AT_FILEEXTENSION, AL_EFFECTIVE, &assocprog);
+    ok(hr == E_INVALIDARG || hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION) /* Win8 */, "got 0x%x\n", hr);
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, httpW, AT_URLPROTOCOL, AL_EFFECTIVE, NULL);
+    ok(hr == E_INVALIDARG, "got 0x%x\n", hr);
+
+    /* AT_FILEEXTENSION must start with a period */
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, txtW, AT_FILEEXTENSION, AL_EFFECTIVE, &assocprog);
+    ok(hr == S_OK, "got 0x%x\n", hr);
+    trace("%s\n", wine_dbgstr_w(assocprog));
+    CoTaskMemFree(assocprog);
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, emptyW, AT_STARTMENUCLIENT, AL_EFFECTIVE, &assocprog);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION), "got 0x%x\n", hr);
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, emptyW, AT_MIMETYPE, AL_EFFECTIVE, &assocprog);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION), "got 0x%x\n", hr);
+
+    hr = IApplicationAssociationRegistration_QueryCurrentDefault(appreg, httpW, AT_URLPROTOCOL, AL_EFFECTIVE, &assocprog);
+    todo_wine ok(hr == S_OK, "got 0x%x\n", hr);
+    trace("%s\n", wine_dbgstr_w(assocprog));
+    CoTaskMemFree(assocprog);
+}
+
 START_TEST(assoc)
 {
     IQueryAssociations *qa;
+    IApplicationAssociationRegistration *appreg;
     HRESULT hr;
 
     CoInitialize(NULL);
@@ -210,7 +236,18 @@ START_TEST(assoc)
     else
         win_skip("IQueryAssociations not supported, 0x%x\n", hr);
 
-    test_IApplicationAssociationRegistration_QueryInterface();
+    /* this works since Vista */
+    hr = CoCreateInstance(&CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_IApplicationAssociationRegistration, (LPVOID *)&appreg);
+    if (hr == S_OK)
+    {
+        test_IApplicationAssociationRegistration_QueryInterface(appreg);
+        test_IApplicationAssociationRegistration_QueryCurrentDefault(appreg);
+
+        IApplicationAssociationRegistration_Release(appreg);
+    }
+    else
+        win_skip("IApplicationAssociationRegistration not supported: 0x%x\n", hr);
 
     CoUninitialize();
 }
index 1936cf9..4c255a1 100644 (file)
@@ -1381,7 +1381,7 @@ static void test_navigation(void)
     ok(pSHCreateShellItem != NULL, "pSHCreateShellItem unexpectedly missing.\n");
 
     GetCurrentDirectoryW(MAX_PATH, current_path);
-    if(!lstrlenW(current_path))
+    if(!current_path[0])
     {
         skip("Failed to create test-directory.\n");
         return;
index d449b7e..a5ac1dc 100644 (file)
@@ -55,8 +55,7 @@ static void test_query_recyclebin(void)
     HRESULT hr;
     HANDLE file;
     SHFILEOPSTRUCTA shfo;
-    const CHAR name[] = "test.txt";
-    CHAR buf[MAX_PATH + sizeof(name) + 1];
+    CHAR temp_path[MAX_PATH-14], buf[MAX_PATH+1];
     if(!pSHQueryRecycleBinA)
     {
         skip("SHQueryRecycleBinA does not exist\n");
@@ -67,18 +66,17 @@ static void test_query_recyclebin(void)
         skip("SHFileOperationA does not exist\n");
         return;
     }
-    GetCurrentDirectoryA(MAX_PATH, buf);
-    strcat(buf,"\\");
-    strcat(buf,name);
+    ok(GetTempPathA(sizeof(temp_path), temp_path), "GetTempPath failed\n");
+    ok(GetTempFileNameA(temp_path, "trash", 0, buf), "GetTempFileName failed\n");
     buf[strlen(buf) + 1] = '\0';
     hr = pSHQueryRecycleBinA(buf,&info1);
     ok(hr == S_OK, "SHQueryRecycleBinA failed with error 0x%x\n", hr);
     ok(info1.i64Size!=0xdeadbeef,"i64Size not set\n");
     ok(info1.i64NumItems!=0xdeadbeef,"i64NumItems not set\n");
     /*create and send a file to the recycle bin*/
-    file = CreateFileA(name,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
-    ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n",name);
-    WriteFile(file,name,strlen(name),&written,NULL);
+    file = CreateFileA(buf,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,0,NULL);
+    ok(file != INVALID_HANDLE_VALUE, "Failure to open file %s\n",buf);
+    WriteFile(file,buf,strlen(buf),&written,NULL);
     CloseHandle(file);
     shfo.hwnd = NULL;
     shfo.wFunc = FO_DELETE;
@@ -89,14 +87,9 @@ static void test_query_recyclebin(void)
     shfo.lpszProgressTitle = NULL;
     ok(!pSHFileOperationA(&shfo), "Deletion was not successful\n");
     hr = pSHQueryRecycleBinA(buf,&info2);
-    ok(hr == S_OK, "SHQueryRecycleBinW failed with error 0x%x\n", hr);
-    if(info2.i64Size!=info1.i64Size || info2.i64NumItems!=info1.i64NumItems) {
-      ok(info2.i64Size==info1.i64Size+written,"Expected recycle bin to have 0x%s bytes\n",str_from_int64(info1.i64Size+written));
-      ok(info2.i64NumItems==info1.i64NumItems+1,"Expected recycle bin to have 0x%s items\n",str_from_int64(info1.i64NumItems+1));
-    } else todo_wine {
-      ok(info2.i64Size==info1.i64Size+written,"Expected recycle bin to have 0x%s bytes\n",str_from_int64(info1.i64Size+written));
-      ok(info2.i64NumItems==info1.i64NumItems+1,"Expected recycle bin to have 0x%s items\n",str_from_int64(info1.i64NumItems+1));
-    }
+    ok(hr == S_OK, "SHQueryRecycleBinA failed with error 0x%x\n", hr);
+    ok(info2.i64Size==info1.i64Size+written,"Expected recycle bin to have 0x%s bytes\n",str_from_int64(info1.i64Size+written));
+    ok(info2.i64NumItems==info1.i64NumItems+1,"Expected recycle bin to have 0x%s items\n",str_from_int64(info1.i64NumItems+1));
 }
 
 
index 0b2b7be..b258052 100755 (executable)
@@ -49,8 +49,6 @@ static const GUID _IID_IShellLinkDataList = {
     { 0xb9, 0x2f, 0x00, 0xa0, 0xc9, 0x03, 0x12, 0xe1 }
 };
 
-static const WCHAR notafile[]= { 'C',':','\\','n','o','n','e','x','i','s','t','e','n','t','\\','f','i','l','e',0 };
-
 
 /* For some reason SHILCreateFromPath does not work on Win98 and
  * SHSimpleIDListFromPathA does not work on NT4. But if we call both we
@@ -1153,6 +1151,41 @@ static void test_SHExtractIcons(void)
     for (i = 0; i < ret; i++) DestroyIcon(icons[i]);
 }
 
+static void test_propertystore(void)
+{
+    IShellLinkA *linkA;
+    IShellLinkW *linkW;
+    IPropertyStore *ps;
+    HRESULT hr;
+
+    hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
+                         &IID_IShellLinkA, (void**)&linkA);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IShellLinkA_QueryInterface(linkA, &IID_IShellLinkW, (void**)&linkW);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    hr = IShellLinkA_QueryInterface(linkA, &IID_IPropertyStore, (void**)&ps);
+    if (hr == S_OK) {
+        IPropertyStoreCache *pscache;
+
+        IPropertyStore_Release(ps);
+
+        hr = IShellLinkW_QueryInterface(linkW, &IID_IPropertyStore, (void**)&ps);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+
+        hr = IPropertyStore_QueryInterface(ps, &IID_IPropertyStoreCache, (void**)&pscache);
+        ok(hr == E_NOINTERFACE, "got 0x%08x\n", hr);
+
+        IPropertyStore_Release(ps);
+    }
+    else
+        win_skip("IShellLink doesn't support IPropertyStore.\n");
+
+    IShellLinkA_Release(linkA);
+    IShellLinkW_Release(linkW);
+}
+
 START_TEST(shelllink)
 {
     HRESULT r;
@@ -1180,6 +1213,7 @@ START_TEST(shelllink)
     test_GetIconLocation();
     test_SHGetStockIconInfo();
     test_SHExtractIcons();
+    test_propertystore();
 
     CoUninitialize();
 }
index 7486fac..64b7c08 100644 (file)
@@ -101,6 +101,7 @@ static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR,UINT);
 static HRESULT (WINAPI *pSHGetKnownFolderPath)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR *);
 static HRESULT (WINAPI *pSHSetKnownFolderPath)(REFKNOWNFOLDERID, DWORD, HANDLE, PWSTR);
 static HRESULT (WINAPI *pSHGetFolderPathEx)(REFKNOWNFOLDERID, DWORD, HANDLE, LPWSTR, DWORD);
+static BOOL (WINAPI *pPathYetAnotherMakeUniqueName)(PWSTR, PCWSTR, PCWSTR, PCWSTR);
 
 static DLLVERSIONINFO shellVersion = { 0 };
 static LPMALLOC pMalloc;
@@ -207,6 +208,7 @@ static void loadShell32(void)
         pILFindLastID = (void *)GetProcAddress(hShell32, (LPCSTR)16);
     GET_PROC(SHFileOperationA)
     GET_PROC(SHGetMalloc)
+    GET_PROC(PathYetAnotherMakeUniqueName)
 
     ok(pSHGetMalloc != NULL, "shell32 is missing SHGetMalloc\n");
     if (pSHGetMalloc)
@@ -859,6 +861,11 @@ if (0) { /* crashes */
     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
     ok(path != NULL, "expected path != NULL\n");
 
+    path = NULL;
+    hr = pSHGetKnownFolderPath(&FOLDERID_Desktop, KF_FLAG_DEFAULT_PATH, NULL, &path);
+    ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
+    ok(path != NULL, "expected path != NULL\n");
+
     hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, MAX_PATH);
     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
     ok(!lstrcmpiW(path, buffer), "expected equal paths\n");
@@ -876,7 +883,7 @@ if (0) { /* crashes */
     ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got 0x%08x\n", hr);
 }
     hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len);
-    ok(hr == HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER), "expected 0x8007007a, got 0x%08x\n", hr);
+    ok(hr == E_NOT_SUFFICIENT_BUFFER, "expected E_NOT_SUFFICIENT_BUFFER, got 0x%08x\n", hr);
 
     hr = pSHGetFolderPathEx(&FOLDERID_Desktop, 0, NULL, buffer, len + 1);
     ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr);
@@ -2631,6 +2638,85 @@ static void test_DoEnvironmentSubst(void)
     }
 }
 
+static void test_PathYetAnotherMakeUniqueName(void)
+{
+    static const WCHAR shortW[] = {'f','i','l','e','.','t','s','t',0};
+    static const WCHAR short2W[] = {'f','i','l','e',' ','(','2',')','.','t','s','t',0};
+    static const WCHAR tmpW[] = {'t','m','p',0};
+    static const WCHAR longW[] = {'n','a','m','e',0};
+    static const WCHAR long2W[] = {'n','a','m','e',' ','(','2',')',0};
+    WCHAR nameW[MAX_PATH], buffW[MAX_PATH], pathW[MAX_PATH];
+    HANDLE file;
+    BOOL ret;
+
+    if (!pPathYetAnotherMakeUniqueName)
+    {
+        win_skip("PathYetAnotherMakeUniqueName() is not available.\n");
+        return;
+    }
+
+if (0)
+{
+    /* crashes on Windows */
+    ret = pPathYetAnotherMakeUniqueName(NULL, NULL, NULL, NULL);
+    ok(!ret, "got %d\n", ret);
+
+    ret = pPathYetAnotherMakeUniqueName(nameW, NULL, NULL, NULL);
+    ok(!ret, "got %d\n", ret);
+}
+
+    GetTempPathW(sizeof(pathW)/sizeof(WCHAR), pathW);
+
+    /* Using short name only first */
+    nameW[0] = 0;
+    ret = pPathYetAnotherMakeUniqueName(nameW, pathW, shortW, NULL);
+    ok(ret, "got %d\n", ret);
+    lstrcpyW(buffW, pathW);
+    lstrcatW(buffW, shortW);
+    ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW));
+
+    /* now create a file with this name and get next name */
+    file = CreateFileW(nameW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+    ok(file != NULL, "got %p\n", file);
+
+    nameW[0] = 0;
+    ret = pPathYetAnotherMakeUniqueName(nameW, pathW, shortW, NULL);
+    ok(ret, "got %d\n", ret);
+    lstrcpyW(buffW, pathW);
+    lstrcatW(buffW, short2W);
+    ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW));
+
+    CloseHandle(file);
+
+    /* Using short and long */
+    nameW[0] = 0;
+    ret = pPathYetAnotherMakeUniqueName(nameW, pathW, tmpW, longW);
+    ok(ret, "got %d\n", ret);
+    lstrcpyW(buffW, pathW);
+    lstrcatW(buffW, longW);
+    ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW));
+
+    file = CreateFileW(nameW, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_FLAG_DELETE_ON_CLOSE, NULL);
+    ok(file != NULL, "got %p\n", file);
+
+    nameW[0] = 0;
+    ret = pPathYetAnotherMakeUniqueName(nameW, pathW, tmpW, longW);
+    ok(ret, "got %d\n", ret);
+    lstrcpyW(buffW, pathW);
+    lstrcatW(buffW, long2W);
+    ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW));
+
+    CloseHandle(file);
+
+    /* Using long only */
+    nameW[0] = 0;
+    ret = pPathYetAnotherMakeUniqueName(nameW, pathW, NULL, longW);
+    ok(ret, "got %d\n", ret);
+    lstrcpyW(buffW, pathW);
+    lstrcatW(buffW, longW);
+    ok(!lstrcmpW(nameW, buffW), "got %s, expected %s\n", wine_dbgstr_w(nameW), wine_dbgstr_w(buffW));
+}
+
 START_TEST(shellpath)
 {
     if (!init()) return;
@@ -2659,5 +2745,6 @@ START_TEST(shellpath)
         test_SHGetFolderPathEx();
         test_knownFolders();
         test_DoEnvironmentSubst();
+        test_PathYetAnotherMakeUniqueName();
     }
 }
index 9f4b1a3..2b3947e 100755 (executable)
@@ -118,7 +118,7 @@ static INT_PTR shell_execute(LPCSTR verb, LPCSTR file, LPCSTR parameters, LPCSTR
      * 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_SHOWNORMAL);
+    rc=(INT_PTR)ShellExecuteA(NULL, verb, file, parameters, directory, SW_HIDE);
 
     if (rc > 32)
     {
@@ -183,7 +183,7 @@ static INT_PTR shell_execute_ex(DWORD mask, LPCSTR verb, LPCSTR file,
         trace("%s\n", shell_call);
 
     sei.cbSize=sizeof(sei);
-    sei.fMask=SEE_MASK_NOCLOSEPROCESS | mask;
+    sei.fMask=SEE_MASK_NOCLOSEPROCESS | SEE_MASK_NO_CONSOLE | mask;
     sei.hwnd=NULL;
     sei.lpVerb=verb;
     sei.lpFile=file;
@@ -857,6 +857,7 @@ static const char* testfiles[]=
     "%s\\masked",
     "%s\\test file.sde",
     "%s\\test file.exe",
+    "%s\\test file two.exe",
     "%s\\test2.exe",
     "%s\\simple.shlexec",
     "%s\\drawback_file.noassoc",
@@ -931,7 +932,7 @@ static void test_lpFile_parsed(void)
     /* 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);
-    todo_wine ok(rc > 32, "%s failed: rc=%lu\n", shell_call, rc);
+    ok(rc > 32, "%s failed: rc=%lu\n", shell_call, 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);
@@ -1159,6 +1160,8 @@ static BOOL test_one_cmdline(const cmdline_tests_t* test)
         win_skip("CommandLineToArgvW not implemented, skipping\n");
         return FALSE;
     }
+    ok(!argsW[cl2a_count] || broken(argsW[cl2a_count] != NULL) /* before Vista */,
+       "expected NULL-terminated list of commandline arguments\n");
 
     count = 0;
     while (test->args[count])
@@ -1218,6 +1221,8 @@ static void test_commandline2argv(void)
     *strW = 0;
     args = CommandLineToArgvW(strW, &numargs);
     ok(numargs == 1, "expected 1 args, got %d\n", numargs);
+    ok(!args || (!args[numargs] || broken(args[numargs] != NULL) /* before Vista */),
+       "expected NULL-terminated list of commandline arguments\n");
     if (numargs == 1)
     {
         GetModuleFileNameW(NULL, strW, sizeof(strW)/sizeof(*strW));
@@ -1543,7 +1548,7 @@ static void test_filename(void)
                "%s failed: rc=%ld err=%u\n", shell_call,
                rc, GetLastError());
         }
-        else todo_wine
+        else
         {
             ok(rc==test->rc, "%s failed: rc=%ld err=%u\n", shell_call,
                rc, GetLastError());
@@ -2090,6 +2095,7 @@ static void test_exes(void)
 {
     char filename[MAX_PATH];
     char params[1024];
+    DWORD retval;
     INT_PTR rc;
 
     sprintf(params, "shlexec \"%s\" Exec", child_file);
@@ -2116,6 +2122,32 @@ static void test_exes(void)
     {
         win_skip("Skipping shellexecute of file with unassociated extension\n");
     }
+
+    /* the directory with the test programs contain "test file.exe"
+     * and "test file two.exe". Check we do not start the first
+     * when we specify to start the second (see bug 19666)
+     */
+    sprintf(filename, "%s\\test file.exe", tmpdir);
+    retval = CopyFileA(argv0, filename, FALSE);
+    ok(retval, "CopyFile(\"%s\",\"%s\",FALSE) failed\n", argv0, filename);
+    sprintf(filename, "%s\\test file two.exe", tmpdir);
+    retval = CopyFileA(argv0, filename, FALSE);
+    ok(retval, "CopyFile(\"%s\",\"%s\",FALSE) failed\n", argv0, filename);
+    rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, params, NULL, NULL);
+    ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+    okChildInt("argcA", 4);
+    okChildString("argvA0", filename);
+    okChildString("argvA3", "Exec");
+
+    /* check quoted filename */
+    sprintf(filename, "\"%s\\test file two.exe\"", tmpdir);
+    rc=shell_execute_ex(SEE_MASK_NOZONECHECKS, NULL, filename, params, NULL, NULL);
+    ok(rc > 32, "%s returned %lu\n", shell_call, rc);
+    okChildInt("argcA", 4);
+    /* strip the quotes for the compare */
+    sprintf(filename, "%s\\test file two.exe", tmpdir);
+    okChildString("argvA0", filename);
+    okChildString("argvA3", "Exec");
 }
 
 typedef struct
index 64d0fbc..07e4ee2 100644 (file)
@@ -251,7 +251,7 @@ static void test_get_file_info(void)
     ok(rc == 1, "SHGetFileInfoA(c:\\nonexistent) should return 1, got 0x%x\n", rc);
     if (rc)
     {
-        ok(strcpy(shfi.szDisplayName, "dummy") != 0, "SHGetFileInfoA(c:\\nonexistent) displayname is not set\n");
+        ok(strcmp(shfi.szDisplayName, "dummy"), "SHGetFileInfoA(c:\\nonexistent) displayname is not set\n");
         ok(shfi.iIcon != 0xdeadbeef, "SHGetFileInfoA(c:\\nonexistent) iIcon is not set\n");
     }
 
@@ -622,7 +622,6 @@ static void test_delete(void)
     shfo.pFrom = "nonexistent.txt\0";
     shfo.wFunc = FO_DELETE;
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == 1026 ||
        ret == ERROR_FILE_NOT_FOUND || /* Vista */
        broken(ret == ERROR_SUCCESS), /* NT4 */
@@ -651,7 +650,6 @@ static void test_delete(void)
     shfo.pFrom = "test1.txt\0nonexistent.txt\0test2.txt\0";
     shfo.wFunc = FO_DELETE;
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == 1026 ||
        ret == ERROR_FILE_NOT_FOUND || /* Vista */
        broken(ret == ERROR_SUCCESS), /* NT4 */
@@ -664,14 +662,12 @@ static void test_delete(void)
     init_shfo_tests();
     shfo.pFrom = "testdir2\\nonexistent.txt\0";
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == ERROR_FILE_NOT_FOUND || /* Vista */
        broken(ret == 0x402) || /* XP */
        broken(ret == ERROR_SUCCESS), /* NT4 */
        "Expected 0x402 or ERROR_FILE_NOT_FOUND, got %x\n", ret);
     shfo.pFrom = "nonexistent\\one.txt\0";
     ret = SHFileOperationA(&shfo);
-    todo_wine
     ok(ret == DE_INVALIDFILES || /* Vista or later */
        broken(ret == 0x402), /* XP */
        "Expected 0x402 or DE_INVALIDFILES, got %x\n", ret);
@@ -898,13 +894,13 @@ static void test_copy(void)
     DeleteFileA("test7.txt");
     RemoveDirectoryA("test8.txt");
 
-    /* number of sources do not correspond to number of targets */
+    /* number of sources does not correspond to number of targets */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
     retval = SHFileOperationA(&shfo2);
     if (dir_exists("test6.txt"))
     {
-        /* Vista and W2K8 (broken or new behavior ?) */
+        /* Vista and W2K8 (broken or new behavior?) */
         ok(retval == DE_DESTSAMETREE, "Expected DE_DESTSAMETREE, got %d\n", retval);
         ok(DeleteFileA("test6.txt\\test1.txt"), "The file is not copied - many files "
            "are specified as a target\n");
@@ -1871,7 +1867,7 @@ static void test_move(void)
 
     init_shfo_tests();
 
-    /* number of sources do not correspond to number of targets,
+    /* number of sources does not correspond to number of targets,
        include directories */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test4.txt\0");
     set_curr_dir_path(to, "test6.txt\0test7.txt\0");
@@ -1904,7 +1900,7 @@ static void test_move(void)
     }
 
     init_shfo_tests();
-    /* number of sources do not correspond to number of targets,
+    /* number of sources does not correspond to number of targets,
        files only,
        from exceeds to */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
@@ -1939,7 +1935,7 @@ static void test_move(void)
     }
 
     init_shfo_tests();
-    /* number of sources do not correspond to number of targets,
+    /* number of sources does not correspond to number of targets,
        files only,
        too exceeds from */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0");
@@ -1963,7 +1959,7 @@ static void test_move(void)
     }
 
     init_shfo_tests();
-    /* number of sources do not correspond to number of targets,
+    /* number of sources does not correspond to number of targets,
        target directories */
     set_curr_dir_path(from, "test1.txt\0test2.txt\0test3.txt\0");
     set_curr_dir_path(to, "test4.txt\0test5.txt\0");
@@ -1987,7 +1983,7 @@ static void test_move(void)
 
 
     init_shfo_tests();
-    /*  0 incomming files */
+    /*  0 incoming files */
     set_curr_dir_path(from, "\0\0");
     set_curr_dir_path(to, "test6.txt\0\0");
     retval = SHFileOperationA(&shfo2);
index f096476..1b457bb 100644 (file)
@@ -60,6 +60,7 @@ static HRESULT (WINAPI *pSHCreateItemFromIDList)(PCIDLIST_ABSOLUTE pidl, REFIID
 static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**);
 static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
 static HRESULT (WINAPI *pSHCreateShellItemArray)(LPCITEMIDLIST,IShellFolder*,UINT,LPCITEMIDLIST*,IShellItemArray**);
+static HRESULT (WINAPI *pSHCreateShellItemArrayFromIDLists)(UINT, PCIDLIST_ABSOLUTE*, IShellItemArray**);
 static HRESULT (WINAPI *pSHCreateShellItemArrayFromDataObject)(IDataObject*, REFIID, void **);
 static HRESULT (WINAPI *pSHCreateShellItemArrayFromShellItem)(IShellItem*, REFIID, void **);
 static LPITEMIDLIST (WINAPI *pILCombine)(LPCITEMIDLIST,LPCITEMIDLIST);
@@ -80,7 +81,7 @@ static WCHAR *make_wstr(const char *str)
     WCHAR *ret;
     int len;
 
-    if(!str || strlen(str) == 0)
+    if (!str || !str[0])
         return NULL;
 
     len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
@@ -116,6 +117,7 @@ static void init_function_pointers(void)
     MAKEFUNC(SHCreateItemFromParsingName);
     MAKEFUNC(SHCreateShellItem);
     MAKEFUNC(SHCreateShellItemArray);
+    MAKEFUNC(SHCreateShellItemArrayFromIDLists);
     MAKEFUNC(SHCreateShellItemArrayFromDataObject);
     MAKEFUNC(SHCreateShellItemArrayFromShellItem);
     MAKEFUNC(SHGetFolderPathA);
@@ -533,12 +535,13 @@ if (0)
 
     IShellFolder_Release(psfSystemDir);
 
-    GetCurrentDirectoryA(MAX_PATH, buf);
-    if(!lstrlenA(buf))
+    cChars = GetCurrentDirectoryA(MAX_PATH, buf);
+    if(!cChars)
     {
         skip("Failed to get current directory, skipping tests.\n");
         return;
     }
+    if(buf[cChars-1] != '\\') lstrcatA(buf, "\\");
 
     SHGetDesktopFolder(&psfDesktop);
 
@@ -546,7 +549,6 @@ if (0)
 
     /* .html */
     lstrcpyA(pathA, buf);
-    lstrcatA(pathA, "\\");
     lstrcatA(pathA, filename_html);
     hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
     if(hfile != INVALID_HANDLE_VALUE)
@@ -590,7 +592,6 @@ if (0)
 
     /* .txt */
     lstrcpyA(pathA, buf);
-    lstrcatA(pathA, "\\");
     lstrcatA(pathA, filename_txt);
     hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
     if(hfile != INVALID_HANDLE_VALUE)
@@ -604,6 +605,7 @@ if (0)
             hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
             ok(hr == E_FAIL || /* Vista+ */
                hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || /* XP, W2K3 */
+               hr == E_INVALIDARG || /* W2K item in top dir */
                broken(hr == S_OK), /* Win9x, NT4, W2K */
                "Got 0x%08x\n", hr);
             if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
@@ -616,7 +618,6 @@ if (0)
 
     /* .foo */
     lstrcpyA(pathA, buf);
-    lstrcatA(pathA, "\\");
     lstrcatA(pathA, filename_foo);
     hfile = CreateFileA(pathA, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
     if(hfile != INVALID_HANDLE_VALUE)
@@ -630,6 +631,7 @@ if (0)
             hr = IShellFolder_BindToObject(psfDesktop, pidl, NULL, &IID_IShellFolder, (void**)&psfChild);
             ok(hr == E_FAIL || /* Vista+ */
                hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) || /* XP, W2K3 */
+               hr == E_INVALIDARG || /* W2K item in top dir */
                broken(hr == S_OK), /* Win9x, NT4, W2K */
                "Got 0x%08x\n", hr);
             if(SUCCEEDED(hr)) IShellFolder_Release(psfChild);
@@ -779,7 +781,8 @@ static void test_GetDisplayName(void)
     if (pidlLast->mkid.cb >= 76) {
         ok(!lstrcmpW((WCHAR*)&pidlLast->mkid.abID[46], wszFileName) ||
             (pidlLast->mkid.cb >= 94 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[64], wszFileName)) ||  /* Vista */
-            (pidlLast->mkid.cb >= 98 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[68], wszFileName)), /* Win7 */
+            (pidlLast->mkid.cb >= 98 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[68], wszFileName)) ||  /* Win7 */
+            (pidlLast->mkid.cb >= 102 && !lstrcmpW((WCHAR*)&pidlLast->mkid.abID[72], wszFileName)),   /* Win8 */
             "Filename should be stored as wchar-string at this position!\n");
     }
     
@@ -1853,8 +1856,9 @@ static void test_ITEMIDLIST_format(void) {
                 }
 
                 ok (!lstrcmpW(wszFile[i], name) ||
-                    !lstrcmpW(wszFile[i], name + 9) || /* Vista */
-                    !lstrcmpW(wszFile[i], name + 11), /* Win7 */
+                    !lstrcmpW(wszFile[i], name + 9)  || /* Vista */
+                    !lstrcmpW(wszFile[i], name + 11) || /* Win7 */
+                    !lstrcmpW(wszFile[i], name + 13),   /* Win8 */
                     "The filename should be stored in unicode at this position!\n");
             }
         }
@@ -2199,7 +2203,7 @@ static void test_SHCreateShellItem(void)
         return;
     }
 
-    if (!lstrlenA(curdirA))
+    if (!curdirA[0])
     {
         win_skip("GetCurrentDirectoryA returned empty string, skipping test_SHCreateShellItem\n");
         return;
@@ -2234,8 +2238,10 @@ static void test_SHCreateShellItem(void)
 
     pidl_abstestfile = pILCombine(pidl_cwd, pidl_testfile);
 
+    shellitem = (void*)0xdeadbeef;
     ret = pSHCreateShellItem(NULL, NULL, NULL, &shellitem);
     ok(ret == E_INVALIDARG, "SHCreateShellItem returned %x\n", ret);
+    ok(shellitem == 0, "Got %p\n", shellitem);
 
     if (0) /* crashes on Windows XP */
     {
@@ -2774,7 +2780,7 @@ static void test_ShellItemCompare(void)
     }
 
     GetCurrentDirectoryW(MAX_PATH, curdirW);
-    if(!lstrlenW(curdirW))
+    if (!curdirW[0])
     {
         skip("Failed to get current directory, skipping.\n");
         return;
@@ -3538,11 +3544,344 @@ static void test_SHCreateShellItemArray(void)
     else
         skip("No SHCreateShellItemArrayFromDataObject.\n");
 
+    if(pSHCreateShellItemArrayFromIDLists)
+    {
+        WCHAR test1W[] = {'t','e','s','t','1','.','t','x','t',0};
+        WCHAR test1pathW[MAX_PATH];
+        LPITEMIDLIST pidltest1;
+        LPCITEMIDLIST pidl_array[2];
+
+        if(0)
+        {
+            /* Crashes */
+            hr = pSHCreateShellItemArrayFromIDLists(0, NULL, NULL);
+        }
+
+        psia = (void*)0xdeadbeef;
+        hr = pSHCreateShellItemArrayFromIDLists(0, NULL, &psia);
+        ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr);
+        ok(psia == NULL, "Got %p\n", psia);
+
+        psia = (void*)0xdeadbeef;
+        hr = pSHCreateShellItemArrayFromIDLists(0, pidl_array, &psia);
+        ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr);
+        ok(psia == NULL, "Got %p\n", psia);
+
+        psia = (void*)0xdeadbeef;
+        pidl_array[0] = NULL;
+        hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia);
+        todo_wine ok(hr == E_OUTOFMEMORY, "Got 0x%08x\n", hr);
+        ok(psia == NULL, "Got %p\n", psia);
+
+        psia = (void*)0xdeadbeef;
+        pidl_array[0] = pidl_testdir;
+        pidl_array[1] = NULL;
+        hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia);
+        todo_wine ok(hr == S_OK || broken(hr == E_INVALIDARG) /* Vista */, "Got 0x%08x\n", hr);
+        todo_wine ok(psia != NULL || broken(psia == NULL) /* Vista */, "Got %p\n", psia);
+        if(SUCCEEDED(hr))
+        {
+            IShellItem *psi;
+            UINT count = 0;
+
+            hr = IShellItemArray_GetCount(psia, &count);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(count == 2, "Got %d\n", count);
+
+            hr = IShellItemArray_GetItemAt(psia, 0, &psi);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            if(SUCCEEDED(hr))
+            {
+                LPWSTR path;
+                hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path));
+                if(SUCCEEDED(hr))
+                    CoTaskMemFree(path);
+
+                IShellItem_Release(psi);
+            }
+
+            hr = IShellItemArray_GetItemAt(psia, 1, &psi);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            if(SUCCEEDED(hr))
+            {
+                LPWSTR path;
+                WCHAR desktoppath[MAX_PATH];
+                BOOL result;
+
+                result = pSHGetSpecialFolderPathW(NULL, desktoppath, CSIDL_DESKTOPDIRECTORY, FALSE);
+                ok(result, "SHGetSpecialFolderPathW(CSIDL_DESKTOPDIRECTORY) failed! %u\n", GetLastError());
+
+                hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                ok(!lstrcmpW(path, desktoppath), "Got %s\n", wine_dbgstr_w(path));
+                if(SUCCEEDED(hr))
+                    CoTaskMemFree(path);
+
+                IShellItem_Release(psi);
+            }
+
+
+            IShellItemArray_Release(psia);
+        }
+
+
+        /* Single pidl */
+        psia = (void*)0xdeadbeef;
+        pidl_array[0] = pidl_testdir;
+        hr = pSHCreateShellItemArrayFromIDLists(1, pidl_array, &psia);
+        ok(hr == S_OK, "Got 0x%08x\n", hr);
+        if(SUCCEEDED(hr))
+        {
+            IShellItem *psi;
+            UINT count = 0;
+
+            hr = IShellItemArray_GetCount(psia, &count);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(count == 1, "Got %d\n", count);
+
+            hr = IShellItemArray_GetItemAt(psia, 0, &psi);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            if(SUCCEEDED(hr))
+            {
+                LPWSTR path;
+                hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path));
+                if(SUCCEEDED(hr))
+                    CoTaskMemFree(path);
+
+                IShellItem_Release(psi);
+            }
+
+            IShellItemArray_Release(psia);
+        }
+
+
+        lstrcpyW(test1pathW, cTestDirW);
+        myPathAddBackslashW(test1pathW);
+        lstrcatW(test1pathW, test1W);
+
+        SHGetDesktopFolder(&pdesktopsf);
+
+        hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, test1pathW, NULL, &pidltest1, NULL);
+        ok(hr == S_OK, "Got 0x%08x\n", hr);
+        if(SUCCEEDED(hr))
+        {
+            psia = (void*)0xdeadbeef;
+            pidl_array[0] = pidl_testdir;
+            pidl_array[1] = pidltest1;
+            hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            if(SUCCEEDED(hr))
+            {
+                IShellItem *psi;
+                UINT count = 0;
+
+                hr = IShellItemArray_GetCount(psia, &count);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                ok(count == 2, "Got %d\n", count);
+
+                hr = IShellItemArray_GetItemAt(psia, 0, &psi);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                if(SUCCEEDED(hr))
+                {
+                    LPWSTR path;
+                    hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    ok(!lstrcmpW(path, cTestDirW), "Got %s\n", wine_dbgstr_w(path));
+                    if(SUCCEEDED(hr))
+                        CoTaskMemFree(path);
+
+                    IShellItem_Release(psi);
+                }
+
+                hr = IShellItemArray_GetItemAt(psia, 1, &psi);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                if(SUCCEEDED(hr))
+                {
+                    LPWSTR path;
+                    hr = IShellItem_GetDisplayName(psi, SIGDN_DESKTOPABSOLUTEPARSING, &path);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    ok(!lstrcmpW(path, test1pathW), "Got %s\n", wine_dbgstr_w(path));
+                    if(SUCCEEDED(hr))
+                        CoTaskMemFree(path);
+
+                    IShellItem_Release(psi);
+                }
+
+
+                IShellItemArray_Release(psia);
+            }
+
+            pILFree(pidltest1);
+        }
+
+        IShellFolder_Release(pdesktopsf);
+    }
+    else
+        skip("No SHCreateShellItemArrayFromIDLists.\n");
+
     IShellFolder_Release(psf);
     pILFree(pidl_testdir);
     Cleanup();
 }
 
+static void test_ShellItemArrayEnumItems(void)
+{
+    IShellFolder *pdesktopsf, *psf;
+    IEnumIDList *peidl;
+    WCHAR cTestDirW[MAX_PATH];
+    HRESULT hr;
+    LPITEMIDLIST pidl_testdir;
+    static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0};
+
+    if(!pSHCreateShellItemArray)
+    {
+        win_skip("No SHCreateShellItemArray, skipping test...\n");
+        return;
+    }
+
+    CreateFilesFolders();
+
+    SHGetDesktopFolder(&pdesktopsf);
+
+    GetCurrentDirectoryW(MAX_PATH, cTestDirW);
+    myPathAddBackslashW(cTestDirW);
+    lstrcatW(cTestDirW, testdirW);
+
+    hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, cTestDirW, NULL, &pidl_testdir, 0);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    if(SUCCEEDED(hr))
+    {
+        hr = IShellFolder_BindToObject(pdesktopsf, pidl_testdir, NULL, (REFIID)&IID_IShellFolder,
+                                       (void**)&psf);
+        ok(hr == S_OK, "Got 0x%08x\n", hr);
+        if(SUCCEEDED(hr))
+            pILFree(pidl_testdir);
+    }
+    IShellFolder_Release(pdesktopsf);
+
+    hr = IShellFolder_EnumObjects(psf, NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &peidl);
+    ok(hr == S_OK, "Got %08x\n", hr);
+    if(SUCCEEDED(hr))
+    {
+        IShellItemArray *psia;
+        LPITEMIDLIST apidl[5];
+        UINT done, numitems, i;
+
+        for(done = 0; done < 5; done++)
+            if(IEnumIDList_Next(peidl, 1, &apidl[done], NULL) != S_OK)
+                break;
+        ok(done == 5, "Got %d pidls\n", done);
+        IEnumIDList_Release(peidl);
+
+        /* Create a ShellItemArray */
+        hr = pSHCreateShellItemArray(NULL, psf, done, (LPCITEMIDLIST*)apidl, &psia);
+        ok(hr == S_OK, "Got 0x%08x\n", hr);
+        if(SUCCEEDED(hr))
+        {
+            IEnumShellItems *iesi;
+            IShellItem *my_array[10];
+            ULONG fetched;
+
+            IShellItemArray_GetCount(psia, &numitems);
+            ok(numitems == done, "Got %d, expected %d\n", numitems, done);
+
+            iesi = NULL;
+            hr = IShellItemArray_EnumItems(psia, &iesi);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(iesi != NULL, "Got NULL\n");
+            if(SUCCEEDED(hr))
+            {
+                IEnumShellItems *iesi2;
+
+                /* This should fail according to the documentation and Win7+ */
+                for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef;
+                hr = IEnumShellItems_Next(iesi, 2, my_array, NULL);
+                ok(hr == E_INVALIDARG || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr);
+                for(i = 0; i < 2; i++)
+                {
+                    ok(my_array[i] == (void*)0xdeadbeef ||
+                       broken(my_array[i] != (void*)0xdeadbeef && my_array[i] != NULL), /* Vista */
+                       "Got %p (%d)\n", my_array[i], i);
+
+                    if(my_array[i] != (void*)0xdeadbeef)
+                        IShellItem_Release(my_array[i]);
+                }
+                ok(my_array[2] == (void*)0xdeadbeef, "Got %p\n", my_array[2]);
+
+                IEnumShellItems_Reset(iesi);
+                for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef;
+                hr = IEnumShellItems_Next(iesi, 1, my_array, NULL);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                ok(my_array[0] != NULL && my_array[0] != (void*)0xdeadbeef, "Got %p\n", my_array[0]);
+                if(my_array[0] != NULL && my_array[0] != (void*)0xdeadbeef)
+                    IShellItem_Release(my_array[0]);
+                ok(my_array[1] == (void*)0xdeadbeef, "Got %p\n", my_array[1]);
+
+                IEnumShellItems_Reset(iesi);
+                fetched = 0;
+                for(i = 0; i < 10; i++) my_array[i] = (void*)0xdeadbeef;
+                hr = IEnumShellItems_Next(iesi, numitems, my_array, &fetched);
+                ok(hr == S_OK, "Got 0x%08x\n", hr);
+                ok(fetched == numitems, "Got %d\n", fetched);
+                for(i = 0;i < numitems; i++)
+                {
+                    ok(my_array[i] != NULL && my_array[i] != (void*)0xdeadbeef,
+                       "Got %p at %d\n", my_array[i], i);
+
+                    if(my_array[i] != NULL && my_array[i] != (void*)0xdeadbeef)
+                        IShellItem_Release(my_array[i]);
+                }
+                ok(my_array[i] == (void*)0xdeadbeef, "Got %p\n", my_array[i]);
+
+                /* Compare all the items */
+                IEnumShellItems_Reset(iesi);
+                for(i = 0; i < numitems; i++)
+                {
+                    IShellItem *psi;
+                    int order;
+
+                    hr = IShellItemArray_GetItemAt(psia, i, &psi);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    hr = IEnumShellItems_Next(iesi, 1, my_array, &fetched);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    ok(fetched == 1, "Got %d\n", fetched);
+
+                    hr = IShellItem_Compare(psi, my_array[0], 0, &order);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    ok(order == 0, "Got %d\n", order);
+
+                    IShellItem_Release(psi);
+                    IShellItem_Release(my_array[0]);
+                }
+
+                my_array[0] = (void*)0xdeadbeef;
+                hr = IEnumShellItems_Next(iesi, 1, my_array, &fetched);
+                ok(hr == S_FALSE, "Got 0x%08x\n", hr);
+                ok(fetched == 0, "Got %d\n", fetched);
+                ok(my_array[0] == (void*)0xdeadbeef, "Got %p\n", my_array[0]);
+
+                /* Cloning not implemented anywhere */
+                iesi2 = (void*)0xdeadbeef;
+                hr = IEnumShellItems_Clone(iesi, &iesi2);
+                ok(hr == E_NOTIMPL, "Got 0x%08x\n", hr);
+                ok(iesi2 == NULL || broken(iesi2 == (void*)0xdeadbeef) /* Vista */, "Got %p\n", iesi2);
+
+                IEnumShellItems_Release(iesi);
+            }
+
+            IShellItemArray_Release(psia);
+        }
+
+        for(i = 0; i < done; i++)
+            pILFree(apidl[i]);
+    }
+}
+
+
 static void test_ShellItemBindToHandler(void)
 {
     IShellItem *psi;
@@ -3640,8 +3979,8 @@ static void test_ShellItemBindToHandler(void)
             if(SUCCEEDED(hr)) IUnknown_Release(punk);
 
             /* BHID_Transfer
-               ITransferSource and ITransferDestination are accessible starting Vista, IUnknown is
-               supported start Win8. */
+               ITransferSource and ITransferDestination are accessible starting from Vista, IUnknown is
+               supported starting from Win8. */
             hr = IShellItem_BindToHandler(psi, NULL, &BHID_Transfer, &IID_ITransferSource, (void**)&punk);
             ok(hr == S_OK || broken(FAILED(hr)) /* pre-Vista */, "Got 0x%08x\n", hr);
             if(SUCCEEDED(hr))
@@ -3709,10 +4048,15 @@ static void test_ShellItemBindToHandler(void)
 
 static void test_ShellItemGetAttributes(void)
 {
-    IShellItem *psi;
-    LPITEMIDLIST pidl_desktop;
+    IShellItem *psi, *psi_folder1, *psi_file1;
+    IShellFolder *pdesktopsf;
+    LPITEMIDLIST pidl_desktop, pidl;
     SFGAOF sfgao;
     HRESULT hr;
+    WCHAR curdirW[MAX_PATH];
+    WCHAR buf[MAX_PATH];
+    static const WCHAR testdir1W[] = {'t','e','s','t','d','i','r',0};
+    static const WCHAR testfile1W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
 
     if(!pSHCreateShellItem)
     {
@@ -3747,6 +4091,148 @@ static void test_ShellItemGetAttributes(void)
     ok(sfgao == SFGAO_FOLDER || broken(sfgao == 0) /* <Vista */, "Got 0x%08x\n", sfgao);
 
     IShellItem_Release(psi);
+
+    CreateFilesFolders();
+
+    SHGetDesktopFolder(&pdesktopsf);
+
+    GetCurrentDirectoryW(MAX_PATH, curdirW);
+    myPathAddBackslashW(curdirW);
+
+    lstrcpyW(buf, curdirW);
+    lstrcatW(buf, testdir1W);
+    hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, &pidl, NULL);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = pSHCreateShellItem(NULL, NULL, pidl, &psi_folder1);
+    ok(hr == S_OK, "Got 0x%08x\n", sfgao);
+    pILFree(pidl);
+
+    lstrcpyW(buf, curdirW);
+    lstrcatW(buf, testfile1W);
+    hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, &pidl, NULL);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = pSHCreateShellItem(NULL, NULL, pidl, &psi_file1);
+    ok(hr == S_OK, "Got 0x%08x\n", sfgao);
+    pILFree(pidl);
+
+    IShellFolder_Release(pdesktopsf);
+
+    sfgao = 0xdeadbeef;
+    hr = IShellItem_GetAttributes(psi_folder1, 0, &sfgao);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    ok(sfgao == 0, "Got 0x%08x\n", sfgao);
+
+    sfgao = 0xdeadbeef;
+    hr = IShellItem_GetAttributes(psi_folder1, SFGAO_FOLDER, &sfgao);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    ok(sfgao == SFGAO_FOLDER, "Got 0x%08x\n", sfgao);
+
+    sfgao = 0xdeadbeef;
+    hr = IShellItem_GetAttributes(psi_file1, SFGAO_FOLDER, &sfgao);
+    ok(hr == S_FALSE, "Got 0x%08x\n", hr);
+    ok(sfgao == 0, "Got 0x%08x\n", sfgao);
+
+    IShellItem_Release(psi_folder1);
+    IShellItem_Release(psi_file1);
+
+    Cleanup();
+}
+
+static void test_ShellItemArrayGetAttributes(void)
+{
+    IShellItemArray *psia_files, *psia_folders1, *psia_folders2, *psia_all;
+    IShellFolder *pdesktopsf;
+    LPCITEMIDLIST pidl_array[5];
+    SFGAOF attr;
+    HRESULT hr;
+    WCHAR curdirW[MAX_PATH];
+    WCHAR buf[MAX_PATH];
+    UINT i;
+    static const WCHAR testdir1W[] = {'t','e','s','t','d','i','r',0};
+    static const WCHAR testdir2W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
+    static const WCHAR testdir3W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','3',0};
+    static const WCHAR testfile1W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
+    static const WCHAR testfile2W[] = {'t','e','s','t','d','i','r','\\','t','e','s','t','2','.','t','x','t',0};
+    static const WCHAR *testfilesW[5] = { testdir1W, testdir2W, testdir3W, testfile1W, testfile2W };
+
+    if(!pSHCreateShellItemArrayFromShellItem)
+    {
+        win_skip("No SHCreateShellItemArrayFromShellItem, skipping test...\n");
+        return;
+    }
+
+    CreateFilesFolders();
+    CreateDirectoryA(".\\testdir\\testdir3", NULL);
+
+    SHGetDesktopFolder(&pdesktopsf);
+
+    GetCurrentDirectoryW(MAX_PATH, curdirW);
+    myPathAddBackslashW(curdirW);
+
+    for(i = 0; i < 5; i++)
+    {
+        lstrcpyW(buf, curdirW);
+        lstrcatW(buf, testfilesW[i]);
+        hr = IShellFolder_ParseDisplayName(pdesktopsf, NULL, NULL, buf, NULL, (LPITEMIDLIST*)&pidl_array[i], NULL);
+        ok(hr == S_OK, "got 0x%08x\n", hr);
+    }
+    IShellFolder_Release(pdesktopsf);
+
+    hr = pSHCreateShellItemArrayFromIDLists(2, pidl_array, &psia_folders1);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = pSHCreateShellItemArrayFromIDLists(2, &pidl_array[1], &psia_folders2);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = pSHCreateShellItemArrayFromIDLists(2, &pidl_array[3], &psia_files);
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+    hr = pSHCreateShellItemArrayFromIDLists(4, &pidl_array[1], &psia_all); /* All except the first */
+    ok(hr == S_OK, "got 0x%08x\n", hr);
+
+    for(i = 0; i < 5; i++)
+        pILFree((LPITEMIDLIST)pidl_array[i]);
+
+    /* [testfolder/, testfolder/testfolder2] seems to break in Vista */
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_folders1, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
+    ok(hr == S_OK || broken(hr == E_UNEXPECTED)  /* Vista */, "Got 0x%08x\n", hr);
+    ok(attr == SFGAO_FOLDER || broken(attr == 0) /* Vista */, "Got 0x%08x\n", attr);
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_folders1, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
+    ok(hr == S_OK || broken(hr == E_UNEXPECTED)  /* Vista */, "Got 0x%08x\n", hr);
+    ok(attr == SFGAO_FOLDER || broken(attr == 0) /* Vista */, "Got 0x%08x\n", attr);
+
+    /* [testfolder/testfolder2, testfolder/testfolder3] works */
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_folders2, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    ok(attr == SFGAO_FOLDER, "Got 0x%08x\n", attr);
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_files, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr);
+    ok(attr == 0, "Got 0x%08x\n", attr);
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_all, SIATTRIBFLAGS_AND, SFGAO_FOLDER, &attr);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr);
+    ok(attr == 0, "Got 0x%08x\n", attr);
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_folders2, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    ok(attr == SFGAO_FOLDER, "Got 0x%08x\n", attr);
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_files, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
+    ok(hr == S_FALSE || broken(hr == S_OK) /* Vista */, "Got 0x%08x\n", hr);
+    ok(attr == 0, "Got 0x%08x\n", attr);
+    attr = 0xdeadbeef;
+    hr = IShellItemArray_GetAttributes(psia_all, SIATTRIBFLAGS_OR, SFGAO_FOLDER, &attr);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    ok(attr == SFGAO_FOLDER, "Got 0x%08x\n", attr);
+
+    IShellItemArray_Release(psia_folders1);
+    IShellItemArray_Release(psia_folders2);
+    IShellItemArray_Release(psia_files);
+    IShellItemArray_Release(psia_all);
+
+    RemoveDirectoryA(".\\testdir\\testdir3");
+    Cleanup();
 }
 
 static void test_SHParseDisplayName(void)
@@ -3901,7 +4387,7 @@ static void test_GetUIObject(void)
     }
 
     GetCurrentDirectoryW(MAX_PATH, path);
-    if(!lstrlenW(path))
+    if (!path[0])
     {
         skip("GetCurrentDirectoryW returned an empty string.\n");
         return;
@@ -3969,7 +4455,8 @@ static void test_GetUIObject(void)
                 }
                 max_id_check -= baseItem;
                 ok((max_id_check == max_id) ||
-                   (max_id_check == max_id-1 /* Win 7 */),
+                   (max_id_check == max_id-1) || /* Win 7 */
+                   (max_id_check == max_id-2),   /* Win 8 */
                    "Not equal (or near equal), got %d and %d\n", max_id_check, max_id);
 
 #define is_win2k() (pSHGetFolderPathA && !pSHGetFolderPathAndSubDirA)
@@ -4502,8 +4989,8 @@ static void test_SHChangeNotify(BOOL test_new_delivery)
 
         exp_data->missing_events = exp_data->notify_count;
         SHChangeNotify(exp_data->signal, SHCNF_PATHA | SHCNF_FLUSH,
-                strlen(exp_data->path_1) > 0 ? exp_data->path_1 : NULL,
-                strlen(exp_data->path_2) > 0 ? exp_data->path_2 : NULL);
+                exp_data->path_1[0] ? exp_data->path_1 : NULL,
+                exp_data->path_2[0] ? exp_data->path_2 : NULL);
         do_events();
         ok(exp_data->missing_events == 0, "%s: Expected wndproc to be called\n", exp_data->id);
 
@@ -4558,7 +5045,7 @@ static void test_SHCreateDefaultContextMenu(void)
     }
 
     GetCurrentDirectoryW(MAX_PATH, path);
-    if(!lstrlenW(path))
+    if (!path[0])
     {
         skip("GetCurrentDirectoryW returned an empty string.\n");
         return;
@@ -4757,6 +5244,7 @@ START_TEST(shlfolder)
     test_LocalizedNames();
     test_SHCreateShellItem();
     test_SHCreateShellItemArray();
+    test_ShellItemArrayEnumItems();
     test_desktop_IPersist();
     test_GetUIObject();
     test_SHSimpleIDListFromPath();
@@ -4770,6 +5258,7 @@ START_TEST(shlfolder)
     test_SHChangeNotify(TRUE);
     test_ShellItemBindToHandler();
     test_ShellItemGetAttributes();
+    test_ShellItemArrayGetAttributes();
     test_SHCreateDefaultContextMenu();
     test_SHCreateShellFolderView();
     test_SHCreateShellFolderViewEx();
index 554e086..b9d07de 100644 (file)
@@ -485,11 +485,6 @@ static const struct message folderview_getfocused_seq[] = {
     { 0 }
 };
 
-static const struct message folderview_itemcount_seq[] = {
-    { LVM_GETITEMCOUNT, sent },
-    { 0 }
-};
-
 static void test_IShellView_CreateViewWindow(void)
 {
     IShellFolder *desktop;