[SHELL32_WINETEST]

* Sync to Wine 1.3.29.

svn path=/trunk/; revision=53821
This commit is contained in:
Amine Khaldi 2011-09-23 23:14:50 +00:00
parent 3ed568c40d
commit b1df00f897
19 changed files with 8076 additions and 151 deletions

View file

@ -8,10 +8,16 @@ add_definitions(
list(APPEND SOURCE
appbar.c
autocomplete.c
brsfolder.c
ebrowser.c
generated.c
progman_dde.c
recyclebin.c
shelldispatch.c
shelllink.c
shellole.c
shellpath.c
shfldr_special.c
shlexec.c
shlfileop.c
shlfolder.c
@ -19,11 +25,10 @@ list(APPEND SOURCE
string.c
systray.c
testlist.c
shfldr_special.c
rsrc.rc)
add_executable(shell32_winetest ${SOURCE})
target_link_libraries(shell32_winetest wine uuid)
set_module_type(shell32_winetest win32cui)
add_importlibs(shell32_winetest shlwapi gdi32 shell32 ole32 oleaut32 user32 advapi32 msvcrt kernel32 ntdll)
add_importlibs(shell32_winetest shell32 ole32 oleaut32 user32 advapi32 msvcrt kernel32 ntdll)
add_cd_file(TARGET shell32_winetest DESTINATION reactos/bin FOR all)

View file

@ -33,11 +33,115 @@ static HWND hMainWnd, hEdit;
static HINSTANCE hinst;
static int killfocus_count;
static void test_invalid_init(void)
{
HRESULT hr;
IAutoComplete *ac;
IUnknown *acSource;
HWND edit_control;
/* AutoComplete instance */
hr = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
&IID_IAutoComplete, (void **)&ac);
if (hr == REGDB_E_CLASSNOTREG)
{
win_skip("CLSID_AutoComplete is not registered\n");
return;
}
ok(hr == S_OK, "no IID_IAutoComplete (0x%08x)\n", hr);
/* AutoComplete source */
hr = CoCreateInstance(&CLSID_ACLMulti, NULL, CLSCTX_INPROC_SERVER,
&IID_IACList, (void **)&acSource);
if (hr == REGDB_E_CLASSNOTREG)
{
win_skip("CLSID_ACLMulti is not registered\n");
IAutoComplete_Release(ac);
return;
}
ok(hr == S_OK, "no IID_IACList (0x%08x)\n", hr);
edit_control = CreateWindowExA(0, "EDIT", "Some text", 0, 10, 10, 300, 300,
hMainWnd, NULL, hinst, NULL);
ok(edit_control != NULL, "Can't create edit control\n");
/* The refcount of acSource would be incremented on older Windows. */
hr = IAutoComplete_Init(ac, NULL, acSource, NULL, NULL);
ok(hr == E_INVALIDARG ||
broken(hr == S_OK), /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
if (hr == E_INVALIDARG)
{
LONG ref;
IUnknown_AddRef(acSource);
ref = IUnknown_Release(acSource);
ok(ref == 1, "Expected AutoComplete source refcount to be 1, got %d\n", ref);
}
if (0)
{
/* Older Windows versions never check the window handle, while newer
* versions only check for NULL. Subsequent attempts to initialize the
* object after this call succeeds would fail, because initialization
* state is determined by whether a non-NULL window handle is stored. */
hr = IAutoComplete_Init(ac, (HWND)0xdeadbeef, acSource, NULL, NULL);
ok(hr == S_OK, "Init returned 0x%08x\n", hr);
/* Tests crash on older Windows. */
hr = IAutoComplete_Init(ac, NULL, NULL, NULL, NULL);
ok(hr == E_INVALIDARG, "Init returned 0x%08x\n", hr);
hr = IAutoComplete_Init(ac, edit_control, NULL, NULL, NULL);
ok(hr == E_INVALIDARG, "Init returned 0x%08x\n", hr);
}
/* bind to edit control */
hr = IAutoComplete_Init(ac, edit_control, acSource, NULL, NULL);
ok(hr == S_OK, "Init returned 0x%08x\n", hr);
/* try invalid parameters after successful initialization .*/
hr = IAutoComplete_Init(ac, NULL, NULL, NULL, NULL);
ok(hr == E_INVALIDARG ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
hr = IAutoComplete_Init(ac, NULL, acSource, NULL, NULL);
ok(hr == E_INVALIDARG ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
hr = IAutoComplete_Init(ac, edit_control, NULL, NULL, NULL);
ok(hr == E_INVALIDARG ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
/* try initializing twice on the same control */
hr = IAutoComplete_Init(ac, edit_control, acSource, NULL, NULL);
ok(hr == E_FAIL, "Init returned 0x%08x\n", hr);
/* try initializing with a different control */
hr = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
ok(hr == E_FAIL, "Init returned 0x%08x\n", hr);
DestroyWindow(edit_control);
/* try initializing with a different control after
* destroying the original initialization control */
hr = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
ok(hr == E_UNEXPECTED ||
hr == E_FAIL, /* Win2k/XP/Win2k3 */
"Init returned 0x%08x\n", hr);
IUnknown_Release(acSource);
IAutoComplete_Release(ac);
}
static IAutoComplete *test_init(void)
{
HRESULT r;
IAutoComplete* ac;
IAutoComplete *ac;
IUnknown *acSource;
LONG_PTR user_data;
/* AutoComplete instance */
r = CoCreateInstance(&CLSID_AutoComplete, NULL, CLSCTX_INPROC_SERVER,
@ -55,18 +159,20 @@ static IAutoComplete *test_init(void)
if (r == REGDB_E_CLASSNOTREG)
{
win_skip("CLSID_ACLMulti is not registered\n");
IAutoComplete_Release(ac);
return NULL;
}
ok(r == S_OK, "no IID_IACList (0x%08x)\n", r);
if (0)
{
/* crashes on native */
r = IAutoComplete_Init(ac, hEdit, NULL, NULL, NULL);
}
user_data = GetWindowLongPtrA(hEdit, GWLP_USERDATA);
ok(user_data == 0, "Expected the edit control user data to be zero\n");
/* bind to edit control */
r = IAutoComplete_Init(ac, hEdit, acSource, NULL, NULL);
ok(r == S_OK, "Init failed (0x%08x)\n", r);
ok(r == S_OK, "Init returned 0x%08x\n", r);
user_data = GetWindowLongPtrA(hEdit, GWLP_USERDATA);
ok(user_data == 0, "Expected the edit control user data to be zero\n");
IUnknown_Release(acSource);
@ -134,6 +240,7 @@ START_TEST(autocomplete)
ok(hMainWnd != NULL, "Failed to create parent window. Tests aborted.\n");
if (!hMainWnd) return;
test_invalid_init();
ac = test_init();
if (!ac)
goto cleanup;

View file

@ -0,0 +1,365 @@
/*
* Unit test of the SHBrowseForFolder function.
*
* Copyright 2009-2010 Michael Mc Donnell
* Copyright 2011 André Hentschel
*
* 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
*/
#include <windows.h>
#include <shlobj.h>
#include <shobjidl.h>
#include <string.h>
#include "wine/test.h"
#define IDD_MAKENEWFOLDER 0x3746 /* From "../shresdef.h" */
#define TIMER_WAIT_MS 50 /* Should be long enough for slow systems */
static const char new_folder_name[] = "foo";
static LPITEMIDLIST selected_folder_pidl;
/*
* Returns the number of folders in a folder.
*/
static int get_number_of_folders(LPCSTR path)
{
int number_of_folders = 0;
char path_search_string[MAX_PATH];
WIN32_FIND_DATA find_data;
HANDLE find_handle;
strncpy(path_search_string, path, MAX_PATH);
strncat(path_search_string, "*", 1);
find_handle = FindFirstFile(path_search_string, &find_data);
if (find_handle == INVALID_HANDLE_VALUE)
return -1;
do
{
if ((find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
strcmp(find_data.cFileName, ".") != 0 &&
strcmp(find_data.cFileName, "..") != 0)
{
number_of_folders++;
}
}
while (FindNextFile(find_handle, &find_data) != 0);
FindClose(find_handle);
return number_of_folders;
}
static BOOL does_folder_or_file_exist(LPCSTR folder_path)
{
DWORD file_attributes = GetFileAttributesA(folder_path);
return !(file_attributes == INVALID_FILE_ATTRIBUTES);
}
/*
* Timer callback used by test_click_make_new_folder_button. It simulates a user
* making a new folder and calling it "foo".
*/
static void CALLBACK make_new_folder_timer_callback(HWND hwnd, UINT uMsg,
UINT_PTR idEvent, DWORD dwTime)
{
static int step = 0;
switch (step++)
{
case 0:
/* Click "Make New Folder" button */
PostMessage(hwnd, WM_COMMAND, IDD_MAKENEWFOLDER, 0);
break;
case 1:
/* Set the new folder name to foo by replacing text in edit control */
SendMessage(GetFocus(), EM_REPLACESEL, 0, (LPARAM) new_folder_name);
SetFocus(hwnd);
break;
case 2:
/*
* The test does not trigger the correct state on Windows. This results
* in the new folder pidl not being returned. The result is as
* expected if the same steps are done manually.
* Sending the down key selects the new folder again which sets the
* correct state. This ensures that the correct pidl is returned.
*/
keybd_event(VK_DOWN, 0, 0, 0);
break;
case 3:
keybd_event(VK_DOWN, 0, KEYEVENTF_KEYUP, 0);
break;
case 4:
KillTimer(hwnd, idEvent);
/* Close dialog box */
SendMessage(hwnd, WM_COMMAND, IDOK, 0);
break;
default:
break;
}
}
/*
* Callback used by test_click_make_new_folder_button. It sets up a timer to
* simulate user input.
*/
static int CALLBACK create_new_folder_callback(HWND hwnd, UINT uMsg,
LPARAM lParam, LPARAM lpData)
{
switch (uMsg)
{
case BFFM_INITIALIZED:
/* User input is simulated in timer callback */
SetTimer(hwnd, 0, TIMER_WAIT_MS, make_new_folder_timer_callback);
return TRUE;
default:
return FALSE;
}
}
/*
* Tests if clicking the "Make New Folder" button in a SHBrowseForFolder
* dialog box creates a new folder. (Bug 17986).
*
* Here follows a description of what happens on W2K,Vista, W2K8, W7:
* When the "Make New Folder" button is clicked a new folder is created and
* inserted into the tree. The folder is given a default name that depends on
* the locale (e.g. "New Folder"). The folder name is selected and the dialog
* waits for the user to type in a new name. The folder is renamed when the user
* types in a name and presses enter.
*
* Note that XP and W2K3 do not select the folder name or wait for the user
* to type in a new folder name. This behavior is considered broken as most
* users would like to give the folder a name after creating it. The fact that
* it originally waited for the user to type in a new folder name(W2K), and then
* again was changed back wait for the new folder name(Vista, W2K8, W7),
* indicates that MS also believes that it was broken in XP and W2K3.
*/
static void test_click_make_new_folder_button(void)
{
HRESULT resCoInit, hr;
BROWSEINFO bi;
LPITEMIDLIST pidl = NULL;
LPITEMIDLIST test_folder_pidl;
IShellFolder *test_folder_object;
char test_folder_path[MAX_PATH];
WCHAR test_folder_pathW[MAX_PATH];
CHAR new_folder_path[MAX_PATH];
CHAR new_folder_pidl_path[MAX_PATH];
char selected_folder[MAX_PATH];
const CHAR title[] = "test_click_make_new_folder_button";
int number_of_folders = -1;
SHFILEOPSTRUCT shfileop;
if (does_folder_or_file_exist(title))
{
skip("The test folder already exists.\n");
return;
}
/* Must initialize COM if using the NEWDIAlOGSTYLE according to MSDN. */
resCoInit = CoInitialize(NULL);
if(!(resCoInit == S_OK || resCoInit == S_FALSE))
{
skip("COM could not be initialized %u\n", GetLastError());
return;
}
/* Leave room for concatenating title, two backslashes, and an extra NULL. */
if (!GetCurrentDirectoryA(MAX_PATH-strlen(title)-3, test_folder_path))
{
skip("GetCurrentDirectoryA failed %u\n", GetLastError());
}
strncat(test_folder_path, "\\", 1);
strncat(test_folder_path, title, MAX_PATH-1);
strncat(test_folder_path, "\\", 1);
/* Avoid conflicts by creating a test folder. */
if (!CreateDirectoryA(title, NULL))
{
skip("CreateDirectoryA failed %u\n", GetLastError());
return;
}
/* Initialize browse info struct for SHBrowseForFolder */
bi.hwndOwner = NULL;
bi.pszDisplayName = (LPTSTR) &selected_folder;
bi.lpszTitle = (LPTSTR) title;
bi.ulFlags = BIF_NEWDIALOGSTYLE;
bi.lpfn = create_new_folder_callback;
/* Use test folder as the root folder for dialog box */
MultiByteToWideChar(CP_UTF8, 0, test_folder_path, MAX_PATH,
test_folder_pathW, MAX_PATH);
hr = SHGetDesktopFolder(&test_folder_object);
ok (SUCCEEDED(hr), "SHGetDesktopFolder failed with hr 0x%08x\n", hr);
if (FAILED(hr)) {
skip("SHGetDesktopFolder failed - skipping\n");
return;
}
test_folder_object->lpVtbl->ParseDisplayName(test_folder_object, NULL, NULL,
test_folder_pathW, 0UL, &test_folder_pidl, 0UL);
bi.pidlRoot = test_folder_pidl;
/* Display dialog box and let callback click the buttons */
pidl = SHBrowseForFolder(&bi);
number_of_folders = get_number_of_folders(test_folder_path);
ok(number_of_folders == 1 || broken(number_of_folders == 0) /* W95, W98 */,
"Clicking \"Make New Folder\" button did not result in a new folder.\n");
/* There should be a new folder foo inside the test folder */
strcpy(new_folder_path, test_folder_path);
strcat(new_folder_path, new_folder_name);
ok(does_folder_or_file_exist(new_folder_path)
|| broken(!does_folder_or_file_exist(new_folder_path)) /* W95, W98, XP, W2K3 */,
"The new folder did not get the name %s\n", new_folder_name);
/* Dialog should return a pidl pointing to the new folder */
ok(SHGetPathFromIDListA(pidl, new_folder_pidl_path),
"SHGetPathFromIDList failed for new folder.\n");
ok(strcmp(new_folder_path, new_folder_pidl_path) == 0
|| broken(strcmp(new_folder_path, new_folder_pidl_path) != 0) /* earlier than Vista */,
"SHBrowseForFolder did not return the pidl for the new folder. "
"Expected '%s' got '%s'\n", new_folder_path, new_folder_pidl_path);
/* Remove test folder and any subfolders created in this test */
shfileop.hwnd = NULL;
shfileop.wFunc = FO_DELETE;
/* Path must be double NULL terminated */
test_folder_path[strlen(test_folder_path)+1] = '\0';
shfileop.pFrom = test_folder_path;
shfileop.pTo = NULL;
shfileop.fFlags = FOF_NOCONFIRMATION|FOF_NOERRORUI|FOF_SILENT;
SHFileOperation(&shfileop);
if (pidl)
CoTaskMemFree(pidl);
if (test_folder_pidl)
CoTaskMemFree(test_folder_pidl);
test_folder_object->lpVtbl->Release(test_folder_object);
CoUninitialize();
}
/*
* Callback used by test_selection.
*/
static int CALLBACK selection_callback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
{
DWORD ret;
switch (uMsg)
{
case BFFM_INITIALIZED:
/* test with zero values */
ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 0, 0);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 0, 0);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 1, 0);
ok(!ret, "SendMessage returned: %u\n", ret);
if(0)
{
/* Crashes on NT4 */
ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 1, 0);
ok(!ret, "SendMessage returned: %u\n", ret);
}
ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 0, (LPARAM)selected_folder_pidl);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 0, (LPARAM)selected_folder_pidl);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 1, (LPARAM)selected_folder_pidl);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)selected_folder_pidl);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONA, 1, (LPARAM)new_folder_name);
ok(!ret, "SendMessage returned: %u\n", ret);
ret = SendMessage(hwnd, BFFM_SETSELECTIONW, 1, (LPARAM)new_folder_name);
ok(!ret, "SendMessage returned: %u\n", ret);
SendMessage(hwnd, WM_COMMAND, IDOK, 0);
return TRUE;
default:
return FALSE;
}
}
static void test_selection(void)
{
HRESULT resCoInit, hr;
BROWSEINFO bi;
LPITEMIDLIST pidl = NULL;
IShellFolder *desktop_object;
WCHAR selected_folderW[MAX_PATH];
const CHAR title[] = "test_selection";
resCoInit = CoInitialize(NULL);
if(!(resCoInit == S_OK || resCoInit == S_FALSE))
{
skip("COM could not be initialized %u\n", GetLastError());
return;
}
if (!GetCurrentDirectoryW(MAX_PATH, selected_folderW))
{
skip("GetCurrentDirectoryW failed %u\n", GetLastError());
}
/* Initialize browse info struct for SHBrowseForFolder */
bi.hwndOwner = NULL;
bi.pszDisplayName = NULL;
bi.lpszTitle = (LPTSTR) title;
bi.lpfn = selection_callback;
hr = SHGetDesktopFolder(&desktop_object);
ok (SUCCEEDED(hr), "SHGetDesktopFolder failed with hr 0x%08x\n", hr);
if (FAILED(hr)) {
skip("SHGetDesktopFolder failed - skipping\n");
return;
}
desktop_object->lpVtbl->ParseDisplayName(desktop_object, NULL, NULL,
selected_folderW, 0UL, &selected_folder_pidl, 0UL);
bi.pidlRoot = selected_folder_pidl;
/* test without flags */
bi.ulFlags = 0;
pidl = SHBrowseForFolder(&bi);
if (pidl)
CoTaskMemFree(pidl);
/* test with flag */
bi.ulFlags = BIF_NEWDIALOGSTYLE;
pidl = SHBrowseForFolder(&bi);
if (pidl)
CoTaskMemFree(pidl);
desktop_object->lpVtbl->Release(desktop_object);
CoUninitialize();
}
START_TEST(brsfolder)
{
test_click_make_new_folder_button();
test_selection();
}

