|  | /* | 
|  | * Unit tests for IShellDispatch | 
|  | * | 
|  | * Copyright 2010 Alexander Morozov for Etersoft | 
|  | * | 
|  | * This library is free software; you can redistribute it and/or | 
|  | * modify it under the terms of the GNU Lesser General Public | 
|  | * License as published by the Free Software Foundation; either | 
|  | * version 2.1 of the License, or (at your option) any later version. | 
|  | * | 
|  | * This library is distributed in the hope that it will be useful, | 
|  | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|  | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU | 
|  | * Lesser General Public License for more details. | 
|  | * | 
|  | * You should have received a copy of the GNU Lesser General Public | 
|  | * License along with this library; if not, write to the Free Software | 
|  | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA | 
|  | */ | 
|  |  | 
|  | #define COBJMACROS | 
|  | #define NONAMELESSUNION | 
|  | #define NONAMELESSSTRUCT | 
|  |  | 
|  | #include "shldisp.h" | 
|  | #include "shlobj.h" | 
|  | #include "shlwapi.h" | 
|  | #include "wine/test.h" | 
|  |  | 
|  | static HRESULT (WINAPI *pSHGetFolderPathW)(HWND, int, HANDLE, DWORD, LPWSTR); | 
|  | static HRESULT (WINAPI *pSHGetNameFromIDList)(PCIDLIST_ABSOLUTE,SIGDN,PWSTR*); | 
|  | static HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *); | 
|  | static DWORD (WINAPI *pGetLongPathNameW)(LPCWSTR, LPWSTR, DWORD); | 
|  |  | 
|  | static void init_function_pointers(void) | 
|  | { | 
|  | HMODULE hshell32, hkernel32; | 
|  |  | 
|  | hshell32 = GetModuleHandleA("shell32.dll"); | 
|  | hkernel32 = GetModuleHandleA("kernel32.dll"); | 
|  | pSHGetFolderPathW = (void*)GetProcAddress(hshell32, "SHGetFolderPathW"); | 
|  | pSHGetNameFromIDList = (void*)GetProcAddress(hshell32, "SHGetNameFromIDList"); | 
|  | pSHGetSpecialFolderLocation = (void*)GetProcAddress(hshell32, | 
|  | "SHGetSpecialFolderLocation"); | 
|  | pGetLongPathNameW = (void*)GetProcAddress(hkernel32, "GetLongPathNameW"); | 
|  | } | 
|  |  | 
|  | static void test_namespace(void) | 
|  | { | 
|  | static const WCHAR winetestW[] = {'w','i','n','e','t','e','s','t',0}; | 
|  | static const WCHAR backslashW[] = {'\\',0}; | 
|  | static const WCHAR clsidW[] = { | 
|  | ':',':','{','6','4','5','F','F','0','4','0','-','5','0','8','1','-', | 
|  | '1','0','1','B','-','9','F','0','8','-', | 
|  | '0','0','A','A','0','0','2','F','9','5','4','E','}',0}; | 
|  |  | 
|  | static WCHAR tempW[MAX_PATH], curW[MAX_PATH]; | 
|  | WCHAR *long_pathW = NULL; | 
|  | HRESULT r; | 
|  | IShellDispatch *sd; | 
|  | Folder *folder; | 
|  | Folder2 *folder2; | 
|  | FolderItem *item; | 
|  | VARIANT var; | 
|  | BSTR title, item_path; | 
|  | int len; | 
|  |  | 
|  | r = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, | 
|  | &IID_IShellDispatch, (LPVOID*)&sd); | 
|  | if (r == REGDB_E_CLASSNOTREG) /* NT4 */ | 
|  | { | 
|  | win_skip("skipping IShellDispatch tests\n"); | 
|  | return; | 
|  | } | 
|  | ok(SUCCEEDED(r), "CoCreateInstance failed: %08x\n", r); | 
|  | if (FAILED(r)) | 
|  | return; | 
|  |  | 
|  | VariantInit(&var); | 
|  | folder = (void*)0xdeadbeef; | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r); | 
|  | ok(folder == NULL, "expected NULL, got %p\n", folder); | 
|  |  | 
|  | V_VT(&var) = VT_I4; | 
|  | V_I4(&var) = -1; | 
|  | folder = (void*)0xdeadbeef; | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | todo_wine { | 
|  | ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r); | 
|  | ok(folder == NULL, "got %p\n", folder); | 
|  | } | 
|  | V_VT(&var) = VT_I4; | 
|  | V_I4(&var) = ssfPROGRAMFILES; | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | ok(r == S_OK || | 
|  | broken(r == S_FALSE), /* NT4 */ | 
|  | "IShellDispatch::NameSpace failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | static WCHAR path[MAX_PATH]; | 
|  |  | 
|  | if (pSHGetFolderPathW) | 
|  | { | 
|  | r = pSHGetFolderPathW(NULL, CSIDL_PROGRAM_FILES, NULL, | 
|  | SHGFP_TYPE_CURRENT, path); | 
|  | ok(r == S_OK, "SHGetFolderPath failed: %08x\n", r); | 
|  | } | 
|  | r = Folder_get_Title(folder, &title); | 
|  | todo_wine | 
|  | ok(r == S_OK, "Folder::get_Title failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | /* On Win2000-2003 title is equal to program files directory name in | 
|  | HKLM\Software\Microsoft\Windows\CurrentVersion\ProgramFilesDir. | 
|  | On newer Windows it seems constant and is not changed | 
|  | if the program files directory name is changed */ | 
|  | if (pSHGetSpecialFolderLocation && pSHGetNameFromIDList) | 
|  | { | 
|  | LPITEMIDLIST pidl; | 
|  | PWSTR name; | 
|  |  | 
|  | r = pSHGetSpecialFolderLocation(NULL, CSIDL_PROGRAM_FILES, &pidl); | 
|  | ok(r == S_OK, "SHGetSpecialFolderLocation failed: %08x\n", r); | 
|  | r = pSHGetNameFromIDList(pidl, SIGDN_NORMALDISPLAY, &name); | 
|  | ok(r == S_OK, "SHGetNameFromIDList failed: %08x\n", r); | 
|  | todo_wine | 
|  | ok(!lstrcmpW(title, name), "expected %s, got %s\n", | 
|  | wine_dbgstr_w(name), wine_dbgstr_w(title)); | 
|  | CoTaskMemFree(name); | 
|  | CoTaskMemFree(pidl); | 
|  | } | 
|  | else if (pSHGetFolderPathW) | 
|  | { | 
|  | WCHAR *p; | 
|  |  | 
|  | p = path + lstrlenW(path); | 
|  | while (path < p && *(p - 1) != '\\') | 
|  | p--; | 
|  | ok(!lstrcmpW(title, p), "expected %s, got %s\n", | 
|  | wine_dbgstr_w(p), wine_dbgstr_w(title)); | 
|  | } | 
|  | else skip("skipping Folder::get_Title test\n"); | 
|  | SysFreeString(title); | 
|  | } | 
|  | r = Folder_QueryInterface(folder, &IID_Folder2, (LPVOID*)&folder2); | 
|  | ok(r == S_OK, "Folder::QueryInterface failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder2_get_Self(folder2, &item); | 
|  | ok(r == S_OK, "Folder::get_Self failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = FolderItem_get_Path(item, &item_path); | 
|  | ok(r == S_OK, "FolderItem::get_Path failed: %08x\n", r); | 
|  | if (pSHGetFolderPathW) | 
|  | ok(!lstrcmpW(item_path, path), "expected %s, got %s\n", | 
|  | wine_dbgstr_w(path), wine_dbgstr_w(item_path)); | 
|  | SysFreeString(item_path); | 
|  | FolderItem_Release(item); | 
|  | } | 
|  | Folder2_Release(folder2); | 
|  | } | 
|  | Folder_Release(folder); | 
|  | } | 
|  |  | 
|  | V_VT(&var) = VT_I4; | 
|  | V_I4(&var) = ssfBITBUCKET; | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | ok(r == S_OK || | 
|  | broken(r == S_FALSE), /* NT4 */ | 
|  | "IShellDispatch::NameSpace failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder_QueryInterface(folder, &IID_Folder2, (LPVOID*)&folder2); | 
|  | ok(r == S_OK || | 
|  | broken(r == E_NOINTERFACE), /* NT4 */ | 
|  | "Folder::QueryInterface failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder2_get_Self(folder2, &item); | 
|  | ok(r == S_OK, "Folder::get_Self failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = FolderItem_get_Path(item, &item_path); | 
|  | todo_wine | 
|  | ok(r == S_OK, "FolderItem::get_Path failed: %08x\n", r); | 
|  | todo_wine | 
|  | ok(!lstrcmpW(item_path, clsidW), "expected %s, got %s\n", | 
|  | wine_dbgstr_w(clsidW), wine_dbgstr_w(item_path)); | 
|  | SysFreeString(item_path); | 
|  | FolderItem_Release(item); | 
|  | } | 
|  | Folder2_Release(folder2); | 
|  | } | 
|  | Folder_Release(folder); | 
|  | } | 
|  |  | 
|  | GetTempPathW(MAX_PATH, tempW); | 
|  | GetCurrentDirectoryW(MAX_PATH, curW); | 
|  | SetCurrentDirectoryW(tempW); | 
|  | CreateDirectoryW(winetestW, NULL); | 
|  | V_VT(&var) = VT_BSTR; | 
|  | V_BSTR(&var) = SysAllocString(winetestW); | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | ok(r == S_FALSE, "expected S_FALSE, got %08x\n", r); | 
|  | SysFreeString(V_BSTR(&var)); | 
|  |  | 
|  | GetFullPathNameW(winetestW, MAX_PATH, tempW, NULL); | 
|  | if (pGetLongPathNameW) | 
|  | { | 
|  | len = pGetLongPathNameW(tempW, NULL, 0); | 
|  | long_pathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR)); | 
|  | if (long_pathW) | 
|  | pGetLongPathNameW(tempW, long_pathW, len); | 
|  | } | 
|  | V_VT(&var) = VT_BSTR; | 
|  | V_BSTR(&var) = SysAllocString(tempW); | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | ok(r == S_OK, "IShellDispatch::NameSpace failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder_get_Title(folder, &title); | 
|  | ok(r == S_OK, "Folder::get_Title failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | ok(!lstrcmpW(title, winetestW), "bad title: %s\n", | 
|  | wine_dbgstr_w(title)); | 
|  | SysFreeString(title); | 
|  | } | 
|  | r = Folder_QueryInterface(folder, &IID_Folder2, (LPVOID*)&folder2); | 
|  | ok(r == S_OK || | 
|  | broken(r == E_NOINTERFACE), /* NT4 */ | 
|  | "Folder::QueryInterface failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder2_get_Self(folder2, &item); | 
|  | ok(r == S_OK, "Folder::get_Self failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = FolderItem_get_Path(item, &item_path); | 
|  | ok(r == S_OK, "FolderItem::get_Path failed: %08x\n", r); | 
|  | if (long_pathW) | 
|  | ok(!lstrcmpW(item_path, long_pathW), | 
|  | "expected %s, got %s\n", wine_dbgstr_w(long_pathW), | 
|  | wine_dbgstr_w(item_path)); | 
|  | SysFreeString(item_path); | 
|  | FolderItem_Release(item); | 
|  | } | 
|  | Folder2_Release(folder2); | 
|  | } | 
|  | Folder_Release(folder); | 
|  | } | 
|  | SysFreeString(V_BSTR(&var)); | 
|  |  | 
|  | len = lstrlenW(tempW); | 
|  | if (len < MAX_PATH - 1) | 
|  | { | 
|  | lstrcatW(tempW, backslashW); | 
|  | V_VT(&var) = VT_BSTR; | 
|  | V_BSTR(&var) = SysAllocString(tempW); | 
|  | r = IShellDispatch_NameSpace(sd, var, &folder); | 
|  | ok(r == S_OK, "IShellDispatch::NameSpace failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder_get_Title(folder, &title); | 
|  | ok(r == S_OK, "Folder::get_Title failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | ok(!lstrcmpW(title, winetestW), "bad title: %s\n", | 
|  | wine_dbgstr_w(title)); | 
|  | SysFreeString(title); | 
|  | } | 
|  | r = Folder_QueryInterface(folder, &IID_Folder2, (LPVOID*)&folder2); | 
|  | ok(r == S_OK || | 
|  | broken(r == E_NOINTERFACE), /* NT4 */ | 
|  | "Folder::QueryInterface failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = Folder2_get_Self(folder2, &item); | 
|  | ok(r == S_OK, "Folder::get_Self failed: %08x\n", r); | 
|  | if (r == S_OK) | 
|  | { | 
|  | r = FolderItem_get_Path(item, &item_path); | 
|  | ok(r == S_OK, "FolderItem::get_Path failed: %08x\n", r); | 
|  | if (long_pathW) | 
|  | ok(!lstrcmpW(item_path, long_pathW), | 
|  | "expected %s, got %s\n", wine_dbgstr_w(long_pathW), | 
|  | wine_dbgstr_w(item_path)); | 
|  | SysFreeString(item_path); | 
|  | FolderItem_Release(item); | 
|  | } | 
|  | Folder2_Release(folder2); | 
|  | } | 
|  | Folder_Release(folder); | 
|  | } | 
|  | SysFreeString(V_BSTR(&var)); | 
|  | } | 
|  |  | 
|  | HeapFree(GetProcessHeap(), 0, long_pathW); | 
|  | RemoveDirectoryW(winetestW); | 
|  | SetCurrentDirectoryW(curW); | 
|  | IShellDispatch_Release(sd); | 
|  | } | 
|  |  | 
|  | START_TEST(shelldispatch) | 
|  | { | 
|  | HRESULT r; | 
|  |  | 
|  | r = CoInitialize(NULL); | 
|  | ok(SUCCEEDED(r), "CoInitialize failed: %08x\n", r); | 
|  | if (FAILED(r)) | 
|  | return; | 
|  |  | 
|  | init_function_pointers(); | 
|  | test_namespace(); | 
|  |  | 
|  | CoUninitialize(); | 
|  | } |