Sweden-Number/dlls/explorerframe/tests/nstc.c

2383 lines
86 KiB
C

/*
* Unit tests for the NamespaceTree Control
*
* Copyright 2010 David Hedberg
*
* 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 <stdio.h>
#define COBJMACROS
#include "shlobj.h"
#include "wine/test.h"
#include "msg.h"
static HWND hwnd;
/* "Intended for internal use" */
#define TVS_EX_NOSINGLECOLLAPSE 0x1
static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
static HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*);
static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**);
static HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *);
#define NUM_MSG_SEQUENCES 1
#define TREEVIEW_SEQ_INDEX 0
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
/* Keep a copy of the last structure passed by TVM_SETITEMW */
static TVITEMEXW last_tvi;
static int tvi_count;
static void init_function_pointers(void)
{
HMODULE hmod;
hmod = GetModuleHandleA("shell32.dll");
pSHCreateShellItem = (void*)GetProcAddress(hmod, "SHCreateShellItem");
pSHGetIDListFromObject = (void*)GetProcAddress(hmod, "SHGetIDListFromObject");
pSHCreateItemFromParsingName = (void*)GetProcAddress(hmod, "SHCreateItemFromParsingName");
pSHGetSpecialFolderLocation = (void*)GetProcAddress(hmod, "SHGetSpecialFolderLocation");
}
/*******************************************************
* INameSpaceTreeControlEvents implementation.
*/
enum { OnItemClick = 0, OnPropertyItemCommit, OnItemStateChanging, OnItemStateChanged,
OnSelectionChanged, OnKeyboardInput, OnBeforeExpand, OnAfterExpand, OnBeginLabelEdit,
OnEndLabelEdit, OnGetToolTip, OnBeforeItemDelete, OnItemAdded, OnItemDeleted,
OnBeforeContextMenu, OnAfterContextMenu, OnBeforeStateImageChange, OnGetDefaultIconIndex,
LastEvent };
typedef struct {
const INameSpaceTreeControlEventsVtbl *lpVtbl;
UINT qi_called_count; /* Keep track of calls to QueryInterface */
BOOL qi_enable_events; /* If FALSE, QueryInterface returns only E_NOINTERFACE */
UINT count[LastEvent]; /* Keep track of calls to all On* functions. */
LONG ref;
} INameSpaceTreeControlEventsImpl;
#define NSTCE_IMPL(iface) \
((INameSpaceTreeControlEventsImpl*)iface)
static HRESULT WINAPI NSTCEvents_fnQueryInterface(
INameSpaceTreeControlEvents* iface,
REFIID riid,
void **ppvObject)
{
NSTCE_IMPL(iface)->qi_called_count++;
if(NSTCE_IMPL(iface)->qi_enable_events &&
IsEqualIID(riid, &IID_INameSpaceTreeControlEvents))
{
IUnknown_AddRef(iface);
*ppvObject = iface;
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI NSTCEvents_fnAddRef(
INameSpaceTreeControlEvents* iface)
{
return InterlockedIncrement(&NSTCE_IMPL(iface)->ref);
}
static ULONG WINAPI NSTCEvents_fnRelease(
INameSpaceTreeControlEvents* iface)
{
return InterlockedDecrement(&NSTCE_IMPL(iface)->ref);
}
static HRESULT WINAPI NSTCEvents_fnOnItemClick(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
NSTCEHITTEST nstceHitTest,
NSTCECLICKTYPE nstceClickType)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnItemClick]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnPropertyItemCommit(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnPropertyItemCommit]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnItemStateChanging(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
NSTCITEMSTATE nstcisMask,
NSTCITEMSTATE nstcisState)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnItemStateChanging]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnItemStateChanged(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
NSTCITEMSTATE nstcisMask,
NSTCITEMSTATE nstcisState)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnItemStateChanged]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnSelectionChanged(
INameSpaceTreeControlEvents* iface,
IShellItemArray *psiaSelection)
{
ok(psiaSelection != NULL, "IShellItemArray was NULL.\n");
if(psiaSelection)
{
HRESULT hr;
DWORD count = 0xdeadbeef;
hr = IShellItemArray_GetCount(psiaSelection, &count);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(count == 1, "Got count 0x%x\n", count);
}
NSTCE_IMPL(iface)->count[OnSelectionChanged]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnKeyboardInput(
INameSpaceTreeControlEvents* iface,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
NSTCE_IMPL(iface)->count[OnKeyboardInput]++;
ok(wParam == 0x1234, "Got unexpected wParam %lx\n", wParam);
ok(lParam == 0x1234, "Got unexpected lParam %lx\n", lParam);
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnBeforeExpand(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnBeforeExpand]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnAfterExpand(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnAfterExpand]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnBeginLabelEdit(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnBeginLabelEdit]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnEndLabelEdit(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnEndLabelEdit]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnGetToolTip(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
LPWSTR pszTip,
int cchTip)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnGetToolTip]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnBeforeItemDelete(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnBeforeItemDelete]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnItemAdded(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
BOOL fIsRoot)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnItemAdded]++;
return S_OK;
}
static HRESULT WINAPI NSTCEvents_fnOnItemDeleted(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
BOOL fIsRoot)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnItemDeleted]++;
return S_OK;
}
static HRESULT WINAPI NSTCEvents_fnOnBeforeContextMenu(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
REFIID riid,
void **ppv)
{
NSTCE_IMPL(iface)->count[OnBeforeContextMenu]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnAfterContextMenu(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
IContextMenu *pcmIn,
REFIID riid,
void **ppv)
{
NSTCE_IMPL(iface)->count[OnAfterContextMenu]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnBeforeStateImageChange(
INameSpaceTreeControlEvents* iface,
IShellItem *psi)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnBeforeStateImageChange]++;
return E_NOTIMPL;
}
static HRESULT WINAPI NSTCEvents_fnOnGetDefaultIconIndex(
INameSpaceTreeControlEvents* iface,
IShellItem *psi,
int *piDefaultIcon,
int *piOpenIcon)
{
ok(psi != NULL, "NULL IShellItem\n");
NSTCE_IMPL(iface)->count[OnGetDefaultIconIndex]++;
return E_NOTIMPL;
}
static const INameSpaceTreeControlEventsVtbl vt_NSTCEvents = {
NSTCEvents_fnQueryInterface,
NSTCEvents_fnAddRef,
NSTCEvents_fnRelease,
NSTCEvents_fnOnItemClick,
NSTCEvents_fnOnPropertyItemCommit,
NSTCEvents_fnOnItemStateChanging,
NSTCEvents_fnOnItemStateChanged,
NSTCEvents_fnOnSelectionChanged,
NSTCEvents_fnOnKeyboardInput,
NSTCEvents_fnOnBeforeExpand,
NSTCEvents_fnOnAfterExpand,
NSTCEvents_fnOnBeginLabelEdit,
NSTCEvents_fnOnEndLabelEdit,
NSTCEvents_fnOnGetToolTip,
NSTCEvents_fnOnBeforeItemDelete,
NSTCEvents_fnOnItemAdded,
NSTCEvents_fnOnItemDeleted,
NSTCEvents_fnOnBeforeContextMenu,
NSTCEvents_fnOnAfterContextMenu,
NSTCEvents_fnOnBeforeStateImageChange,
NSTCEvents_fnOnGetDefaultIconIndex
};
#undef NSTCE_IMPL
static INameSpaceTreeControlEventsImpl *create_nstc_events(void)
{
INameSpaceTreeControlEventsImpl *This;
This = HeapAlloc(GetProcessHeap(), 0, sizeof(INameSpaceTreeControlEventsImpl));
This->lpVtbl = &vt_NSTCEvents;
This->ref = 1;
return This;
}
/*********************************************************************
* Event count checking
*/
static void ok_no_events_(INameSpaceTreeControlEventsImpl *impl,
const char *file, int line)
{
UINT i;
for(i = 0; i < LastEvent; i++)
{
ok_(file, line)
(!impl->count[i], "Got event %d, count %d\n", i, impl->count[i]);
impl->count[i] = 0;
}
}
#define ok_no_events(impl) \
ok_no_events_(impl, __FILE__, __LINE__)
#define ok_event_count_broken(impl, event, c, b) \
do { ok(impl->count[event] == c || broken(impl->count[event] == b), \
"Got event %d, count %d\n", event, impl->count[event]); \
impl->count[event] = 0; \
} while(0)
#define ok_event_count(impl, event, c) \
ok_event_count_broken(impl, event, c, -1)
#define ok_event_broken(impl, event) \
do { ok(impl->count[event] || broken(!impl->count[event]), \
"No event.\n"); \
impl->count[event] = 0; \
} while(0)
#define ok_event(impl, event) \
do { ok(impl->count[event], "No event %d.\n", event); \
impl->count[event] = 0; \
} while(0)
/* Process some messages */
static void process_msgs(void)
{
MSG msg;
BOOL got_msg;
do {
got_msg = FALSE;
Sleep(100);
while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
got_msg = TRUE;
}
} while(got_msg);
/* There seem to be a timer that sometimes fires after about
500ms, we need to wait for it. Failing to wait can result in
seemingly sporadic selection change events. (Timer ID is 87,
sending WM_TIMER manually does not seem to help us.) */
Sleep(500);
while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
/** Some functions from shell32/tests/shlfolder.c */
/* creates a file with the specified name for tests */
static void CreateTestFile(const CHAR *name)
{
HANDLE file;
DWORD written;
file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
if (file != INVALID_HANDLE_VALUE)
{
WriteFile(file, name, strlen(name), &written, NULL);
WriteFile(file, "\n", strlen("\n"), &written, NULL);
CloseHandle(file);
}
}
/* initializes the tests */
static void CreateFilesFolders(void)
{
CreateDirectoryA(".\\testdir", NULL);
CreateTestFile (".\\testdir\\test1.txt ");
CreateTestFile (".\\testdir\\test2.txt ");
CreateTestFile (".\\testdir\\test3.txt ");
CreateDirectoryA(".\\testdir\\testdir2 ", NULL);
CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL);
}
/* cleans after tests */
static void Cleanup(void)
{
DeleteFileA(".\\testdir\\test1.txt");
DeleteFileA(".\\testdir\\test2.txt");
DeleteFileA(".\\testdir\\test3.txt");
RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
RemoveDirectoryA(".\\testdir\\testdir2");
RemoveDirectoryA(".\\testdir");
}
/* Based on PathAddBackslashW from dlls/shlwapi/path.c */
static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
{
size_t iLen;
if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
return NULL;
if (iLen)
{
lpszPath += iLen;
if (lpszPath[-1] != '\\')
{
*lpszPath++ = '\\';
*lpszPath = '\0';
}
}
return lpszPath;
}
static HWND get_treeview_hwnd(INameSpaceTreeControl *pnstc)
{
IOleWindow *pow;
HRESULT hr;
HWND treeview = NULL;
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
HWND host;
hr = IOleWindow_GetWindow(pow, &host);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
treeview = FindWindowExW(host, NULL, WC_TREEVIEWW, NULL);
IOleWindow_Release(pow);
}
return treeview;
}
static LRESULT WINAPI treeview_subclass_proc(HWND hwnd_tv, UINT message, WPARAM wParam, LPARAM lParam)
{
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrW(hwnd_tv, GWLP_USERDATA);
static LONG defwndproc_counter = 0;
LRESULT ret;
struct message msg;
msg.message = message;
msg.flags = sent|wparam|lparam;
if (defwndproc_counter) msg.flags |= defwinproc;
msg.wParam = wParam;
msg.lParam = lParam;
msg.id = 0;
add_message(sequences, TREEVIEW_SEQ_INDEX, &msg);
if(message == TVM_SETITEMW)
{
memcpy(&last_tvi, (void*)lParam, sizeof(TVITEMEXW));
tvi_count++;
}
defwndproc_counter++;
ret = CallWindowProcW(oldproc, hwnd_tv, message, wParam, lParam);
defwndproc_counter--;
return ret;
}
static BOOL subclass_treeview(INameSpaceTreeControl *pnstc)
{
HWND hwnd_tv;
WNDPROC oldproc = NULL;
hwnd_tv = get_treeview_hwnd(pnstc);
if(hwnd_tv)
{
oldproc = (WNDPROC)SetWindowLongPtrW(hwnd_tv, GWLP_WNDPROC,
(LONG_PTR)treeview_subclass_proc);
SetWindowLongPtrW(hwnd_tv, GWLP_USERDATA, (LONG_PTR)oldproc);
ok(oldproc != NULL, "Failed to subclass.\n");
}
return oldproc?TRUE:FALSE;
}
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;
}
/* Returns FALSE if the NamespaceTreeControl failed to be instantiated. */
static BOOL test_initialization(void)
{
INameSpaceTreeControl *pnstc;
IOleWindow *pow;
IUnknown *punk;
HWND hwnd_host1;
LONG lres;
HRESULT hr;
RECT rc;
hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
&IID_INameSpaceTreeControl, (void**)&pnstc);
ok(hr == S_OK || hr == REGDB_E_CLASSNOTREG, "Got 0x%08x\n", hr);
if(FAILED(hr))
{
return FALSE;
}
hr = INameSpaceTreeControl_Initialize(pnstc, NULL, NULL, 0);
ok(hr == HRESULT_FROM_WIN32(ERROR_TLW_WITH_WSCHILD), "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_Initialize(pnstc, (HWND)0xDEADBEEF, NULL, 0);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE), "Got (0x%08x)\n", hr);
ZeroMemory(&rc, sizeof(RECT));
hr = INameSpaceTreeControl_Initialize(pnstc, NULL, &rc, 0);
ok(hr == HRESULT_FROM_WIN32(ERROR_TLW_WITH_WSCHILD), "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_Initialize(pnstc, (HWND)0xDEADBEEF, &rc, 0);
ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE), "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
if(SUCCEEDED(hr))
{
hr = IOleWindow_GetWindow(pow, &hwnd_host1);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(hwnd_host1 == NULL, "hwnd is not null.\n");
hr = IOleWindow_ContextSensitiveHelp(pow, TRUE);
ok(hr == E_NOTIMPL, "Got (0x%08x)\n", hr);
hr = IOleWindow_ContextSensitiveHelp(pow, FALSE);
ok(hr == E_NOTIMPL, "Got (0x%08x)\n", hr);
IOleWindow_Release(pow);
}
hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, NULL, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
static const CHAR namespacetree[] = "NamespaceTreeControl";
char buf[1024];
LONG style, expected_style;
HWND hwnd_tv;
hr = IOleWindow_GetWindow(pow, &hwnd_host1);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(hwnd_host1 != NULL, "hwnd_host1 is null.\n");
buf[0] = '\0';
GetClassNameA(hwnd_host1, buf, 1024);
ok(!lstrcmpA(namespacetree, buf), "Class name was %s\n", buf);
expected_style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
style = GetWindowLongPtrW(hwnd_host1, GWL_STYLE);
ok(style == expected_style, "Got style %08x\n", style);
expected_style = 0;
style = GetWindowLongPtrW(hwnd_host1, GWL_EXSTYLE);
ok(style == expected_style, "Got style %08x\n", style);
expected_style = 0;
style = SendMessageW(hwnd_host1, TVM_GETEXTENDEDSTYLE, 0, 0);
ok(style == expected_style, "Got 0x%08x\n", style);
hwnd_tv = FindWindowExW(hwnd_host1, NULL, WC_TREEVIEWW, NULL);
ok(hwnd_tv != NULL, "Failed to get treeview hwnd.\n");
if(hwnd_tv)
{
expected_style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | WS_TABSTOP | TVS_NOHSCROLL |
TVS_NONEVENHEIGHT | TVS_INFOTIP | TVS_TRACKSELECT | TVS_EDITLABELS;
style = GetWindowLongPtrW(hwnd_tv, GWL_STYLE);
ok(style == expected_style, "Got style %08x\n", style);
expected_style = 0;
style = GetWindowLongPtrW(hwnd_tv, GWL_EXSTYLE);
ok(style == expected_style, "Got style %08x\n", style);
expected_style = TVS_EX_NOSINGLECOLLAPSE | TVS_EX_DOUBLEBUFFER |
TVS_EX_RICHTOOLTIP | TVS_EX_DRAWIMAGEASYNC;
style = SendMessageW(hwnd_tv, TVM_GETEXTENDEDSTYLE, 0, 0);
todo_wine ok(style == expected_style, "Got 0x%08x\n", style);
}
IOleWindow_Release(pow);
}
if(0)
{
/* The control can be initialized again without crashing, but
* the reference counting will break. */
hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, &rc, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
if(SUCCEEDED(hr))
{
HWND hwnd_host2;
hr = IOleWindow_GetWindow(pow, &hwnd_host2);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(hwnd_host1 != hwnd_host2, "Same hwnd.\n");
IOleWindow_Release(pow);
}
}
/* Some "random" interfaces */
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceObject, (void**)&punk);
ok(hr == E_NOINTERFACE || hr == S_OK /* vista, w2k8 */, "Got (0x%08x)\n", hr);
if(SUCCEEDED(hr)) IUnknown_Release(punk);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceActiveObject, (void**)&punk);
ok(hr == E_NOINTERFACE || hr == S_OK /* vista, w2k8 */, "Got (0x%08x)\n", hr);
if(SUCCEEDED(hr)) IUnknown_Release(punk);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceObjectWindowless, (void**)&punk);
ok(hr == E_NOINTERFACE || hr == S_OK /* vista, w2k8 */, "Got (0x%08x)\n", hr);
if(SUCCEEDED(hr)) IUnknown_Release(punk);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceUIWindow, (void**)&punk);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceFrame, (void**)&punk);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceSite, (void**)&punk);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceSiteEx, (void**)&punk);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceSiteWindowless, (void**)&punk);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
/* On windows, the reference count won't go to zero until the
* window is destroyed. */
INameSpaceTreeControl_AddRef(pnstc);
lres = INameSpaceTreeControl_Release(pnstc);
ok(lres > 1, "Reference count was (%d).\n", lres);
DestroyWindow(hwnd_host1);
lres = INameSpaceTreeControl_Release(pnstc);
ok(!lres, "lres was %d\n", lres);
return TRUE;
}
static void verify_root_order_(INameSpaceTreeControl *pnstc, IShellItem **roots,
const char *file, int line)
{
HRESULT hr;
IShellItemArray *psia;
hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
ok_(file,line) (hr == S_OK, "GetRootItems: got (0x%08x)\n", hr);
if(SUCCEEDED(hr))
{
DWORD i, expected, count = -1;
hr = IShellItemArray_GetCount(psia, &count);
ok_(file,line) (hr == S_OK, "Got (0x%08x)\n", hr);
for(expected = 0; roots[expected] != NULL; expected++);
ok_(file,line) (count == expected, "Got %d roots, expected %d\n", count, expected);
for(i = 0; i < count && roots[i] != NULL; i++)
{
IShellItem *psi;
hr = IShellItemArray_GetItemAt(psia, i, &psi);
ok_(file,line) (hr == S_OK, "GetItemAt %i: got 0x%08x\n", i, hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, roots[i], SICHINT_DISPLAY, &cmp);
ok_(file,line) (hr == S_OK, "Compare %i: got 0x%08x\n", i, hr);
IShellItem_Release(psi);
}
}
IShellItem_Release(psia);
}
}
#define verify_root_order(pnstc, psi_a) \
verify_root_order_(pnstc, psi_a, __FILE__, __LINE__)
static void test_basics(void)
{
INameSpaceTreeControl *pnstc;
INameSpaceTreeControl2 *pnstc2;
IShellItemArray *psia;
IShellFolder *psfdesktop;
IShellItem *psi;
IShellItem *psidesktop, *psidesktop2;
IShellItem *psitestdir, *psitestdir2, *psitest1;
IOleWindow *pow;
LPITEMIDLIST pidl_desktop;
NSTCITEMSTATE istate;
HRESULT hr;
UINT i, res, height;
HWND hwnd_tv;
RECT rc;
IShellItem *roots[10];
POINT pt;
int cbstate;
WCHAR curdirW[MAX_PATH];
WCHAR buf[MAX_PATH];
static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0};
static const WCHAR testdir2W[] =
{'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
static const WCHAR test1W[] =
{'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
static const WCHAR explorerW[] = {'E','x','p','l','o','r','e','r',0};
static const WCHAR randomW[] = {'_','_','h','e','l','l','o',0};
/* These should exist on platforms supporting the NSTC */
ok(pSHCreateShellItem != NULL, "No SHCreateShellItem.\n");
ok(pSHCreateItemFromParsingName != NULL, "No SHCreateItemFromParsingName\n");
ok(pSHGetIDListFromObject != NULL, "No SHCreateShellItem.\n");
ok(pSHCreateItemFromParsingName != NULL, "No SHCreateItemFromParsingName\n");
/* Create ShellItems for testing. */
SHGetDesktopFolder(&psfdesktop);
hr = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl_desktop);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(FAILED(hr)) IShellItem_Release(psidesktop);
}
ILFree(pidl_desktop);
}
ok(psidesktop != psidesktop2, "psidesktop == psidesktop2\n");
IShellFolder_Release(psfdesktop);
if(FAILED(hr))
{
win_skip("Test setup failed.\n");
return;
}
CreateFilesFolders();
GetCurrentDirectoryW(MAX_PATH, curdirW);
ok(lstrlenW(curdirW), "Got 0 length string.\n");
lstrcpyW(buf, curdirW);
myPathAddBackslashW(buf);
lstrcatW(buf, testdirW);
hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psitestdir);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(FAILED(hr)) goto cleanup;
lstrcpyW(buf, curdirW);
myPathAddBackslashW(buf);
lstrcatW(buf, testdir2W);
hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psitestdir2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(FAILED(hr)) goto cleanup;
lstrcpyW(buf, curdirW);
myPathAddBackslashW(buf);
lstrcatW(buf, test1W);
hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psitest1);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(FAILED(hr)) goto cleanup;
hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
&IID_INameSpaceTreeControl, (void**)&pnstc);
ok(hr == S_OK, "Failed to initialize control (0x%08x)\n", hr);
/* Some tests on an uninitialized control */
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveRoot(pnstc, NULL);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
process_msgs();
/* Initialize the control */
rc.top = rc.left = 0; rc.right = rc.bottom = 200;
hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, &rc, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
/* Set/GetControlStyle(2) */
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_INameSpaceTreeControl2, (void**)&pnstc2);
ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
DWORD tmp;
NSTCSTYLE style;
NSTCSTYLE2 style2;
static const NSTCSTYLE2 styles2[] =
{ NSTCS2_INTERRUPTNOTIFICATIONS,NSTCS2_SHOWNULLSPACEMENU,
NSTCS2_DISPLAYPADDING,NSTCS2_DISPLAYPINNEDONLY,
NTSCS2_NOSINGLETONAUTOEXPAND,NTSCS2_NEVERINSERTNONENUMERATED, 0};
/* We can use this to differentiate between two versions of
* this interface. Windows 7 returns hr == S_OK. */
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0, 0);
ok(hr == S_OK || broken(hr == E_FAIL), "Got 0x%08x\n", hr);
if(hr == S_OK)
{
static const NSTCSTYLE styles_setable[] =
{ NSTCS_HASEXPANDOS,NSTCS_HASLINES,NSTCS_SINGLECLICKEXPAND,
NSTCS_FULLROWSELECT,NSTCS_HORIZONTALSCROLL,
NSTCS_ROOTHASEXPANDO,NSTCS_SHOWSELECTIONALWAYS,NSTCS_NOINFOTIP,
NSTCS_EVENHEIGHT,NSTCS_NOREPLACEOPEN,NSTCS_DISABLEDRAGDROP,
NSTCS_NOORDERSTREAM,NSTCS_BORDER,NSTCS_NOEDITLABELS,
NSTCS_TABSTOP,NSTCS_FAVORITESMODE,NSTCS_EMPTYTEXT,NSTCS_CHECKBOXES,
NSTCS_ALLOWJUNCTIONS,NSTCS_SHOWTABSBUTTON,NSTCS_SHOWDELETEBUTTON,
NSTCS_SHOWREFRESHBUTTON, 0};
static const NSTCSTYLE styles_nonsetable[] =
{ NSTCS_SPRINGEXPAND, NSTCS_RICHTOOLTIP, NSTCS_AUTOHSCROLL,
NSTCS_FADEINOUTEXPANDOS,
NSTCS_PARTIALCHECKBOXES, NSTCS_EXCLUSIONCHECKBOXES,
NSTCS_DIMMEDCHECKBOXES, NSTCS_NOINDENTCHECKS,0};
/* Set/GetControlStyle */
style = style2 = 0xdeadbeef;
hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style == 0, "Got style %x\n", style);
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0, 0xFFFFFFF);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0xFFFFFFFF, 0);
ok(hr == E_FAIL, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0xFFFFFFFF, 0xFFFFFFFF);
ok(hr == E_FAIL, "Got 0x%08x\n", hr);
tmp = 0;
for(i = 0; styles_setable[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_setable[i], styles_setable[i]);
ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles_setable[i]);
if(SUCCEEDED(hr)) tmp |= styles_setable[i];
}
for(i = 0; styles_nonsetable[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_nonsetable[i], styles_nonsetable[i]);
ok(hr == E_FAIL, "Got 0x%08x (%x)\n", hr, styles_nonsetable[i]);
}
hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style == tmp, "Got style %x (expected %x)\n", style, tmp);
if(SUCCEEDED(hr))
{
DWORD tmp2;
for(i = 0; styles_setable[i] != 0; i++)
{
hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, styles_setable[i], &tmp2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(tmp2 == (style & styles_setable[i]), "Got %x\n", tmp2);
}
}
for(i = 0; styles_setable[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_setable[i], 0);
ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles_setable[i]);
}
for(i = 0; styles_nonsetable[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_nonsetable[i], 0);
ok(hr == E_FAIL, "Got 0x%08x (%x)\n", hr, styles_nonsetable[i]);
}
hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style == 0, "Got style %x\n", style);
/* Set/GetControlStyle2 */
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == 0, "Got style %x\n", style2);
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0, 0);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0, 0xFFFFFFFF);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0xFFFFFFFF);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == 0x00000000, "Got style %x\n", style2);
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == 0, "Got style %x\n", style2);
tmp = 0;
for(i = 0; styles2[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], styles2[i]);
ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
if(SUCCEEDED(hr)) tmp |= styles2[i];
}
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == tmp, "Got style %x (expected %x)\n", style2, tmp);
if(SUCCEEDED(hr))
{
DWORD tmp2;
for(i = 0; styles2[i] != 0; i++)
{
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, styles2[i], &tmp2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(tmp2 == (style2 & styles2[i]), "Got %x\n", tmp2);
}
}
for(i = 0; styles2[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], 0);
ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
}
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == 0, "Got style %x (expected 0)\n", style2);
}
else
{
/* 64-bit Windows Vista (others?) seems to have a somewhat
* different idea of how the methods of this interface
* should behave. */
static const NSTCSTYLE styles[] =
{ NSTCS_HASEXPANDOS,NSTCS_HASLINES,NSTCS_SINGLECLICKEXPAND,
NSTCS_FULLROWSELECT,NSTCS_SPRINGEXPAND,NSTCS_HORIZONTALSCROLL,
NSTCS_RICHTOOLTIP, NSTCS_AUTOHSCROLL,
NSTCS_FADEINOUTEXPANDOS,
NSTCS_PARTIALCHECKBOXES,NSTCS_EXCLUSIONCHECKBOXES,
NSTCS_DIMMEDCHECKBOXES, NSTCS_NOINDENTCHECKS,
NSTCS_ROOTHASEXPANDO,NSTCS_SHOWSELECTIONALWAYS,NSTCS_NOINFOTIP,
NSTCS_EVENHEIGHT,NSTCS_NOREPLACEOPEN,NSTCS_DISABLEDRAGDROP,
NSTCS_NOORDERSTREAM,NSTCS_BORDER,NSTCS_NOEDITLABELS,
NSTCS_TABSTOP,NSTCS_FAVORITESMODE,NSTCS_EMPTYTEXT,NSTCS_CHECKBOXES,
NSTCS_ALLOWJUNCTIONS,NSTCS_SHOWTABSBUTTON,NSTCS_SHOWDELETEBUTTON,
NSTCS_SHOWREFRESHBUTTON, 0};
trace("Detected broken INameSpaceTreeControl2.\n");
style = 0xdeadbeef;
hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style == 0xdeadbeef, "Got style %x\n", style);
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == 0, "Got style %x\n", style2);
tmp = 0;
for(i = 0; styles[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles[i], styles[i]);
ok(hr == E_FAIL || ((styles[i] & NSTCS_SPRINGEXPAND) && hr == S_OK),
"Got 0x%08x (%x)\n", hr, styles[i]);
if(SUCCEEDED(hr)) tmp |= styles[i];
}
style = 0xdeadbeef;
hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, tmp, &style);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style == 0xdeadbeef, "Got style %x\n", style);
tmp = 0;
for(i = 0; styles2[i] != 0; i++)
{
hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], styles2[i]);
ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
if(SUCCEEDED(hr)) tmp |= styles2[i];
}
style2 = 0xdeadbeef;
hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(style2 == tmp, "Got style %x\n", style2);
}
INameSpaceTreeControl2_Release(pnstc2);
}
else
{
skip("INameSpaceTreeControl2 missing.\n");
}
hr = INameSpaceTreeControl_RemoveRoot(pnstc, NULL);
ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
/* Append / Insert root */
if(0)
{
/* Crashes under Windows 7 */
hr = INameSpaceTreeControl_AppendRoot(pnstc, NULL, SHCONTF_FOLDERS, 0, NULL);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, NULL, SHCONTF_FOLDERS, 0, NULL);
}
/* Note the usage of psidesktop and psidesktop2 */
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop2, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 50, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
/* GetRootItems */
if(0)
{
/* Crashes on native. */
hr = INameSpaceTreeControl_GetRootItems(pnstc, NULL);
}
hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop2, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
roots[0] = psidesktop;
roots[1] = psidesktop2;
roots[2] = psitestdir;
roots[3] = psitestdir2;
roots[4] = NULL;
verify_root_order(pnstc, roots);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, psitestdir2, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
roots[0] = psitestdir2;
roots[1] = psidesktop;
roots[2] = psidesktop2;
roots[3] = psitestdir;
roots[4] = psitestdir2;
roots[5] = NULL;
verify_root_order(pnstc, roots);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 5, psidesktop, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
roots[5] = psidesktop;
roots[6] = NULL;
verify_root_order(pnstc, roots);
hr = INameSpaceTreeControl_InsertRoot(pnstc, 3, psitestdir2, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
roots[3] = psitestdir2;
roots[4] = psitestdir;
roots[5] = psitestdir2;
roots[6] = psidesktop;
roots[7] = NULL;
verify_root_order(pnstc, roots);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
roots[7] = psitestdir2;
roots[8] = NULL;
verify_root_order(pnstc, roots);
hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, 0, 0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
roots[0] = psidesktop;
roots[1] = psitestdir2;
roots[2] = psidesktop;
roots[3] = psidesktop2;
roots[4] = psitestdir2;
roots[5] = psitestdir;
roots[6] = psitestdir2;
roots[7] = psidesktop;
roots[8] = psitestdir2;
roots[9] = NULL;
verify_root_order(pnstc, roots);
/* CollapseAll */
hr = INameSpaceTreeControl_CollapseAll(pnstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_CollapseAll(pnstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
/* SetItemState message checks */
res = subclass_treeview(pnstc);
ok(res, "Failed to subclass treeview.\n");
if(res)
{
UINT isMask, isFlags;
hr = INameSpaceTreeControl_AppendRoot(
pnstc, psidesktop, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
flush_sequences(sequences, NUM_MSG_SEQUENCES);
/* A special case -
* The first expansion results in an "unrelated" TVM_SETITEMW being sent
* (mask == 0x50 (TVIF_CHILDREN|TVIF_HANDLE) )
*/
tvi_count = 0;
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
NSTCIS_EXPANDED, NSTCIS_EXPANDED);
ok(hr == S_OK, "Got 0x%08x\n", hr);
todo_wine
{
ok(tvi_count == 1, "Got %d\n", tvi_count);
ok(last_tvi.mask == 0x50, "Got mask %x, expected 0x50\n", last_tvi.mask);
}
tvi_count = 0;
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
NSTCIS_EXPANDED, NSTCIS_EXPANDED);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(tvi_count == 0, "Got %d\n", tvi_count);
/* Test all the combinations of NSTCIS_SELECTED to NSTCIS_SELECTEDNOEXPAND */
flush_sequences(sequences, NUM_MSG_SEQUENCES);
for(isMask = 0; isMask <= 0x1f; isMask++)
{
for(isFlags = 0; isFlags <= 0x1f; isFlags++)
{
UINT select_sent, select_sent_vista, ensurev_sent, expand_sent;
TVITEMEXW tviexp;
UINT msg_count;
flush_sequences(sequences, NUM_MSG_SEQUENCES);
tvi_count = 0;
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, isMask, isFlags);
ok(hr == S_OK, "(%x|%x)Got 0x%08x\n", isMask, isFlags, hr);
/*****************************/
/* Calculate expected values */
/*****************************/
/* Number of TVM_SELECTITEM/TVM_ENSUREVISIBLE and TVM_EXPAND sent */
select_sent = ((isMask&isFlags) & NSTCIS_SELECTED)?1:0;
select_sent_vista = ensurev_sent = select_sent;
select_sent += ((isMask&isFlags) & NSTCIS_SELECTEDNOEXPAND)?1:0;
select_sent_vista += ((isMask&isFlags) & NSTCIS_EXPANDED)?1:0;
expand_sent = ((isMask|isFlags) & NSTCIS_EXPANDED)?1:0;
/* Possible TWM_SETITEMW message and its contents */
if(isMask & NSTCIS_DISABLED)
tviexp.mask = TVIF_STATE | TVIF_STATEEX;
else if( ((isMask^isFlags) & (NSTCIS_SELECTED|NSTCIS_EXPANDED|NSTCIS_SELECTEDNOEXPAND)) ||
((isMask|isFlags) & NSTCIS_BOLD) || (isFlags & NSTCIS_DISABLED) )
tviexp.mask = TVIF_STATE;
else
tviexp.mask = 0;
if(tviexp.mask)
{
tviexp.stateMask = tviexp.state = 0;
tviexp.stateMask |= ((isMask^isFlags)&NSTCIS_SELECTED) ? TVIS_SELECTED : 0;
tviexp.stateMask |= (isMask|isFlags)&NSTCIS_BOLD ? TVIS_BOLD:0;
tviexp.state |= (isMask&isFlags)&NSTCIS_BOLD ? TVIS_BOLD:0;
if((isMask&NSTCIS_EXPANDED)^(isFlags&NSTCIS_EXPANDED))
{
tviexp.stateMask = 0;
}
tviexp.uStateEx = (isFlags&isMask)&NSTCIS_DISABLED?TVIS_EX_DISABLED:0;
}
else
{
/* Make sure that no tests accidentally succeeded
* (and avoid a gcc warning) */
tviexp.stateMask = tviexp.state = tviexp.uStateEx = -1;
}
/*****************************/
/* Check the values. */
/*****************************/
msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_SELECTITEM);
ok(msg_count == select_sent || broken(msg_count == select_sent_vista),
"(%x|%x) Got msg_count %d, expected %d (%d)\n",
isMask, isFlags, msg_count, select_sent, select_sent_vista);
msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_ENSUREVISIBLE);
ok(msg_count == ensurev_sent || broken(msg_count == 0 /* Vista */),
"(%x|%x) Got msg_count %d, expected %d\n",
isMask, isFlags, msg_count, ensurev_sent);
msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_EXPAND);
ok(msg_count == expand_sent, "(%x|%x) Got msg_count %d, expected %d\n",
isMask, isFlags, msg_count, expand_sent);
msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_SETITEMW);
if(!tviexp.mask)
{
/* Four special cases for vista */
BOOL vista_check = ( (isMask == 0x10 && isFlags == 0x10) ||
(isMask == 0x11 && isFlags == 0x11) ||
(isMask == 0x12 && isFlags == 0x12) ||
(isMask == 0x13 && isFlags == 0x13) );
ok(msg_count == 0 || broken(msg_count == 1 && vista_check),
"(%x|%x) Got msg_count %d (tviexp.mask %x)\n",
isMask, isFlags, msg_count, tviexp.mask);
}
else
{
ok(msg_count == 1, "(%x|%x) Got msg_count %d, expected 1\n",
isMask, isFlags, msg_count);
ok(last_tvi.mask == tviexp.mask,
"(%x|%x) Got mask %x, expected %x\n",
isMask, isFlags, last_tvi.mask, tviexp.mask);
ok(last_tvi.stateMask == tviexp.stateMask,
"(%x|%x) Got stateMask %x, expected %x\n",
isMask, isFlags, last_tvi.stateMask, tviexp.stateMask);
ok(last_tvi.state == tviexp.state,
"(%x|%x) Got state %x, expected %x\n",
isMask, isFlags, last_tvi.state, tviexp.state);
ok(last_tvi.uStateEx == tviexp.uStateEx,
"(%x|%x) Got uStateEx %x, expected %x\n",
isMask, isFlags, last_tvi.uStateEx, tviexp.uStateEx);
}
}
}
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
}
/* GetSelectedItems */
if(0)
{
/* Crashes under Windows 7 */
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, NULL);
}
psia = (void*)0xdeadbeef;
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
ok(hr == E_FAIL, "Got 0x%08x\n", hr);
ok(psia == (void*)0xdeadbeef, "Got %p\n", psia);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir, SHCONTF_FOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
hr = INameSpaceTreeControl_SetItemState(pnstc, psitestdir,
NSTCIS_SELECTED, NSTCIS_SELECTED);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
UINT count;
hr = IShellItemArray_GetCount(psia, &count);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(count == 1, "Got %d selected items.\n", count);
if(count)
{
hr = IShellItemArray_GetItemAt(psia, 0, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
IShellItem_Release(psi);
}
}
IShellItemArray_Release(psia);
}
hr = INameSpaceTreeControl_SetItemState(pnstc, psitestdir2,
NSTCIS_SELECTED, NSTCIS_SELECTED);
ok(hr == S_OK, "Got 0x%08x\n", hr);
process_msgs();
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
UINT count;
hr = IShellItemArray_GetCount(psia, &count);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(count == 1, "Got %d selected items.\n", count);
if(count)
{
hr = IShellItemArray_GetItemAt(psia, 0, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, psitestdir2, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
IShellItem_Release(psi);
}
}
IShellItemArray_Release(psia);
}
hr = INameSpaceTreeControl_SetItemState(pnstc, psitest1,
NSTCIS_SELECTED, NSTCIS_SELECTED);
todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
UINT count;
hr = IShellItemArray_GetCount(psia, &count);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(count == 1, "Got %d selected items.\n", count);
if(count)
{
hr = IShellItemArray_GetItemAt(psia, 0, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, psitest1, SICHINT_DISPLAY, &cmp);
todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
IShellItem_Release(psi);
}
}
IShellItemArray_Release(psia);
}
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK || broken(hr == E_FAIL), "Got 0x%08x\n", hr);
if(hr == E_FAIL)
{
/* For some reason, Vista fails to properly remove both the
* roots here on the first try. */
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
}
/* Adding without NSTCRS_EXPANDED does not set the selection */
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
0, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
process_msgs();
hr = INameSpaceTreeControl_GetItemState(pnstc, psitestdir, 0xFF, &istate);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(!(istate & NSTCIS_SELECTED), "Got 0x%08x\n", istate);
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
ok(hr == E_FAIL, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr)) IShellItemArray_Release(psia);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
/* Adding with NSTCRS_EXPANDED sets the selection */
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
NSTCRS_EXPANDED, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
process_msgs();
hr = INameSpaceTreeControl_GetItemState(pnstc, psitestdir, 0xFF, &istate);
ok(hr == S_OK, "Got 0x%08x\n", hr);
todo_wine ok(istate & NSTCIS_SELECTED, "Got 0x%08x\n", istate);
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
IShellItem *psi;
hr = IShellItemArray_GetItemAt(psia, 0, &psi);
if(SUCCEEDED(hr))
{
INT cmp;
hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
IShellItem_Release(psi);
}
IShellItemArray_Release(psia);
}
/* Adding a second root with NSTCRS_EXPANDED does not change the selection */
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
NSTCRS_EXPANDED, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
process_msgs();
hr = INameSpaceTreeControl_GetItemState(pnstc, psitestdir2, 0xFF, &istate);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(!(istate & NSTCIS_SELECTED), "Got 0x%08x\n", istate);
hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
IShellItem *psi;
hr = IShellItemArray_GetItemAt(psia, 0, &psi);
if(SUCCEEDED(hr))
{
INT cmp;
hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
IShellItem_Release(psi);
}
IShellItemArray_Release(psia);
}
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
/* GetItemRect */
rc.top = rc.left = rc.bottom = rc.right = 0;
if(0)
{
/* Crashes under win 7 */
hr = INameSpaceTreeControl_GetItemRect(pnstc, NULL, NULL);
hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir, NULL);
hr = INameSpaceTreeControl_GetItemRect(pnstc, NULL, &rc);
}
hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir, &rc);
ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
NSTCRS_EXPANDED, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
process_msgs();
hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir, &rc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(rc.top != rc.bottom, "Got 0 height.\n");
ok(rc.left != rc.bottom, "Got 0 width.\n");
height = 0;
hwnd_tv = get_treeview_hwnd(pnstc);
if(hwnd_tv)
{
HTREEITEM hroot = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_ROOT, 0);
ok(hroot != NULL, "Failed to get root.\n");
if(hroot)
{
RECT tv_rc;
BOOL bret;
*(HTREEITEM*)&tv_rc = hroot;
bret = SendMessageW(hwnd_tv, TVM_GETITEMRECT, FALSE, (LPARAM)&tv_rc);
ok(bret, "TVM_GETITEMRECT failed.\n");
/* The NamespaceTreeControl returns screen coordinates. */
MapWindowPoints(NULL, hwnd, (POINT*)&rc, 2);
ok(rc.left == tv_rc.left, "Differed, got %d and %d\n", rc.left, tv_rc.left);
ok(rc.top == tv_rc.top, "Differed, got %d and %d\n", rc.top, tv_rc.top);
ok(rc.right == tv_rc.right, "Differed, got %d and %d\n", rc.right, tv_rc.right);
ok(rc.bottom == tv_rc.bottom, "Differed, got %d and %d\n", rc.bottom, tv_rc.bottom);
/* Save the height and compare to that of other items.
Observed values: 18, 19, 21 */
height = rc.bottom - rc.top;
trace("height: %d\n", height);
}
}
else
win_skip("Skipping some GetItemRect tests.\n");
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
/* HitTest */
hr = INameSpaceTreeControl_HitTest(pnstc, NULL, NULL);
ok(hr == E_POINTER, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_HitTest(pnstc, &pt, NULL);
ok(hr == E_POINTER, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_HitTest(pnstc, NULL, &psi);
ok(hr == E_POINTER, "Got 0x%08x\n", hr);
psi = (void*)0xdeadbeef;
hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
ok(hr == S_FALSE, "Got 0x%08x\n", hr);
ok(psi == NULL, "Got psi %p\n", psi);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
NSTCRS_EXPANDED, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
process_msgs();
pt.x = pt.y = 0;
hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(!cmp, "Got cmp %d\n", cmp);
IShellItem_Release(psi);
}
pt.y += height - 1;
hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(!cmp, "Got cmp %d\n", cmp);
IShellItem_Release(psi);
}
pt.y += 1;
hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
todo_wine
{
hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
ok(hr == S_FALSE, "Got 0x%08x\n", hr);
ok(cmp, "no cmp value.\n");
hr = IShellItem_Compare(psi, psitestdir2, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(!cmp, "Got cmp %d\n", cmp);
}
IShellItem_Release(psi);
}
hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir2, &rc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
MapWindowPoints(NULL, hwnd, (POINT*)&rc, 2);
pt.x = rc.left; pt.y = rc.top;
hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
int cmp;
hr = IShellItem_Compare(psi, psitestdir2, SICHINT_DISPLAY, &cmp);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(!cmp, "Got cmp %d\n", cmp);
IShellItem_Release(psi);
}
}
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
/* GetItemCustomState / SetItemCustomState */
if(0)
{
/* Crashes under Windows 7 */
hr = INameSpaceTreeControl_GetItemCustomState(pnstc, NULL, NULL);
hr = INameSpaceTreeControl_GetItemCustomState(pnstc, NULL, &cbstate);
hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, NULL);
hr = INameSpaceTreeControl_SetItemCustomState(pnstc, NULL, 0);
}
hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
0, NULL);
process_msgs();
ok(hr == S_OK, "Got 0x%08x\n", hr);
todo_wine
{
cbstate = -1;
hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, &cbstate);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(cbstate == BST_UNCHECKED || broken(cbstate == BST_CHECKED /* Vista x64 */),
"Got %d\n", cbstate);
hr = INameSpaceTreeControl_SetItemCustomState(pnstc, psitestdir, BST_CHECKED);
ok(hr == S_OK, "Got 0x%08x\n", hr);
cbstate = -1;
hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, &cbstate);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(cbstate == BST_CHECKED, "Got %d\n", cbstate);
hr = INameSpaceTreeControl_SetItemCustomState(pnstc, psitestdir, 0xFFF);
ok(hr == S_OK, "Got 0x%08x\n", hr);
cbstate = -1;
hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, &cbstate);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok(cbstate == 0xF, "Got %d\n", cbstate);
}
/* SetTheme */
todo_wine
{
hr = INameSpaceTreeControl_SetTheme(pnstc, NULL);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_SetTheme(pnstc, explorerW);
ok(hr == S_OK, "Got 0x%08x\n", hr);
hr = INameSpaceTreeControl_SetTheme(pnstc, randomW);
ok(hr == S_OK, "Got 0x%08x\n", hr);
}
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
IShellItem_Release(psidesktop);
IShellItem_Release(psidesktop2);
IShellItem_Release(psitestdir);
IShellItem_Release(psitestdir2);
IShellItem_Release(psitest1);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
HWND hwnd_nstc;
hr = IOleWindow_GetWindow(pow, &hwnd_nstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
DestroyWindow(hwnd_nstc);
IOleWindow_Release(pow);
}
res = INameSpaceTreeControl_Release(pnstc);
ok(!res, "res was %d!\n", res);
cleanup:
Cleanup();
}
static void test_events(void)
{
INameSpaceTreeControl *pnstc;
INameSpaceTreeControlEventsImpl *pnstceimpl, *pnstceimpl2;
INameSpaceTreeControlEvents *pnstce, *pnstce2;
IShellFolder *psfdesktop;
IShellItem *psidesktop;
IOleWindow *pow;
LPITEMIDLIST pidl_desktop;
LPITEMIDLIST pidl_drives;
NSTCITEMSTATE itemstate;
IShellItem *psi;
DWORD cookie1, cookie2;
HWND hwnd_tv;
HRESULT hr;
UINT res;
hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
&IID_INameSpaceTreeControl, (void**)&pnstc);
ok(hr == S_OK, "Failed to initialize control (0x%08x)\n", hr);
ok(pSHCreateShellItem != NULL, "No SHCreateShellItem.\n");
ok(pSHGetIDListFromObject != NULL, "No SHCreateShellItem.\n");
SHGetDesktopFolder(&psfdesktop);
hr = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl_desktop);
IShellFolder_Release(psfdesktop);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop);
ok(hr == S_OK, "Got 0x%08x\n", hr);
ILFree(pidl_desktop);
/* Create two instances of INameSpaceTreeControlEvents */
pnstceimpl = create_nstc_events();
pnstce = (INameSpaceTreeControlEvents*)pnstceimpl;
ZeroMemory(&pnstceimpl->count, sizeof(UINT)*LastEvent);
pnstceimpl2 = create_nstc_events();
pnstce2 = (INameSpaceTreeControlEvents*)pnstceimpl2;
if(0)
{
/* Crashes native */
hr = INameSpaceTreeControl_TreeAdvise(pnstc, NULL, NULL);
hr = INameSpaceTreeControl_TreeAdvise(pnstc, NULL, &cookie1);
hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, NULL);
}
/* TreeAdvise in NameSpaceTreeController seems to support only one
* client at the time.
*/
/* First, respond with E_NOINTERFACE to all QI's */
pnstceimpl->qi_enable_events = FALSE;
pnstceimpl->qi_called_count = 0;
cookie1 = 0xDEADBEEF;
hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie1);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
ok(cookie1 == 0, "cookie now (0x%08x)\n", cookie1);
todo_wine
{
ok(pnstceimpl->qi_called_count == 7 || pnstceimpl->qi_called_count == 4 /* Vista */,
"QueryInterface called %d times.\n",
pnstceimpl->qi_called_count);
}
ok(pnstceimpl->ref == 1, "refcount was %d\n", pnstceimpl->ref);
/* Accept query for IID_INameSpaceTreeControlEvents */
pnstceimpl->qi_enable_events = TRUE;
pnstceimpl->qi_called_count = 0;
cookie1 = 0xDEADBEEF;
hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie1);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(cookie1 == 1, "cookie now (0x%08x)\n", cookie1);
todo_wine
{
ok(pnstceimpl->qi_called_count == 7 || pnstceimpl->qi_called_count == 4 /* Vista */,
"QueryInterface called %d times.\n",
pnstceimpl->qi_called_count);
}
ok(pnstceimpl->ref == 2, "refcount was %d\n", pnstceimpl->ref);
/* A second time, query interface will not be called at all. */
pnstceimpl->qi_enable_events = TRUE;
pnstceimpl->qi_called_count = 0;
cookie2 = 0xDEADBEEF;
hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie2);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
ok(cookie2 == 0, "cookie now (0x%08x)\n", cookie2);
ok(!pnstceimpl->qi_called_count, "QueryInterface called %d times.\n",
pnstceimpl->qi_called_count);
ok(pnstceimpl->ref == 2, "refcount was %d\n", pnstceimpl->ref);
/* Using another "instance" does not help. */
pnstceimpl2->qi_enable_events = TRUE;
pnstceimpl2->qi_called_count = 0;
cookie2 = 0xDEADBEEF;
hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce2, &cookie2);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
ok(cookie2 == 0, "cookie now (0x%08x)\n", cookie2);
ok(!pnstceimpl2->qi_called_count, "QueryInterface called %d times.\n",
pnstceimpl2->qi_called_count);
ok(pnstceimpl2->ref == 1, "refcount was %d\n", pnstceimpl->ref);
/* Unadvise with bogus cookie (will actually unadvise properly) */
pnstceimpl->qi_enable_events = TRUE;
pnstceimpl->qi_called_count = 0;
hr = INameSpaceTreeControl_TreeUnadvise(pnstc, 1234);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(!pnstceimpl->qi_called_count, "QueryInterface called %d times.\n",
pnstceimpl->qi_called_count);
ok(pnstceimpl->ref == 1, "refcount was %d\n", pnstceimpl->ref);
/* Unadvise "properly" (will have no additional effect) */
pnstceimpl->qi_enable_events = TRUE;
pnstceimpl->qi_called_count = 0;
hr = INameSpaceTreeControl_TreeUnadvise(pnstc, cookie1);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(!pnstceimpl->qi_called_count, "QueryInterface called %d times.\n",
pnstceimpl->qi_called_count);
ok(pnstceimpl->ref == 1, "refcount was %d\n", pnstceimpl->ref);
/* Advise again.. */
pnstceimpl->qi_enable_events = 1;
pnstceimpl->qi_called_count = 0;
hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie2);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(cookie2 == 1, "Cookie is %d\n", cookie2);
ok(cookie1 == cookie2, "Old cookie differs from old cookie.\n");
todo_wine
{
ok(pnstceimpl->qi_called_count == 7 || pnstceimpl->qi_called_count == 4 /* Vista */,
"QueryInterface called %d times.\n",
pnstceimpl->qi_called_count);
}
ok(pnstceimpl->ref == 2, "refcount was %d\n", pnstceimpl->ref);
/* Initialize the control */
hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, NULL, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
ok_event_count(pnstceimpl, OnGetDefaultIconIndex, 0);
ok_no_events(pnstceimpl);
hwnd_tv = get_treeview_hwnd(pnstc);
ok(hwnd_tv != NULL, "Failed to get hwnd_tv HWND.\n");
if(hwnd_tv)
{
HTREEITEM hroot, hitem;
UINT i;
static const UINT kbd_msgs_event[] = {
WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
WM_SYSCHAR, 0 };
static const UINT kbd_msgs_noevent[] ={
WM_DEADCHAR, WM_SYSDEADCHAR, WM_UNICHAR, 0 };
/* Test On*Expand */
hroot = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_ROOT, 0);
SendMessage(hwnd_tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)hroot);
process_msgs();
ok_event_count(pnstceimpl, OnBeforeExpand, 1);
ok_event_count(pnstceimpl, OnAfterExpand, 1);
ok_event_broken(pnstceimpl, OnItemAdded); /* No event on Vista */
todo_wine ok_event_count(pnstceimpl, OnSelectionChanged, 1);
ok_no_events(pnstceimpl);
SendMessage(hwnd_tv, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hroot);
process_msgs();
ok_no_events(pnstceimpl);
SendMessage(hwnd_tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)hroot);
process_msgs();
ok_no_events(pnstceimpl);
/* Test OnSelectionChanged */
hitem = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hroot);
SendMessageW(hwnd_tv, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hitem);
process_msgs();
ok_event_count(pnstceimpl, OnSelectionChanged, 1);
ok_no_events(pnstceimpl);
/* Test OnKeyboardInput */
for(i = 0; kbd_msgs_event[i] != 0; i++)
{
SendMessageW(hwnd_tv, kbd_msgs_event[i], 0x1234, 0x1234);
ok(pnstceimpl->count[OnKeyboardInput] == 1,
"%d (%x): Got count %d\n",
kbd_msgs_event[i], kbd_msgs_event[i], pnstceimpl->count[OnKeyboardInput]);
pnstceimpl->count[OnKeyboardInput] = 0;
}
for(i = 0; kbd_msgs_noevent[i] != 0; i++)
{
SendMessageW(hwnd_tv, kbd_msgs_noevent[i], 0x1234, 0x1234);
ok(pnstceimpl->count[OnKeyboardInput] == 0,
"%d (%x): Got count %d\n",
kbd_msgs_noevent[i], kbd_msgs_noevent[i], pnstceimpl->count[OnKeyboardInput]);
pnstceimpl->count[OnKeyboardInput] = 0;
}
ok_no_events(pnstceimpl);
}
else
skip("Skipping some tests.\n");
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
process_msgs();
ok(hr == S_OK, "Got 0x%08x\n", hr);
ok_event(pnstceimpl, OnItemDeleted);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
process_msgs();
ok_no_events(pnstceimpl);
/* Expand the root */
itemstate |= NSTCIS_EXPANDED;
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count(pnstceimpl, OnBeforeExpand, 1);
ok_event_broken(pnstceimpl, OnItemAdded); /* Does not fire on Vista */
ok_event_count(pnstceimpl, OnAfterExpand, 1);
todo_wine
{
ok_event_count_broken(pnstceimpl, OnSelectionChanged, 1, 0 /* Vista*/);
}
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate & NSTCIS_EXPANDED, "Item not expanded.\n");
todo_wine
{
ok(itemstate == (NSTCIS_SELECTED | NSTCIS_EXPANDED)||
broken(itemstate == NSTCIS_EXPANDED) /* Vista */,
"itemstate is 0x%08x\n", itemstate);
process_msgs();
ok_event_count_broken(pnstceimpl, OnSelectionChanged, 1, 0 /* Vista*/);
}
ok_no_events(pnstceimpl);
/* Deselect the root */
itemstate &= ~NSTCIS_SELECTED;
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == (NSTCIS_EXPANDED), "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_CollapseAll(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
/* Delete all roots */
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_event_count(pnstceimpl, OnItemDeleted, 1);
ok_no_events(pnstceimpl);
/* Get/SetItemState */
if(0)
{
/* Crashes on Windows 7 */
hr = INameSpaceTreeControl_SetItemState(pnstc, NULL, 0, 0);
hr = INameSpaceTreeControl_GetItemState(pnstc, NULL, 0, NULL);
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0, NULL);
hr = INameSpaceTreeControl_GetItemState(pnstc, NULL, 0, &itemstate);
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0, NULL);
hr = INameSpaceTreeControl_GetItemState(pnstc, NULL, 0, &itemstate);
}
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop,
SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0, 0xffff);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
todo_wine
{
ok_event_count(pnstceimpl, OnBeforeExpand, 0);
ok_event_count(pnstceimpl, OnAfterExpand, 0);
ok_event_count(pnstceimpl, OnItemAdded, 0);
}
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
todo_wine
ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, NSTCIS_SELECTED);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count(pnstceimpl, OnSelectionChanged, 1);
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_EXPANDED, NSTCIS_SELECTED);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, NSTCIS_SELECTEDNOEXPAND);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, NSTCIS_EXPANDED);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
todo_wine
{
ok_event_count(pnstceimpl, OnBeforeExpand, 1);
ok_event_broken(pnstceimpl, OnItemAdded); /* Does not fire on Vista */
ok_event_count(pnstceimpl, OnAfterExpand, 1);
}
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_EXPANDED, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0xffff);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
todo_wine
{
ok(itemstate == (NSTCIS_EXPANDED | NSTCIS_BOLD | NSTCIS_DISABLED),
"itemstate is 0x%08x\n", itemstate);
}
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_SELECTED, NSTCIS_SELECTED);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
todo_wine
{
ok(itemstate == (NSTCIS_EXPANDED | NSTCIS_BOLD | NSTCIS_DISABLED),
"itemstate is 0x%08x\n", itemstate);
}
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
NSTCIS_SELECTED | NSTCIS_DISABLED, NSTCIS_SELECTED);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == (NSTCIS_BOLD | NSTCIS_EXPANDED),
"itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_SELECTED, NSTCIS_SELECTED);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == (NSTCIS_BOLD | NSTCIS_EXPANDED),
"itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff & ~NSTCIS_DISABLED, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_no_events(pnstceimpl);
itemstate = 0xDEADBEEF;
hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok(itemstate == (NSTCIS_BOLD), "itemstate is 0x%08x\n", itemstate);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_event_count(pnstceimpl, OnItemDeleted, 1);
ok_no_events(pnstceimpl);
/* GetNextItem */
hr = INameSpaceTreeControl_GetNextItem(pnstc, NULL, 0, NULL);
ok(hr == E_POINTER, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, 0, NULL);
ok(hr == E_POINTER, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_GetNextItem(pnstc, NULL, 0, &psi);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, 0, &psi);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
ok_no_events(pnstceimpl);
/* Get child from unexpanded and unfilled parent */
psi = (void*)0xDEADBEEF;
hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, NSTCGNI_CHILD, &psi);
ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
ok(psi == NULL, "psi is %p\n", psi);
process_msgs();
ok_no_events(pnstceimpl);
/* Expand and try again */
hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_EXPANDED, 0xffff);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count(pnstceimpl, OnBeforeExpand, 1);
ok_event_broken(pnstceimpl, OnItemAdded); /* Does not fire on Vista */
ok_event_count(pnstceimpl, OnAfterExpand, 1);
todo_wine ok_event_count_broken(pnstceimpl, OnSelectionChanged, 1, 0 /*Vista */);
ok_no_events(pnstceimpl);
psi = (void*)0xDEADBEEF;
hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, NSTCGNI_CHILD, &psi);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok((psi != NULL) && (psi != (void*)0xDEADBEEF), "psi is %p\n", psi);
process_msgs();
ok_no_events(pnstceimpl);
if(SUCCEEDED(hr)) IShellItem_Release(psi);
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_event_count(pnstceimpl, OnItemDeleted, 1);
ok_no_events(pnstceimpl);
/* EnsureItemVisible */
if(0)
{
/* Crashes on Windows 7 */
hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, NULL);
}
hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psidesktop);
ok(hr == E_INVALIDARG || hr == E_FAIL, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = pSHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidl_drives);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
if(SUCCEEDED(hr))
{
hr = pSHCreateShellItem(NULL, NULL, pidl_drives, &psi);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
if(SUCCEEDED(hr))
{
hr = INameSpaceTreeControl_AppendRoot(pnstc, psi, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psidesktop);
ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psi);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
process_msgs();
ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psidesktop);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psi);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_no_events(pnstceimpl);
}
else
skip("Failed to create shellitem.\n");
ILFree(pidl_drives);
}
else
skip("Failed to get pidl for CSIDL_DRIVES.\n");
hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
ok_event_count(pnstceimpl, OnItemDeleted, 2);
ok_no_events(pnstceimpl);
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
{
HWND hwnd_nstc;
hr = IOleWindow_GetWindow(pow, &hwnd_nstc);
ok(hr == S_OK, "Got 0x%08x\n", hr);
DestroyWindow(hwnd_nstc);
IOleWindow_Release(pow);
}
hr = INameSpaceTreeControl_TreeUnadvise(pnstc, cookie2);
ok(hr == S_OK, "Got 0x%08x\n", hr);
res = INameSpaceTreeControl_Release(pnstc);
ok(!res, "res was %d!\n", res);
if(!res)
{
/* Freeing these prematurely causes a crash. */
HeapFree(GetProcessHeap(), 0, pnstceimpl);
HeapFree(GetProcessHeap(), 0, pnstceimpl2);
}
}
static void setup_window(void)
{
WNDCLASSA wc;
static const char nstctest_wnd_name[] = "nstctest_wnd";
ZeroMemory(&wc, sizeof(WNDCLASSA));
wc.lpfnWndProc = DefWindowProcA;
wc.lpszClassName = nstctest_wnd_name;
RegisterClassA(&wc);
hwnd = CreateWindowA(nstctest_wnd_name, NULL, WS_TABSTOP,
0, 0, 200, 200, NULL, 0, 0, NULL);
ok(hwnd != NULL, "Failed to create window for test (lasterror: %d).\n",
GetLastError());
}
static void destroy_window(void)
{
DestroyWindow(hwnd);
}
START_TEST(nstc)
{
OleInitialize(NULL);
setup_window();
init_function_pointers();
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
if(test_initialization())
{
test_basics();
test_events();
}
else
{
win_skip("No NamespaceTreeControl (or instantiation failed).\n");
}
destroy_window();
OleUninitialize();
}