File diff suppressed because it is too large Load diff

View file

@ -200,14 +200,22 @@ static void init_strings(void)
WCHAR module[MAX_PATH];
WCHAR module_expanded[MAX_PATH];
WCHAR localized[MAX_PATH];
HRESULT hr;
int id;
MultiByteToWideChar(CP_ACP, 0, startup, -1, startupW, sizeof(startupW)/sizeof(WCHAR));
pSHGetLocalizedName(startupW, module, MAX_PATH, &id);
ExpandEnvironmentStringsW(module, module_expanded, MAX_PATH);
LoadStringW(GetModuleHandleW(module_expanded), id, localized, MAX_PATH);
hr = pSHGetLocalizedName(startupW, module, MAX_PATH, &id);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
/* check to be removed when SHGetLocalizedName is implemented */
if (hr == S_OK)
{
ExpandEnvironmentStringsW(module, module_expanded, MAX_PATH);
LoadStringW(GetModuleHandleW(module_expanded), id, localized, MAX_PATH);
WideCharToMultiByte(CP_ACP, 0, localized, -1, StartupTitle, sizeof(StartupTitle), NULL, NULL);
WideCharToMultiByte(CP_ACP, 0, localized, -1, StartupTitle, sizeof(StartupTitle), NULL, NULL);
}
else
lstrcpyA(StartupTitle, (strrchr(startup, '\\') + 1));
}
else
{

View file

@ -0,0 +1,107 @@
/*
* Tests for recycle bin functions
*
* Copyright 2011 Jay Yang
*
* 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 WIN32_LEAN_AND_MEAN
#include <windows.h>
#include "shellapi.h"
#include <stdio.h>
#include "wine/test.h"
static int (WINAPI *pSHQueryRecycleBinA)(LPCSTR,LPSHQUERYRBINFO);
static int (WINAPI *pSHFileOperationA)(LPSHFILEOPSTRUCTA);
static char int64_buffer[65];
/* Note: This function uses a single buffer for the return value.*/
static const char* str_from_int64(__int64 ll)
{
if (sizeof(ll) > sizeof(unsigned long) && ll >> 32)
sprintf(int64_buffer,"%lx%08lx",(unsigned long)(ll >> 32),(unsigned long)ll);
else
sprintf(int64_buffer,"%lx",(unsigned long)ll);
return int64_buffer;
}
static void setup_pointers(void)
{
HMODULE hshell32 = GetModuleHandleA("shell32.dll");
pSHQueryRecycleBinA = (void*)GetProcAddress(hshell32, "SHQueryRecycleBinA");
pSHFileOperationA = (void*)GetProcAddress(hshell32, "SHFileOperationA");
}
static void test_query_recyclebin(void)
{
SHQUERYRBINFO info1={sizeof(info1),0xdeadbeef,0xdeadbeef};
SHQUERYRBINFO info2={sizeof(info2),0xdeadbeef,0xdeadbeef};
UINT written;
HRESULT hr;
HANDLE file;
SHFILEOPSTRUCTA shfo;
const CHAR *name="test.txt";
CHAR buf[MAX_PATH+strlen(name)+2];
if(!pSHQueryRecycleBinA)
{
skip("SHQueryRecycleBinA does not exist\n");
return;
}
if(!pSHFileOperationA)
{
skip("SHFileOperationA does not exist\n");
return;
}
GetCurrentDirectoryA(MAX_PATH, buf);
strcat(buf,"\\");
strcat(buf,name);
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);
CloseHandle(file);
shfo.hwnd = NULL;
shfo.wFunc = FO_DELETE;
shfo.pFrom = buf;
shfo.pTo = NULL;
shfo.fFlags = FOF_FILESONLY | FOF_NOCONFIRMATION | FOF_SILENT | FOF_ALLOWUNDO;
shfo.hNameMappings = NULL;
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));
}
}
START_TEST(recyclebin)
{
setup_pointers();
test_query_recyclebin();
}

View file

@ -17,10 +17,16 @@
<library>ntdll</library>
<file>appbar.c</file>
<file>autocomplete.c</file>
<file>brsfolder.c</file>
<file>ebrowser.c</file>
<file>generated.c</file>
<file>progman_dde.c</file>
<file>recyclebin.c</file>
<file>shelldispatch.c</file>
<file>shelllink.c</file>
<file>shellole.c</file>
<file>shellpath.c</file>
<file>shfldr_special.c</file>
<file>shlexec.c</file>
<file>shlfileop.c</file>
<file>shlfolder.c</file>
@ -28,7 +34,6 @@
<file>string.c</file>
<file>systray.c</file>
<file>testlist.c</file>
<file>shfldr_special.c</file>
<file>rsrc.rc</file>
</module>
</group>

View file

@ -1,7 +1,7 @@
/*
* Unit test suite for shell32 functions
*
* Copyright 2005 Francois Gougett for CodeWeavers
* Copyright 2005 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

View file

@ -0,0 +1,319 @@
/*
* 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();
}

View file

@ -168,15 +168,15 @@ static void test_get_set(void)
CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
&IID_IShellLinkW, (LPVOID*)&slW);
if (!slW)
skip("SetPath with NULL parameter crashes on Win9x\n");
if (!slW /* Win9x */ || !pGetLongPathNameA /* NT4 */)
skip("SetPath with NULL parameter crashes on Win9x and some NT4\n");
else
{
IShellLinkW_Release(slW);
r = IShellLinkA_SetPath(sl, NULL);
ok(r==E_INVALIDARG ||
broken(r==S_OK), /* Some Win95 and NT4 */
"SetPath failed (0x%08x)\n", r);
"SetPath returned wrong error (0x%08x)\n", r);
}
r = IShellLinkA_SetPath(sl, "");
@ -204,16 +204,14 @@ static void test_get_set(void)
/* Test the interaction of SetPath and SetIDList */
tmp_pidl=NULL;
r = IShellLinkA_GetIDList(sl, &tmp_pidl);
todo_wine ok(r == S_OK, "GetIDList failed (0x%08x)\n", r);
ok(r == S_OK, "GetIDList failed (0x%08x)\n", r);
if (r == S_OK)
{
BOOL ret;
strcpy(buffer,"garbage");
ret = SHGetPathFromIDListA(tmp_pidl, buffer);
todo_wine {
ok(ret, "SHGetPathFromIDListA failed\n");
}
if (ret)
ok(lstrcmpi(buffer,str)==0, "GetIDList returned '%s'\n", buffer);
pILFree(tmp_pidl);
@ -326,9 +324,7 @@ static void test_get_set(void)
i=0xdeadbeef;
strcpy(buffer,"garbage");
r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
todo_wine {
ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
}
ok(*buffer=='\0', "GetIconLocation returned '%s'\n", buffer);
ok(i==0, "GetIconLocation returned %d\n", i);
@ -435,7 +431,7 @@ void create_lnk_(int line, const WCHAR* path, lnk_desc_t* desc, int save_fails)
if (0)
{
/* crashes on XP */
r = IPersistFile_GetCurFile(pf, NULL);
IPersistFile_GetCurFile(pf, NULL);
}
/* test GetCurFile before ::Save */
@ -685,6 +681,24 @@ static void test_load_save(void)
create_lnk(lnkfile, &desc, 0);
check_lnk(lnkfile, &desc, 0x0);
/* Test omitting .exe from an absolute path */
p=strrchr(realpath, '.');
if (p)
*p='\0';
desc.description="absolute path without .exe";
desc.workdir=mydir;
desc.path=realpath;
desc.pidl=NULL;
desc.arguments="/option1 /option2 \"Some string\"";
desc.showcmd=SW_SHOWNORMAL;
desc.icon=mypath;
desc.icon_id=0;
desc.hotkey=0x1234;
create_lnk(lnkfile, &desc, 0);
strcat(realpath, ".exe");
check_lnk(lnkfile, &desc, 0x4);
/* Overwrite the existing lnk file and test link to a command on the path */
desc.description="command on path";
desc.workdir=mypath;
@ -701,6 +715,22 @@ static void test_load_save(void)
desc.path=realpath;
check_lnk(lnkfile, &desc, 0x0);
/* Test omitting .exe from a command on the path */
desc.description="command on path without .exe";
desc.workdir=mypath;
desc.path="rundll32";
desc.pidl=NULL;
desc.arguments="/option1 /option2 \"Some string\"";
desc.showcmd=SW_SHOWNORMAL;
desc.icon=mypath;
desc.icon_id=0;
desc.hotkey=0x1234;
create_lnk(lnkfile, &desc, 0);
/* Check that link is created to proper location */
SearchPathA( NULL, "rundll32", NULL, MAX_PATH, realpath, NULL);
desc.path=realpath;
check_lnk(lnkfile, &desc, 0x4);
/* Create a temporary non-executable file */
r=GetTempPath(sizeof(mypath), mypath);
ok(r<sizeof(mypath), "GetTempPath failed (%d), err %d\n", r, GetLastError());
@ -730,6 +760,8 @@ static void test_load_save(void)
check_lnk(lnkfile, &desc, 0x0);
r=pGetShortPathNameA(mydir, mypath, sizeof(mypath));
ok(r<sizeof(mypath), "GetShortPathName failed (%d), err %d\n", r, GetLastError());
strcpy(realpath, mypath);
strcat(realpath, "\\test.txt");
strcat(mypath, "\\\\test.txt");
@ -751,6 +783,36 @@ static void test_load_save(void)
r = DeleteFileA(mypath);
ok(r, "failed to delete file %s (%d)\n", mypath, GetLastError());
/* Create a temporary .bat file */
strcpy(mypath, mydir);
strcat(mypath, "\\test.bat");
hf = CreateFile(mypath, GENERIC_WRITE, 0, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
CloseHandle(hf);
strcpy(realpath, mypath);
p=strrchr(mypath, '.');
if (p)
*p='\0';
/* Try linking to the .bat file without the extension */
desc.description="batch file";
desc.workdir=mydir;
desc.path=mypath;
desc.pidl=NULL;
desc.arguments="";
desc.showcmd=SW_SHOWNORMAL;
desc.icon=mypath;
desc.icon_id=0;
desc.hotkey=0x1234;
create_lnk(lnkfile, &desc, 0);
desc.path = realpath;
check_lnk(lnkfile, &desc, 0x4);
r = DeleteFileA(realpath);
ok(r, "failed to delete file %s (%d)\n", realpath, GetLastError());
/* FIXME: Also test saving a .lnk pointing to a pidl that cannot be
* represented as a path.
*/
@ -812,16 +874,21 @@ static void test_datalink(void)
ok( r == E_FAIL, "CopyDataBlock failed\n");
ok( dar == NULL, "should be null\n");
r = IShellLinkW_SetPath(sl, NULL);
ok(r == E_INVALIDARG, "set path failed\n");
if (!pGetLongPathNameA /* NT4 */)
skip("SetPath with NULL parameter crashes on NT4\n");
else
{
r = IShellLinkW_SetPath(sl, NULL);
ok(r == E_INVALIDARG, "SetPath returned wrong error (0x%08x)\n", r);
}
r = IShellLinkW_SetPath(sl, lnk);
ok(r == S_OK, "set path failed\n");
ok(r == S_OK, "SetPath failed\n");
if (0)
{
/* the following crashes */
r = IShellLinkDataList_GetFlags( dl, NULL );
IShellLinkDataList_GetFlags( dl, NULL );
}
flags = 0;
@ -872,6 +939,66 @@ static void test_shdefextracticon(void)
ok(SUCCEEDED(res), "SHDefExtractIconA failed, res=%x\n", res);
}
static void test_GetIconLocation(void)
{
IShellLinkA *sl;
const char *str;
char buffer[INFOTIPSIZE], mypath[MAX_PATH];
int i;
HRESULT r;
LPITEMIDLIST pidl;
r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
&IID_IShellLinkA, (LPVOID*)&sl);
ok(r == S_OK, "no IID_IShellLinkA (0x%08x)\n", r);
if(r != S_OK)
return;
i = 0xdeadbeef;
strcpy(buffer, "garbage");
r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer);
ok(i == 0, "GetIconLocation returned %d\n", i);
str = "c:\\some\\path";
r = IShellLinkA_SetPath(sl, str);
ok(r == S_FALSE || r == S_OK, "SetPath failed (0x%08x)\n", r);
i = 0xdeadbeef;
strcpy(buffer, "garbage");
r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer);
ok(i == 0, "GetIconLocation returned %d\n", i);
GetWindowsDirectoryA(mypath, sizeof(mypath) - 12);
strcat(mypath, "\\regedit.exe");
pidl = path_to_pidl(mypath);
r = IShellLinkA_SetIDList(sl, pidl);
ok(r == S_OK, "SetPath failed (0x%08x)\n", r);
pILFree(pidl);
i = 0xdeadbeef;
strcpy(buffer, "garbage");
r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
ok(*buffer == '\0', "GetIconLocation returned '%s'\n", buffer);
ok(i == 0, "GetIconLocation returned %d\n", i);
str = "c:\\nonexistent\\file";
r = IShellLinkA_SetIconLocation(sl, str, 0xbabecafe);
ok(r == S_OK, "SetIconLocation failed (0x%08x)\n", r);
i = 0xdeadbeef;
r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i);
ok(r == S_OK, "GetIconLocation failed (0x%08x)\n", r);
ok(lstrcmpi(buffer,str) == 0, "GetIconLocation returned '%s'\n", buffer);
ok(i == 0xbabecafe, "GetIconLocation returned %d'\n", i);
IShellLinkA_Release(sl);
}
START_TEST(shelllink)
{
HRESULT r;
@ -895,6 +1022,7 @@ START_TEST(shelllink)
test_load_save();
test_datalink();
test_shdefextracticon();
test_GetIconLocation();
CoUninitialize();
}

View file

@ -0,0 +1,437 @@
/*
* Copyright 2010 Piotr Caban for CodeWeavers
*
* 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 CONST_VTABLE
#define NONAMELESSUNION
#include <stdio.h>
#include <wine/test.h>
#include "winbase.h"
#include "shlobj.h"
#include "initguid.h"
DEFINE_GUID(FMTID_Test,0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12);
DEFINE_GUID(FMTID_NotExisting, 0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13);
#define DEFINE_EXPECT(func) \
static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
#define SET_EXPECT(func) \
expect_ ## func = TRUE
#define CHECK_EXPECT2(func) \
do { \
ok(expect_ ##func, "unexpected call " #func "\n"); \
called_ ## func = TRUE; \
}while(0)
#define CHECK_EXPECT(func) \
do { \
CHECK_EXPECT2(func); \
expect_ ## func = FALSE; \
}while(0)
#define CHECK_CALLED(func) \
do { \
ok(called_ ## func, "expected " #func "\n"); \
expect_ ## func = called_ ## func = FALSE; \
}while(0)
DEFINE_EXPECT(Create);
DEFINE_EXPECT(Delete);
DEFINE_EXPECT(Open);
DEFINE_EXPECT(ReadMultiple);
DEFINE_EXPECT(ReadMultipleCodePage);
DEFINE_EXPECT(Release);
DEFINE_EXPECT(Stat);
DEFINE_EXPECT(WriteMultiple);
static HRESULT (WINAPI *pSHPropStgCreate)(IPropertySetStorage*, REFFMTID, const CLSID*,
DWORD, DWORD, DWORD, IPropertyStorage**, UINT*);
static HRESULT (WINAPI *pSHPropStgReadMultiple)(IPropertyStorage*, UINT,
ULONG, const PROPSPEC*, PROPVARIANT*);
static HRESULT (WINAPI *pSHPropStgWriteMultiple)(IPropertyStorage*, UINT*,
ULONG, const PROPSPEC*, PROPVARIANT*, PROPID);
static void init(void)
{
HMODULE hmod = GetModuleHandleA("shell32.dll");
pSHPropStgCreate = (void*)GetProcAddress(hmod, "SHPropStgCreate");
pSHPropStgReadMultiple = (void*)GetProcAddress(hmod, "SHPropStgReadMultiple");
pSHPropStgWriteMultiple = (void*)GetProcAddress(hmod, "SHPropStgWriteMultiple");
}
static HRESULT WINAPI PropertyStorage_QueryInterface(IPropertyStorage *This,
REFIID riid, void **ppvObject)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static ULONG WINAPI PropertyStorage_AddRef(IPropertyStorage *This)
{
ok(0, "unexpected call\n");
return 2;
}
static ULONG WINAPI PropertyStorage_Release(IPropertyStorage *This)
{
CHECK_EXPECT(Release);
return 1;
}
static HRESULT WINAPI PropertyStorage_ReadMultiple(IPropertyStorage *This, ULONG cpspec,
const PROPSPEC *rgpspec, PROPVARIANT *rgpropvar)
{
if(cpspec == 1) {
CHECK_EXPECT(ReadMultipleCodePage);
ok(rgpspec != NULL, "rgpspec = NULL\n");
ok(rgpropvar != NULL, "rgpropvar = NULL\n");
ok(rgpspec[0].ulKind == PRSPEC_PROPID, "rgpspec[0].ulKind = %d\n", rgpspec[0].ulKind);
ok(rgpspec[0].u.propid == PID_CODEPAGE, "rgpspec[0].propid = %d\n", rgpspec[0].u.propid);
rgpropvar[0].vt = VT_I2;
rgpropvar[0].u.iVal = 1234;
} else {
CHECK_EXPECT(ReadMultiple);
ok(cpspec == 10, "cpspec = %u\n", cpspec);
ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec);
ok(rgpropvar != NULL, "rgpropvar = NULL\n");
ok(rgpropvar[0].vt==0 || broken(rgpropvar[0].vt==VT_BSTR), "rgpropvar[0].vt = %d\n", rgpropvar[0].vt);
rgpropvar[0].vt = VT_BSTR;
rgpropvar[0].u.bstrVal = (void*)0xdeadbeef;
rgpropvar[1].vt = VT_LPSTR;
rgpropvar[1].u.pszVal = (void*)0xdeadbeef;
rgpropvar[2].vt = VT_BYREF|VT_I1;
rgpropvar[2].u.pcVal = (void*)0xdeadbeef;
rgpropvar[3].vt = VT_BYREF|VT_VARIANT;
rgpropvar[3].u.pvarVal = (void*)0xdeadbeef;
}
return S_OK;
}
static HRESULT WINAPI PropertyStorage_WriteMultiple(IPropertyStorage *This, ULONG cpspec,
const PROPSPEC *rgpspec, const PROPVARIANT *rgpropvar,
PROPID propidNameFirst)
{
CHECK_EXPECT(WriteMultiple);
ok(cpspec == 20, "cpspec = %d\n", cpspec);
ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec);
ok(rgpropvar == (void*)0xdeadbeef, "rgpropvar = %p\n", rgpspec);
ok(propidNameFirst == PID_FIRST_USABLE, "propidNameFirst = %d\n", propidNameFirst);
return S_OK;
}
static HRESULT WINAPI PropertyStorage_DeleteMultiple(IPropertyStorage *This, ULONG cpspec,
const PROPSPEC *rgpspec)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_ReadPropertyNames(IPropertyStorage *This, ULONG cpropid,
const PROPID *rgpropid, LPOLESTR *rglpwstrName)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_WritePropertyNames(IPropertyStorage *This, ULONG cpropid,
const PROPID *rgpropid, const LPOLESTR *rglpwstrName)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_DeletePropertyNames(IPropertyStorage *This, ULONG cpropid,
const PROPID *rgpropid)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_Commit(IPropertyStorage *This, DWORD grfCommitFlags)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_Revert(IPropertyStorage *This)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_Enum(IPropertyStorage *This, IEnumSTATPROPSTG **ppenum)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_SetTimes(IPropertyStorage *This, const FILETIME *pctime,
const FILETIME *patime, const FILETIME *pmtime)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_SetClass(IPropertyStorage *This, REFCLSID clsid)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI PropertyStorage_Stat(IPropertyStorage *This, STATPROPSETSTG *statpsstg)
{
CHECK_EXPECT(Stat);
memset(statpsstg, 0, sizeof(STATPROPSETSTG));
memcpy(&statpsstg->fmtid, &FMTID_Test, sizeof(FMTID));
statpsstg->grfFlags = PROPSETFLAG_ANSI;
return S_OK;
}
static IPropertyStorageVtbl PropertyStorageVtbl = {
PropertyStorage_QueryInterface,
PropertyStorage_AddRef,
PropertyStorage_Release,
PropertyStorage_ReadMultiple,
PropertyStorage_WriteMultiple,
PropertyStorage_DeleteMultiple,
PropertyStorage_ReadPropertyNames,
PropertyStorage_WritePropertyNames,
PropertyStorage_DeletePropertyNames,
PropertyStorage_Commit,
PropertyStorage_Revert,
PropertyStorage_Enum,
PropertyStorage_SetTimes,
PropertyStorage_SetClass,
PropertyStorage_Stat
};
static IPropertyStorage PropertyStorage = { &PropertyStorageVtbl };
static HRESULT WINAPI PropertySetStorage_QueryInterface(IPropertySetStorage *This,
REFIID riid, void **ppvObject)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static ULONG WINAPI PropertySetStorage_AddRef(IPropertySetStorage *This)
{
ok(0, "unexpected call\n");
return 2;
}
static ULONG WINAPI PropertySetStorage_Release(IPropertySetStorage *This)
{
ok(0, "unexpected call\n");
return 1;
}
static HRESULT WINAPI PropertySetStorage_Create(IPropertySetStorage *This,
REFFMTID rfmtid, const CLSID *pclsid, DWORD grfFlags,
DWORD grfMode, IPropertyStorage **ppprstg)
{
CHECK_EXPECT(Create);
ok(IsEqualGUID(rfmtid, &FMTID_Test) || IsEqualGUID(rfmtid, &FMTID_NotExisting),
"Incorrect rfmtid value\n");
ok(pclsid == NULL, "pclsid != NULL\n");
ok(grfFlags == PROPSETFLAG_ANSI, "grfFlags = %x\n", grfFlags);
ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode);
*ppprstg = &PropertyStorage;
return S_OK;
}
static HRESULT WINAPI PropertySetStorage_Open(IPropertySetStorage *This,
REFFMTID rfmtid, DWORD grfMode, IPropertyStorage **ppprstg)
{
CHECK_EXPECT(Open);
if(IsEqualGUID(rfmtid, &FMTID_Test)) {
ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode);
*ppprstg = &PropertyStorage;
return S_OK;
}
return STG_E_FILENOTFOUND;
}
static HRESULT WINAPI PropertySetStorage_Delete(IPropertySetStorage *This,
REFFMTID rfmtid)
{
CHECK_EXPECT(Delete);
ok(IsEqualGUID(rfmtid, &FMTID_Test), "wrong rfmtid value\n");
return S_OK;
}
static HRESULT WINAPI PropertySetStorage_Enum(IPropertySetStorage *This,
IEnumSTATPROPSETSTG **ppenum)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static IPropertySetStorageVtbl PropertySetStorageVtbl = {
PropertySetStorage_QueryInterface,
PropertySetStorage_AddRef,
PropertySetStorage_Release,
PropertySetStorage_Create,
PropertySetStorage_Open,
PropertySetStorage_Delete,
PropertySetStorage_Enum
};
static IPropertySetStorage PropertySetStorage = { &PropertySetStorageVtbl };
static void test_SHPropStg_functions(void)
{
IPropertyStorage *property_storage;
UINT codepage;
PROPVARIANT read[10];
HRESULT hres;
if(!pSHPropStgCreate || !pSHPropStgReadMultiple || !pSHPropStgWriteMultiple) {
win_skip("SHPropStg* functions are missing\n");
return;
}
if(0) {
/* Crashes on Windows */
pSHPropStgCreate(NULL, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
pSHPropStgCreate(&PropertySetStorage, NULL, NULL, PROPSETFLAG_DEFAULT,
STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
STGM_READ, OPEN_EXISTING, NULL, &codepage);
}
SET_EXPECT(Open);
SET_EXPECT(ReadMultipleCodePage);
hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT,
STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
ok(codepage == 1234, "codepage = %d\n", codepage);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(Open);
CHECK_CALLED(ReadMultipleCodePage);
SET_EXPECT(Open);
hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL,
PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage);
ok(hres == STG_E_FILENOTFOUND, "hres = %x\n", hres);
CHECK_CALLED(Open);
SET_EXPECT(Open);
SET_EXPECT(Release);
SET_EXPECT(Delete);
SET_EXPECT(Create);
SET_EXPECT(ReadMultipleCodePage);
hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_ANSI,
STGM_READ, CREATE_ALWAYS, &property_storage, &codepage);
ok(codepage == 1234, "codepage = %d\n", codepage);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(Open);
CHECK_CALLED(Release);
CHECK_CALLED(Delete);
CHECK_CALLED(Create);
CHECK_CALLED(ReadMultipleCodePage);
SET_EXPECT(Open);
SET_EXPECT(Create);
SET_EXPECT(ReadMultipleCodePage);
hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL, PROPSETFLAG_ANSI,
STGM_READ, CREATE_ALWAYS, &property_storage, &codepage);
ok(codepage == 1234, "codepage = %d\n", codepage);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(Open);
CHECK_CALLED(Create);
CHECK_CALLED(ReadMultipleCodePage);
SET_EXPECT(Open);
hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, &FMTID_NotExisting,
PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, NULL);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(Open);
SET_EXPECT(Stat);
SET_EXPECT(ReadMultipleCodePage);
SET_EXPECT(WriteMultiple);
codepage = 0;
hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
ok(hres == S_OK, "hres = %x\n", hres);
ok(codepage == 1234, "codepage = %d\n", codepage);
CHECK_CALLED(Stat);
CHECK_CALLED(ReadMultipleCodePage);
CHECK_CALLED(WriteMultiple);
SET_EXPECT(Stat);
SET_EXPECT(ReadMultipleCodePage);
SET_EXPECT(WriteMultiple);
hres = pSHPropStgWriteMultiple(property_storage, NULL, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(Stat);
CHECK_CALLED(ReadMultipleCodePage);
CHECK_CALLED(WriteMultiple);
SET_EXPECT(Stat);
SET_EXPECT(WriteMultiple);
codepage = 1000;
hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE);
ok(hres == S_OK, "hres = %x\n", hres);
ok(codepage == 1000, "codepage = %d\n", codepage);
CHECK_CALLED(Stat);
CHECK_CALLED(WriteMultiple);
read[0].vt = VT_BSTR;
read[0].u.bstrVal = (void*)0xdeadbeef;
SET_EXPECT(ReadMultiple);
SET_EXPECT(ReadMultipleCodePage);
SET_EXPECT(Stat);
hres = pSHPropStgReadMultiple(property_storage, 0, 10, (void*)0xdeadbeef, read);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(ReadMultiple);
CHECK_CALLED(ReadMultipleCodePage);
CHECK_CALLED(Stat);
SET_EXPECT(ReadMultiple);
SET_EXPECT(Stat);
hres = pSHPropStgReadMultiple(property_storage, 1251, 10, (void*)0xdeadbeef, read);
ok(hres == S_OK, "hres = %x\n", hres);
CHECK_CALLED(ReadMultiple);
CHECK_CALLED(Stat);
}
START_TEST(shellole)
{
init();
test_SHPropStg_functions();
}

File diff suppressed because it is too large Load diff

View file

@ -150,9 +150,9 @@ static void test_printers_folder(void)
if (0)
{
/* crashes on XP */
hr = IShellFolder2_GetDetailsOf(folder, NULL, 0, NULL);
hr = IShellFolder2_GetDefaultColumnState(folder, 0, NULL);
hr = IPersistFolder2_GetCurFolder(pf, NULL);
IShellFolder2_GetDetailsOf(folder, NULL, 0, NULL);
IShellFolder2_GetDefaultColumnState(folder, 0, NULL);
IPersistFolder2_GetCurFolder(pf, NULL);
}
/* 5 columns defined */
@ -162,8 +162,11 @@ if (0)
hr = IShellFolder2_GetDefaultColumnState(folder, 6, &state);
ok(broken(hr == E_NOTIMPL) || hr == E_INVALIDARG /* Win7 */, "got 0x%08x\n", hr);
details.str.u.pOleStr = NULL;
hr = IShellFolder2_GetDetailsOf(folder, NULL, 0, &details);
ok(hr == S_OK || broken(E_NOTIMPL) /* W2K */, "got 0x%08x\n", hr);
if (SHELL_OsIsUnicode()) SHFree(details.str.u.pOleStr);
/* test every column if method is implemented */
if (hr == S_OK)
{

View file

@ -57,6 +57,7 @@ static char tmpdir[MAX_PATH];
static char child_file[MAX_PATH];
static DLLVERSIONINFO dllver;
static BOOL skip_noassoc_tests = FALSE;
static HANDLE dde_ready_event;
/***
@ -526,7 +527,7 @@ static void CALLBACK childTimeout(HWND wnd, UINT msg, UINT_PTR timer, DWORD time
static void doChild(int argc, char** argv)
{
char* filename;
char *filename, longpath[MAX_PATH] = "";
HANDLE hFile, map;
int i;
int rc;
@ -552,6 +553,8 @@ static void doChild(int argc, char** argv)
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)
@ -572,13 +575,14 @@ static void doChild(int argc, char** argv)
timer = SetTimer(NULL, 0, 2500, childTimeout);
dde_ready = CreateEvent(NULL, FALSE, FALSE, "winetest_shlexec_dde_ready");
dde_ready = OpenEvent(EVENT_MODIFY_STATE, FALSE, "winetest_shlexec_dde_ready");
SetEvent(dde_ready);
CloseHandle(dde_ready);
while (GetMessage(&msg, NULL, 0, 0))
DispatchMessage(&msg);
Sleep(500);
KillTimer(NULL, timer);
assert(DdeNameService(ddeInst, hszApplication, 0L, DNS_UNREGISTER));
assert(DdeFreeStringHandle(ddeInst, hszTopic));
@ -587,7 +591,7 @@ static void doChild(int argc, char** argv)
}
else
{
dde_ready = CreateEvent(NULL, FALSE, FALSE, "winetest_shlexec_dde_ready");
dde_ready = OpenEvent(EVENT_MODIFY_STATE, FALSE, "winetest_shlexec_dde_ready");
SetEvent(dde_ready);
CloseHandle(dde_ready);
}
@ -676,6 +680,11 @@ static void _okChildString(const char* file, int line, const char* key, const ch
{
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,
"%s expected '%s', got '%s'\n", key, expected, result);
}
@ -684,6 +693,11 @@ static void _okChildPath(const char* file, int line, const char* key, const char
{
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);
}
@ -774,6 +788,26 @@ static DWORD get_long_path_name(const char* shortpath, char* longpath, DWORD lon
return tmplen;
}
/***
*
* PathFindFileNameA equivalent that supports WinNT
*
***/
static LPSTR path_find_file_name(LPCSTR lpszPath)
{
LPCSTR lastSlash = lpszPath;
while (lpszPath && *lpszPath)
{
if ((*lpszPath == '\\' || *lpszPath == '/' || *lpszPath == ':') &&
lpszPath[1] && lpszPath[1] != '\\' && lpszPath[1] != '/')
lastSlash = lpszPath + 1;
lpszPath = CharNext(lpszPath);
}
return (LPSTR)lastSlash;
}
/***
*
* Tests
@ -1613,14 +1647,7 @@ static dde_tests_t dde_tests[] =
static DWORD WINAPI hooked_WaitForInputIdle(HANDLE process, DWORD timeout)
{
HANDLE dde_ready;
DWORD wait_result;
dde_ready = CreateEventA(NULL, FALSE, FALSE, "winetest_shlexec_dde_ready");
wait_result = WaitForSingleObject(dde_ready, timeout);
CloseHandle(dde_ready);
return wait_result;
return WaitForSingleObject(dde_ready_event, timeout);
}
/*
@ -1714,7 +1741,7 @@ static void test_dde(void)
{
if (!create_test_association(".sde"))
{
skip("Unable to create association for '.sfe'\n");
skip("Unable to create association for '.sde'\n");
return;
}
create_test_verb_dde(".sde", "Open", 0, test->command, test->ddeexec,
@ -1732,7 +1759,9 @@ static void test_dde(void)
}
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);
CloseHandle(dde_ready_event);
if ((test->todo & 0x1)==0)
{
ok(32 < rc, "%s failed: rc=%d err=%d\n", shell_call,
@ -2118,8 +2147,9 @@ static void test_commandline(void)
static const WCHAR chkfmt3[] = {'\\','\"','%','s','\"',0};
static const WCHAR chkfmt4[] = {'%','s','=','%','s','\"',' ','%','s','\"',0};
WCHAR cmdline[255];
LPWSTR *args = (LPWSTR*)0xdeadcafe;
LPWSTR *args = (LPWSTR*)0xdeadcafe, pbuf;
INT numargs = -1;
size_t buflen;
wsprintfW(cmdline,fmt1,one,two,three,four);
args=CommandLineToArgvW(cmdline,&numargs);
@ -2170,6 +2200,46 @@ static void test_commandline(void)
wsprintfW(cmdline,fmt6);
args=CommandLineToArgvW(cmdline,&numargs);
ok(numargs == 1, "expected 1 args, got %i\n",numargs);
if (numargs == 1) {
buflen = max(lstrlenW(args[0])+1,256);
pbuf = HeapAlloc(GetProcessHeap(), 0, buflen*sizeof(pbuf[0]));
GetModuleFileNameW(NULL, pbuf, buflen);
pbuf[buflen-1] = 0;
/* check args[0] is module file name */
ok(lstrcmpW(args[0],pbuf)==0, "wrong path to the current executable\n");
HeapFree(GetProcessHeap(), 0, pbuf);
}
}
static void test_directory(void)
{
char path[MAX_PATH], newdir[MAX_PATH];
char params[1024];
int rc;
/* copy this executable to a new folder and cd to it */
sprintf(newdir, "%s\\newfolder", tmpdir);
rc = CreateDirectoryA( newdir, NULL );
ok( rc, "failed to create %s err %u\n", newdir, GetLastError() );
sprintf(path, "%s\\%s", newdir, path_find_file_name(argv0));
CopyFileA(argv0, path, FALSE);
SetCurrentDirectory(tmpdir);
sprintf(params, "shlexec \"%s\" Exec", child_file);
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, path_find_file_name(argv0), params, NULL);
todo_wine ok(rc == SE_ERR_FNF, "%s returned %d\n", shell_call, rc);
rc=shell_execute_ex(SEE_MASK_NOZONECHECKS|SEE_MASK_FLAG_NO_UI,
NULL, path_find_file_name(argv0), params, newdir);
ok(rc > 32, "%s returned %d\n", shell_call, rc);
okChildInt("argcA", 4);
okChildString("argvA3", "Exec");
todo_wine okChildPath("longPath", path);
DeleteFile(path);
RemoveDirectoryA(newdir);
}
START_TEST(shlexec)
@ -2194,6 +2264,7 @@ START_TEST(shlexec)
test_dde();
test_dde_default_app();
test_commandline();
test_directory();
cleanup_test();
}

View file

@ -820,6 +820,7 @@ static void test_copy(void)
DWORD retval;
LPSTR ptr;
BOOL on_nt4 = FALSE;
BOOL ret;
if (old_shell32)
{
@ -973,16 +974,16 @@ static void test_copy(void)
shfo.pTo = "test2.txt\0";
/* suppress the error-dialog in win9x here */
shfo.fFlags = FOF_NOERRORUI | FOF_NOCONFIRMATION | FOF_SILENT;
ok(SetFileAttributesA(shfo.pTo, FILE_ATTRIBUTE_READONLY),
"Failure to set file attributes (error %x)\n", GetLastError());
ret = SetFileAttributesA(shfo.pTo, FILE_ATTRIBUTE_READONLY);
ok(ret, "Failure to set file attributes (error %x)\n", GetLastError());
retval = CopyFileA(shfo.pFrom, shfo.pTo, FALSE);
ok(!retval && GetLastError() == ERROR_ACCESS_DENIED, "CopyFileA should have fail with ERROR_ACCESS_DENIED\n");
retval = SHFileOperationA(&shfo);
/* Does not work on Win95, Win95B, NT4WS and NT4SRV */
ok(!retval || broken(retval == DE_OPCANCELLED), "SHFileOperationA failed to copy (error %x)\n", retval);
/* Set back normal attributes to make the file deletion succeed */
ok(SetFileAttributesA(shfo.pTo, FILE_ATTRIBUTE_NORMAL),
"Failure to set file attributes (error %x)\n", GetLastError());
ret = SetFileAttributesA(shfo.pTo, FILE_ATTRIBUTE_NORMAL);
ok(ret, "Failure to set file attributes (error %x)\n", GetLastError());
shfo.fFlags = tmp_flags;
/* try to copy files to a file */
@ -1715,11 +1716,11 @@ static void test_copy(void)
{
ok(DeleteFileA("threedir\\two.txt"), "Expected file to exist\n");
ok(!DeleteFileA("fourdir"), "Expected file to not exist\n");
ok(!RemoveDirectoryA("fourdir"), "Expected dit to not exist\n");
ok(!RemoveDirectoryA("fourdir"), "Expected dir to not exist\n");
}
ok(RemoveDirectoryA("threedir"), "Expected dir to exist\n");
ok(!DeleteFileA("five"), "Expected file to not exist\n");
ok(!RemoveDirectoryA("five"), "Expected dit to not exist\n");
ok(!RemoveDirectoryA("five"), "Expected dir to not exist\n");
createTestFile("aa.txt");
createTestFile("ab.txt");
@ -2057,6 +2058,7 @@ static void test_sh_create_dir(void)
ok(ERROR_ALREADY_EXISTS == ret, "SHCreateDirectoryEx should fail to create existing directory, ret = %d\n", ret);
ret = pSHCreateDirectoryExA(NULL, "c:\\testdir3", NULL);
ok(ERROR_SUCCESS == ret, "SHCreateDirectoryEx failed to create directory, ret = %d\n", ret);
ok(file_exists("c:\\testdir3"), "The directory is not created\n");
}
@ -2065,6 +2067,7 @@ static void test_sh_path_prepare(void)
HRESULT res;
CHAR path[MAX_PATH];
CHAR UNICODE_PATH_A[MAX_PATH];
BOOL UsedDefaultChar;
if(!pSHPathPrepareForWriteA)
{
@ -2156,7 +2159,19 @@ static void test_sh_path_prepare(void)
win_skip("Skipping SHPathPrepareForWriteW tests\n");
return;
}
WideCharToMultiByte(CP_ACP, 0, UNICODE_PATH, -1, UNICODE_PATH_A, sizeof(UNICODE_PATH_A), NULL, NULL);
SetLastError(0xdeadbeef);
UsedDefaultChar = FALSE;
if (WideCharToMultiByte(CP_ACP, WC_NO_BEST_FIT_CHARS, UNICODE_PATH, -1, UNICODE_PATH_A, sizeof(UNICODE_PATH_A), NULL, &UsedDefaultChar) == 0)
{
win_skip("Could not convert Unicode path name to multibyte (%d)\n", GetLastError());
return;
}
if (UsedDefaultChar)
{
win_skip("Could not find unique multibyte representation for directory name using default codepage\n");
return;
}
/* unicode directory doesn't exist, SHPPFW_NONE */
RemoveDirectoryA(UNICODE_PATH_A);

File diff suppressed because it is too large Load diff

View file

@ -78,6 +78,16 @@ static HWND subclass_listview(HWND hwnd)
/* listview is a first child */
listview = FindWindowExA(hwnd, NULL, WC_LISTVIEWA, NULL);
if(!listview)
{
/* .. except for some versions of Windows XP, where things
are slightly more complicated. */
HWND hwnd_tmp;
hwnd_tmp = FindWindowExA(hwnd, NULL, "DUIViewWndClassName", NULL);
hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "DirectUIHWND", NULL);
hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "CtrlNotifySink", NULL);
listview = FindWindowExA(hwnd_tmp, NULL, WC_LISTVIEWA, NULL);
}
oldproc = (WNDPROC)SetWindowLongPtrA(listview, GWLP_WNDPROC,
(LONG_PTR)listview_subclass_proc);
@ -86,28 +96,71 @@ static HWND subclass_listview(HWND hwnd)
return listview;
}
static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message)
{
struct msg_sequence *msg_seq = seq[sequence_index];
UINT i, count = 0;
for(i = 0; i < msg_seq->count ; i++)
if(msg_seq->sequence[i].message == message)
count++;
return count;
}
/* Checks that every message in the sequence seq is also present in
* the UINT array msgs */
static void verify_msgs_in_(struct msg_sequence *seq, const UINT *msgs,
const char *file, int line)
{
UINT i, j, msg, failcount = 0;
for(i = 0; i < seq->count; i++)
{
BOOL found = FALSE;
msg = seq->sequence[i].message;
for(j = 0; msgs[j] != 0; j++)
if(msgs[j] == msg) found = TRUE;
if(!found)
{
failcount++;
trace("Unexpected message %d\n", msg);
}
}
ok_(file, line) (!failcount, "%d failures.\n", failcount);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
}
#define verify_msgs_in(seq, msgs) \
verify_msgs_in_(seq, msgs, __FILE__, __LINE__)
/* dummy IDataObject implementation */
typedef struct {
const IDataObjectVtbl *lpVtbl;
IDataObject IDataObject_iface;
LONG ref;
} IDataObjectImpl;
static const IDataObjectVtbl IDataObjectImpl_Vtbl;
static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface)
{
return CONTAINING_RECORD(iface, IDataObjectImpl, IDataObject_iface);
}
static IDataObject* IDataObjectImpl_Construct(void)
{
IDataObjectImpl *obj;
obj = HeapAlloc(GetProcessHeap(), 0, sizeof(*obj));
obj->lpVtbl = &IDataObjectImpl_Vtbl;
obj->IDataObject_iface.lpVtbl = &IDataObjectImpl_Vtbl;
obj->ref = 1;
return (IDataObject*)obj;
return &obj->IDataObject_iface;
}
static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObj)
{
IDataObjectImpl *This = (IDataObjectImpl *)iface;
IDataObjectImpl *This = impl_from_IDataObject(iface);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IDataObject))
@ -126,13 +179,13 @@ static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID
static ULONG WINAPI IDataObjectImpl_AddRef(IDataObject * iface)
{
IDataObjectImpl *This = (IDataObjectImpl *)iface;
IDataObjectImpl *This = impl_from_IDataObject(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IDataObjectImpl_Release(IDataObject * iface)
{
IDataObjectImpl *This = (IDataObjectImpl *)iface;
IDataObjectImpl *This = impl_from_IDataObject(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (!ref)
@ -210,28 +263,33 @@ static const IDataObjectVtbl IDataObjectImpl_Vtbl =
/* dummy IShellBrowser implementation */
typedef struct {
const IShellBrowserVtbl *lpVtbl;
IShellBrowser IShellBrowser_iface;
LONG ref;
} IShellBrowserImpl;
static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
{
return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface);
}
static IShellBrowser* IShellBrowserImpl_Construct(void)
{
IShellBrowserImpl *browser;
browser = HeapAlloc(GetProcessHeap(), 0, sizeof(*browser));
browser->lpVtbl = &IShellBrowserImpl_Vtbl;
browser->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl;
browser->ref = 1;
return (IShellBrowser*)browser;
return &browser->IShellBrowser_iface;
}
static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
REFIID riid,
LPVOID *ppvObj)
{
IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
*ppvObj = NULL;
@ -253,13 +311,13 @@ static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
{
IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
{
IShellBrowserImpl *This = (IShellBrowserImpl *)iface;
IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
ULONG ref = InterlockedDecrement(&This->ref);
if (!ref)
@ -423,7 +481,7 @@ static const struct message folderview_getselectionmarked_seq[] = {
};
static const struct message folderview_getfocused_seq[] = {
{ LVM_GETNEXTITEM, sent|wparam|lparam, -1, LVNI_FOCUSED },
{ LVM_GETNEXTITEM, sent|wparam|lparam|optional, -1, LVNI_FOCUSED },
{ 0 }
};
@ -451,7 +509,7 @@ static void test_IShellView_CreateViewWindow(void)
if (0)
{
/* crashes on native */
hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL);
IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL);
}
settings.ViewMode = FVM_ICON;
@ -487,7 +545,7 @@ static void test_IFolderView(void)
HWND hwnd_view, hwnd_list;
PITEMID_CHILD pidl;
HRESULT hr;
INT ret;
INT ret, count;
POINT pt;
LONG ref1, ref2;
RECT r;
@ -519,14 +577,14 @@ static void test_IFolderView(void)
if (0)
{
/* crashes on Vista and Win2k8 - List not created yet case */
hr = IFolderView_GetSpacing(fv, &pt);
IFolderView_GetSpacing(fv, &pt);
/* crashes on XP */
hr = IFolderView_GetSelectionMarkedItem(fv, NULL);
hr = IFolderView_GetFocusedItem(fv, NULL);
IFolderView_GetSelectionMarkedItem(fv, NULL);
IFolderView_GetFocusedItem(fv, NULL);
/* crashes on Vista+ */
hr = IFolderView_Item(fv, 0, NULL);
IFolderView_Item(fv, 0, NULL);
}
browser = IShellBrowserImpl_Construct();
@ -570,32 +628,48 @@ if (0)
ok(pt.x == LOWORD(ret) && pt.y == HIWORD(ret), "got (%d, %d)\n", LOWORD(ret), HIWORD(ret));
}
/* IFolderView::ItemCount */
if (0)
{
/* crashes on XP */
IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL);
}
flush_sequences(sequences, NUM_MSG_SEQUENCES);
IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &count);
/* IFolderView::GetSelectionMarkedItem */
if (0)
{
/* crashes on XP */
hr = IFolderView_GetSelectionMarkedItem(fv, NULL);
IFolderView_GetSelectionMarkedItem(fv, NULL);
}
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hr = IFolderView_GetSelectionMarkedItem(fv, &ret);
ok(hr == S_OK, "got (0x%08x)\n", hr);
if (count)
ok(hr == S_OK, "got (0x%08x)\n", hr);
else
ok(hr == S_FALSE, "got (0x%08x)\n", hr);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getselectionmarked_seq,
"IFolderView::GetSelectionMarkedItem", FALSE);
"IFolderView::GetSelectionMarkedItem", FALSE);
/* IFolderView::GetFocusedItem */
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hr = IFolderView_GetFocusedItem(fv, &ret);
ok(hr == S_OK, "got (0x%08x)\n", hr);
if (count)
ok(hr == S_OK, "got (0x%08x)\n", hr);
else
ok(hr == S_FALSE, "got (0x%08x)\n", hr);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getfocused_seq,
"IFolderView::GetFocusedItem", FALSE);
"IFolderView::GetFocusedItem", FALSE);
/* IFolderView::GetFolder, just return pointer */
if (0)
{
/* crashes on XP */
hr = IFolderView_GetFolder(fv, NULL, (void**)&folder);
hr = IFolderView_GetFolder(fv, NULL, NULL);
IFolderView_GetFolder(fv, NULL, (void**)&folder);
IFolderView_GetFolder(fv, NULL, NULL);
}
hr = IFolderView_GetFolder(fv, &IID_IShellFolder, NULL);
@ -607,22 +681,10 @@ if (0)
ok(hr == S_OK, "got (0x%08x)\n", hr);
ref2 = IShellFolder_AddRef(desktop);
IShellFolder_Release(desktop);
ok(ref1 == ref2, "expected same refcount, got %d\n", ref2);
ok(ref1 == ref2 || ref1 + 1 == ref2, /* >= vista */
"expected same refcount, got %d\n", ref2);
ok(desktop == folder, "\n");
/* IFolderView::ItemCount */
if (0)
{
/* crashes on XP */
hr = IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL);
}
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hr = IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &ret);
ok(hr == S_OK, "got (0x%08x)\n", hr);
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_itemcount_seq,
"IFolderView::ItemCount", FALSE);
IShellBrowser_Release(browser);
IFolderView_Release(fv);
IShellView_Release(view);
@ -711,9 +773,9 @@ static void test_IShellFolderView(void)
/* ::RemoveObject */
i = 0xdeadbeef;
hr = IShellFolderView_RemoveObject(folderview, NULL, &i);
ok(hr == S_OK, "got (0x%08x)\n", hr);
ok(i == 0 || i == -1 /* Win7 */ || broken(i == 0xdeadbeef) /* Vista, 2k8 */,
"got %d\n", i);
ok(hr == S_OK || hr == E_FAIL, "got (0x%08x)\n", hr);
if (hr == S_OK) ok(i == 0 || broken(i == 0xdeadbeef) /* Vista, 2k8 */,
"got %d\n", i);
IShellFolderView_Release(folderview);
@ -743,6 +805,352 @@ static void test_IOleWindow(void)
IShellFolder_Release(desktop);
}
static const struct message folderview_setcurrentviewmode1_2_prevista[] = {
{ LVM_SETVIEW, sent|wparam, LV_VIEW_ICON},
{ LVM_SETIMAGELIST, sent|wparam, 0},
{ LVM_SETIMAGELIST, sent|wparam, 1},
{ 0x105a, sent},
{ LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
{ LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
{ LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
{ LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
{ LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
{ LVM_ARRANGE, sent },
{ LVM_ARRANGE, sent|optional }, /* WinXP */
{ 0 }
};
static const struct message folderview_setcurrentviewmode3_prevista[] = {
{ LVM_SETVIEW, sent|wparam, LV_VIEW_LIST},
{ LVM_SETIMAGELIST, sent|wparam, 0},
{ LVM_SETIMAGELIST, sent|wparam, 1},
{ 0x105a, sent},
{ LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
{ LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
{ LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
{ LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
{ LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
{ 0 }
};
static const struct message folderview_setcurrentviewmode4_prevista[] = {
{ LVM_GETHEADER, sent},
{ LVM_GETITEMCOUNT, sent|optional },
{ LVM_SETSELECTEDCOLUMN, sent},
{ WM_NOTIFY, sent },
{ WM_NOTIFY, sent },
{ WM_NOTIFY, sent },
{ WM_NOTIFY, sent },
{ LVM_SETVIEW, sent|wparam, LV_VIEW_DETAILS},
{ LVM_SETIMAGELIST, sent|wparam, 0},
{ LVM_SETIMAGELIST, sent|wparam, 1},
{ 0x105a, sent},
{ LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
{ LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
{ LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
{ LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
{ LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
{ 0 }
};
/* XP, SetCurrentViewMode(5)
108e - LVM_SETVIEW (LV_VIEW_ICON);
1036 - LVM_SETEXTEDEDLISTVIEWSTYLE (0x8000, 0)
100c/104c repeated X times
1003 - LVM_SETIMAGELIST
1035 - LVM_SETICONSPACING
1004 - LVM_GETITEMCOUNT
105a - ?
1016 - LVM_ARRANGE
1016 - LVM_ARRANGE
*/
/* XP, SetCurrentViewMode(6)
1036 - LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0)
1035 - LVM_SETICONSPACING
1003 - LVM_SETIMAGELIST
1003 - LVM_SETIMAGELIST
100c/104c repeated X times
10a2 - LVM_SETTILEVIEWINFO
108e - LVM_SETVIEW (LV_VIEW_TILE)
1003 - LVM_SETIMAGELIST
105a - ?
1016 - LVM_ARRANGE
1016 - LVM_ARRANGE
*/
/* XP, SetCurrentViewMode (7)
10a2 - LVM_SETTILEVIEWINFO
108e - LVM_SETVIEW (LV_VIEW_ICON)
1004/10a4 (LVM_GETITEMCOUNT/LVM_SETTILEINFO) X times
1016 - LVM_ARRANGE
1016 - LVM_ARRANGE
...
LVM_SETEXTENDEDLISTVIEWSTYLE (0x40000, 0x40000)
...
LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0x8000)
*/
static void test_GetSetCurrentViewMode(void)
{
IShellFolder *desktop;
IShellView *sview;
IFolderView *fview;
IShellBrowser *browser;
FOLDERSETTINGS fs;
UINT viewmode;
HWND hwnd;
RECT rc = {0, 0, 10, 10};
HRESULT hr;
UINT i;
static const int winxp_res[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
static const int win2k3_res[11] = {0, 1, 2, 3, 4, 5, 6, 5, 8, 0, 0};
static const int vista_res[11] = {0, 1, 5, 3, 4, 5, 6, 7, 7, 0, 0};
static const int win7_res[11] = {1, 1, 1, 3, 4, 1, 6, 1, 8, 8, 8};
hr = SHGetDesktopFolder(&desktop);
ok(hr == S_OK, "got (0x%08x)\n", hr);
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&sview);
ok(hr == S_OK, "got (0x%08x)\n", hr);
fs.ViewMode = 1;
fs.fFlags = 0;
browser = IShellBrowserImpl_Construct();
hr = IShellView_CreateViewWindow(sview, NULL, &fs, browser, &rc, &hwnd);
ok(hr == S_OK || broken(hr == S_FALSE /*Win2k*/ ), "got (0x%08x)\n", hr);
hr = IShellView_QueryInterface(sview, &IID_IFolderView, (void**)&fview);
ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got (0x%08x)\n", hr);
if(SUCCEEDED(hr))
{
HWND hwnd_lv;
UINT count;
if (0)
{
/* Crashes under Win7/WinXP */
IFolderView_GetCurrentViewMode(fview, NULL);
}
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
ok(hr == S_OK, "got (0x%08x)\n", hr);
ok(viewmode == 1, "ViewMode was %d\n", viewmode);
hr = IFolderView_SetCurrentViewMode(fview, FVM_AUTO);
ok(hr == S_OK, "got (0x%08x)\n", hr);
hr = IFolderView_SetCurrentViewMode(fview, 0);
ok(hr == E_INVALIDARG || broken(hr == S_OK),
"got (0x%08x)\n", hr);
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
ok(hr == S_OK, "got (0x%08x)\n", hr);
for(i = 1; i < 9; i++)
{
hr = IFolderView_SetCurrentViewMode(fview, i);
ok(hr == S_OK || (i == 8 && hr == E_INVALIDARG /*Vista*/),
"(%d) got (0x%08x)\n", i, hr);
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
ok(hr == S_OK, "(%d) got (0x%08x)\n", i, hr);
/* Wine currently behaves like winxp here. */
ok((viewmode == win7_res[i]) || (viewmode == vista_res[i]) ||
(viewmode == win2k3_res[i]) || (viewmode == winxp_res[i]),
"(%d) got %d\n",i , viewmode);
}
hr = IFolderView_SetCurrentViewMode(fview, 9);
ok(hr == E_INVALIDARG || broken(hr == S_OK),
"got (0x%08x)\n", hr);
/* Test messages */
hwnd_lv = subclass_listview(hwnd);
ok(hwnd_lv != NULL, "Failed to subclass listview\n");
if(hwnd_lv)
{
/* Vista seems to set the viewmode by other means than
sending messages. At least no related messages are
captured by subclassing.
*/
BOOL vista_plus = FALSE;
static const UINT vista_plus_msgs[] = {
WM_SETREDRAW, WM_NOTIFY, WM_NOTIFYFORMAT, WM_QUERYUISTATE,
WM_MENUCHAR, WM_WINDOWPOSCHANGING, WM_NCCALCSIZE, WM_WINDOWPOSCHANGED,
WM_PARENTNOTIFY, LVM_GETHEADER, 0 };
flush_sequences(sequences, NUM_MSG_SEQUENCES);
hr = IFolderView_SetCurrentViewMode(fview, 1);
ok(hr == S_OK, "got 0x%08x\n", hr);
/* WM_SETREDRAW is not sent in versions before Vista. */
vista_plus = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, WM_SETREDRAW);
if(vista_plus)
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
else
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista,
"IFolderView::SetCurrentViewMode(1)", TRUE);
hr = IFolderView_SetCurrentViewMode(fview, 2);
ok(hr == S_OK, "got 0x%08x\n", hr);
if(vista_plus)
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
else
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista,
"IFolderView::SetCurrentViewMode(2)", TRUE);
hr = IFolderView_SetCurrentViewMode(fview, 3);
ok(hr == S_OK, "got 0x%08x\n", hr);
if(vista_plus)
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
else
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode3_prevista,
"IFolderView::SetCurrentViewMode(3)", TRUE);
hr = IFolderView_SetCurrentViewMode(fview, 4);
ok(hr == S_OK, "got 0x%08x\n", hr);
if(vista_plus)
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
else
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode4_prevista,
"IFolderView::SetCurrentViewMode(4)", TRUE);
hr = IFolderView_SetCurrentViewMode(fview, 5);
ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine
{
if(vista_plus)
{
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
}
else
{
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
}
}
hr = IFolderView_SetCurrentViewMode(fview, 6);
ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine
{
if(vista_plus)
{
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
}
else
{
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
}
}
hr = IFolderView_SetCurrentViewMode(fview, 7);
ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine
{
if(vista_plus)
{
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
}
else
{
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
}
}
hr = IFolderView_SetCurrentViewMode(fview, 8);
ok(hr == S_OK || broken(hr == E_INVALIDARG /* Vista */), "got 0x%08x\n", hr);
todo_wine
{
if(vista_plus)
{
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
}
else
{
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
}
}
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
ok(hr == S_OK, "Failed to get current viewmode.\n");
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq,
"IFolderView::GetCurrentViewMode", FALSE);
}
IFolderView_Release(fview);
}
else
{
skip("No IFolderView for the desktop folder.\n");
}
IShellBrowser_Release(browser);
IShellView_DestroyViewWindow(sview);
IShellView_Release(sview);
IShellFolder_Release(desktop);
}
static void test_IOleCommandTarget(void)
{
IShellFolder *psf_desktop;
IShellView *psv;
IOleCommandTarget *poct;
HRESULT hr;
hr = SHGetDesktopFolder(&psf_desktop);
ok(hr == S_OK, "got (0x%08x)\n", hr);
hr = IShellFolder_CreateViewObject(psf_desktop, NULL, &IID_IShellView, (void**)&psv);
ok(hr == S_OK, "got (0x%08x)\n", hr);
if(SUCCEEDED(hr))
{
hr = IShellView_QueryInterface(psv, &IID_IOleCommandTarget, (void**)&poct);
ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win95/NT4 */, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
OLECMD oc;
hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, NULL, NULL);
ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr);
oc.cmdID = 1;
hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, &oc, NULL);
ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08x\n", hr);
oc.cmdID = 1;
hr = IOleCommandTarget_QueryStatus(poct, NULL, 1, &oc, NULL);
ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08x\n", hr);
hr = IOleCommandTarget_Exec(poct, NULL, 0, 0, NULL, NULL);
ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08x\n", hr);
IOleCommandTarget_Release(poct);
}
IShellView_Release(psv);
}
IShellFolder_Release(psf_desktop);
}
START_TEST(shlview)
{
OleInitialize(NULL);
@ -754,6 +1162,8 @@ START_TEST(shlview)
test_GetItemObject();
test_IShellFolderView();
test_IOleWindow();
test_GetSetCurrentViewMode();
test_IOleCommandTarget();
OleUninitialize();
}

View file

@ -45,19 +45,15 @@ static void test_cbsize(void)
nidW.hIcon = LoadIcon(NULL, IDI_APPLICATION);
nidW.uCallbackMessage = WM_USER+17;
ret = pShell_NotifyIconW(NIM_ADD, &nidW);
if (ret)
{
/* using an invalid cbSize does work */
nidW.cbSize = 3;
nidW.hWnd = hMainWnd;
nidW.uID = 1;
ret = pShell_NotifyIconW(NIM_DELETE, &nidW);
ok( ret || broken(!ret), /* nt4 */ "NIM_DELETE failed!\n");
/* as icon doesn't exist anymore - now there will be an error */
nidW.cbSize = sizeof(nidW);
ok(!pShell_NotifyIconW(NIM_DELETE, &nidW) != !ret, "The icon was not deleted\n");
}
else win_skip( "Shell_NotifyIconW not working\n" ); /* win9x */
/* using an invalid cbSize does work */
nidW.cbSize = 3;
nidW.hWnd = hMainWnd;
nidW.uID = 1;
ret = pShell_NotifyIconW(NIM_DELETE, &nidW);
ok( ret || broken(!ret), /* nt4 */ "NIM_DELETE failed!\n");
/* as icon doesn't exist anymore - now there will be an error */
nidW.cbSize = sizeof(nidW);
ok(!pShell_NotifyIconW(NIM_DELETE, &nidW) != !ret, "The icon was not deleted\n");
}
/* same for Shell_NotifyIconA */
@ -75,7 +71,7 @@ static void test_cbsize(void)
nidA.hWnd = hMainWnd;
nidA.uID = 1;
ret = Shell_NotifyIconA(NIM_DELETE, &nidA);
ok( ret || broken(!ret), /* win9x */ "NIM_DELETE failed!\n");
ok(ret, "NIM_DELETE failed!\n");
/* as icon doesn't exist anymore - now there will be an error */
nidA.cbSize = sizeof(nidA);
ok(!Shell_NotifyIconA(NIM_DELETE, &nidA) != !ret, "The icon was not deleted\n");

View file

@ -8,9 +8,14 @@
extern void func_appbar(void);
extern void func_autocomplete(void);
extern void func_brsfolder(void);
extern void func_ebrowser(void);
extern void func_generated(void);
extern void func_progman_dde(void);
extern void func_recyclebin(void);
extern void func_shelldispatch(void);
extern void func_shelllink(void);
extern void func_shellole(void);
extern void func_shellpath(void);
extern void func_shfldr_special(void);
extern void func_shlexec(void);
@ -22,17 +27,22 @@ extern void func_systray(void);
const struct test winetest_testlist[] =
{
{ "appbar", func_appbar },
{ "autocomplete", func_autocomplete },
{ "generated", func_generated },
{ "progman_dde", func_progman_dde },
{ "appbar", func_appbar },
{ "autocomplete", func_autocomplete },
{ "brsfolder", func_brsfolder },
{ "ebrowser", func_ebrowser },
{ "generated", func_generated },
{ "progman_dde", func_progman_dde },
{ "recyclebin", func_recyclebin },
{ "shelldispatch", func_shelldispatch },
{ "shelllink", func_shelllink },
{ "shellole", func_shellole },
{ "shellpath", func_shellpath },
{ "shfldr_special", func_shfldr_special },
{ "shfldr_special", func_shfldr_special },
{ "shlexec", func_shlexec },
{ "shlfileop", func_shlfileop },
{ "shlfolder", func_shlfolder },
{ "shlview", func_shlview },
{ "shlview", func_shlview },
{ "string", func_string },
{ "systray", func_systray },
{ 0, 0 }