2 * Unit tests for the NamespaceTree Control
4 * Copyright 2010 David Hedberg
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
33 /* "Intended for internal use" */
34 #define TVS_EX_NOSINGLECOLLAPSE 0x1
36 static HRESULT (WINAPI *pSHCreateShellItem)(LPCITEMIDLIST,IShellFolder*,LPCITEMIDLIST,IShellItem**);
37 static HRESULT (WINAPI *pSHGetIDListFromObject)(IUnknown*, PIDLIST_ABSOLUTE*);
38 static HRESULT (WINAPI *pSHCreateItemFromParsingName)(PCWSTR,IBindCtx*,REFIID,void**);
39 static HRESULT (WINAPI *pSHGetSpecialFolderLocation)(HWND, int, LPITEMIDLIST *);
41 #define NUM_MSG_SEQUENCES 1
42 #define TREEVIEW_SEQ_INDEX 0
44 static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
46 /* Keep a copy of the last structure passed by TVM_SETITEMW */
47 static TVITEMEXW last_tvi;
50 static void init_function_pointers(void)
54 hmod = GetModuleHandleA("shell32.dll");
55 pSHCreateShellItem = (void*)GetProcAddress(hmod, "SHCreateShellItem");
56 pSHGetIDListFromObject = (void*)GetProcAddress(hmod, "SHGetIDListFromObject");
57 pSHCreateItemFromParsingName = (void*)GetProcAddress(hmod, "SHCreateItemFromParsingName");
58 pSHGetSpecialFolderLocation = (void*)GetProcAddress(hmod, "SHGetSpecialFolderLocation");
61 /*******************************************************
62 * INameSpaceTreeControlEvents implementation.
64 enum { OnItemClick = 0, OnPropertyItemCommit, OnItemStateChanging, OnItemStateChanged,
65 OnSelectionChanged, OnKeyboardInput, OnBeforeExpand, OnAfterExpand, OnBeginLabelEdit,
66 OnEndLabelEdit, OnGetToolTip, OnBeforeItemDelete, OnItemAdded, OnItemDeleted,
67 OnBeforeContextMenu, OnAfterContextMenu, OnBeforeStateImageChange, OnGetDefaultIconIndex,
71 INameSpaceTreeControlEvents INameSpaceTreeControlEvents_iface;
72 UINT qi_called_count; /* Keep track of calls to QueryInterface */
73 BOOL qi_enable_events; /* If FALSE, QueryInterface returns only E_NOINTERFACE */
74 UINT count[LastEvent]; /* Keep track of calls to all On* functions. */
76 } INameSpaceTreeControlEventsImpl;
78 static inline INameSpaceTreeControlEventsImpl *impl_from_INameSpaceTreeControlEvents(INameSpaceTreeControlEvents *iface)
80 return CONTAINING_RECORD(iface, INameSpaceTreeControlEventsImpl, INameSpaceTreeControlEvents_iface);
83 static HRESULT WINAPI NSTCEvents_fnQueryInterface(
84 INameSpaceTreeControlEvents* iface,
88 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
90 This->qi_called_count++;
92 if(This->qi_enable_events && IsEqualIID(riid, &IID_INameSpaceTreeControlEvents))
94 IUnknown_AddRef(iface);
102 static ULONG WINAPI NSTCEvents_fnAddRef(
103 INameSpaceTreeControlEvents* iface)
105 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
107 return InterlockedIncrement(&This->ref);
110 static ULONG WINAPI NSTCEvents_fnRelease(
111 INameSpaceTreeControlEvents* iface)
113 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
115 return InterlockedDecrement(&This->ref);
118 static HRESULT WINAPI NSTCEvents_fnOnItemClick(
119 INameSpaceTreeControlEvents* iface,
121 NSTCEHITTEST nstceHitTest,
122 NSTCECLICKTYPE nstceClickType)
124 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
126 ok(psi != NULL, "NULL IShellItem\n");
127 This->count[OnItemClick]++;
131 static HRESULT WINAPI NSTCEvents_fnOnPropertyItemCommit(
132 INameSpaceTreeControlEvents* iface,
135 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
137 ok(psi != NULL, "NULL IShellItem\n");
138 This->count[OnPropertyItemCommit]++;
142 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanging(
143 INameSpaceTreeControlEvents* iface,
145 NSTCITEMSTATE nstcisMask,
146 NSTCITEMSTATE nstcisState)
148 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
150 ok(psi != NULL, "NULL IShellItem\n");
151 This->count[OnItemStateChanging]++;
155 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanged(
156 INameSpaceTreeControlEvents* iface,
158 NSTCITEMSTATE nstcisMask,
159 NSTCITEMSTATE nstcisState)
161 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
163 ok(psi != NULL, "NULL IShellItem\n");
164 This->count[OnItemStateChanged]++;
168 static HRESULT WINAPI NSTCEvents_fnOnSelectionChanged(
169 INameSpaceTreeControlEvents* iface,
170 IShellItemArray *psiaSelection)
172 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
174 ok(psiaSelection != NULL, "IShellItemArray was NULL.\n");
178 DWORD count = 0xdeadbeef;
179 hr = IShellItemArray_GetCount(psiaSelection, &count);
180 ok(hr == S_OK, "Got 0x%08x\n", hr);
181 ok(count == 1, "Got count 0x%x\n", count);
183 This->count[OnSelectionChanged]++;
187 static HRESULT WINAPI NSTCEvents_fnOnKeyboardInput(
188 INameSpaceTreeControlEvents* iface,
193 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
195 This->count[OnKeyboardInput]++;
196 ok(wParam == 0x1234, "Got unexpected wParam %lx\n", wParam);
197 ok(lParam == 0x1234, "Got unexpected lParam %lx\n", lParam);
201 static HRESULT WINAPI NSTCEvents_fnOnBeforeExpand(
202 INameSpaceTreeControlEvents* iface,
205 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
207 ok(psi != NULL, "NULL IShellItem\n");
208 This->count[OnBeforeExpand]++;
212 static HRESULT WINAPI NSTCEvents_fnOnAfterExpand(
213 INameSpaceTreeControlEvents* iface,
216 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
218 ok(psi != NULL, "NULL IShellItem\n");
219 This->count[OnAfterExpand]++;
223 static HRESULT WINAPI NSTCEvents_fnOnBeginLabelEdit(
224 INameSpaceTreeControlEvents* iface,
227 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
229 ok(psi != NULL, "NULL IShellItem\n");
230 This->count[OnBeginLabelEdit]++;
234 static HRESULT WINAPI NSTCEvents_fnOnEndLabelEdit(
235 INameSpaceTreeControlEvents* iface,
238 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
240 ok(psi != NULL, "NULL IShellItem\n");
241 This->count[OnEndLabelEdit]++;
245 static HRESULT WINAPI NSTCEvents_fnOnGetToolTip(
246 INameSpaceTreeControlEvents* iface,
251 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
253 ok(psi != NULL, "NULL IShellItem\n");
254 This->count[OnGetToolTip]++;
258 static HRESULT WINAPI NSTCEvents_fnOnBeforeItemDelete(
259 INameSpaceTreeControlEvents* iface,
262 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
264 ok(psi != NULL, "NULL IShellItem\n");
265 This->count[OnBeforeItemDelete]++;
269 static HRESULT WINAPI NSTCEvents_fnOnItemAdded(
270 INameSpaceTreeControlEvents* iface,
274 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
276 ok(psi != NULL, "NULL IShellItem\n");
277 This->count[OnItemAdded]++;
281 static HRESULT WINAPI NSTCEvents_fnOnItemDeleted(
282 INameSpaceTreeControlEvents* iface,
286 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
288 ok(psi != NULL, "NULL IShellItem\n");
289 This->count[OnItemDeleted]++;
293 static HRESULT WINAPI NSTCEvents_fnOnBeforeContextMenu(
294 INameSpaceTreeControlEvents* iface,
299 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
301 This->count[OnBeforeContextMenu]++;
305 static HRESULT WINAPI NSTCEvents_fnOnAfterContextMenu(
306 INameSpaceTreeControlEvents* iface,
312 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
314 This->count[OnAfterContextMenu]++;
318 static HRESULT WINAPI NSTCEvents_fnOnBeforeStateImageChange(
319 INameSpaceTreeControlEvents* iface,
322 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
324 ok(psi != NULL, "NULL IShellItem\n");
325 This->count[OnBeforeStateImageChange]++;
329 static HRESULT WINAPI NSTCEvents_fnOnGetDefaultIconIndex(
330 INameSpaceTreeControlEvents* iface,
335 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
337 ok(psi != NULL, "NULL IShellItem\n");
338 This->count[OnGetDefaultIconIndex]++;
342 static const INameSpaceTreeControlEventsVtbl vt_NSTCEvents = {
343 NSTCEvents_fnQueryInterface,
345 NSTCEvents_fnRelease,
346 NSTCEvents_fnOnItemClick,
347 NSTCEvents_fnOnPropertyItemCommit,
348 NSTCEvents_fnOnItemStateChanging,
349 NSTCEvents_fnOnItemStateChanged,
350 NSTCEvents_fnOnSelectionChanged,
351 NSTCEvents_fnOnKeyboardInput,
352 NSTCEvents_fnOnBeforeExpand,
353 NSTCEvents_fnOnAfterExpand,
354 NSTCEvents_fnOnBeginLabelEdit,
355 NSTCEvents_fnOnEndLabelEdit,
356 NSTCEvents_fnOnGetToolTip,
357 NSTCEvents_fnOnBeforeItemDelete,
358 NSTCEvents_fnOnItemAdded,
359 NSTCEvents_fnOnItemDeleted,
360 NSTCEvents_fnOnBeforeContextMenu,
361 NSTCEvents_fnOnAfterContextMenu,
362 NSTCEvents_fnOnBeforeStateImageChange,
363 NSTCEvents_fnOnGetDefaultIconIndex
366 static INameSpaceTreeControlEventsImpl *create_nstc_events(void)
368 INameSpaceTreeControlEventsImpl *This;
369 This = HeapAlloc(GetProcessHeap(), 0, sizeof(INameSpaceTreeControlEventsImpl));
370 This->INameSpaceTreeControlEvents_iface.lpVtbl = &vt_NSTCEvents;
376 /*********************************************************************
377 * Event count checking
379 static void ok_no_events_(INameSpaceTreeControlEventsImpl *impl,
380 const char *file, int line)
383 for(i = 0; i < LastEvent; i++)
386 (!impl->count[i], "Got event %d, count %d\n", i, impl->count[i]);
390 #define ok_no_events(impl) \
391 ok_no_events_(impl, __FILE__, __LINE__)
393 #define ok_event_count_broken(impl, event, c, b) \
394 do { ok(impl->count[event] == c || broken(impl->count[event] == b), \
395 "Got event %d, count %d\n", event, impl->count[event]); \
396 impl->count[event] = 0; \
399 #define ok_event_count(impl, event, c) \
400 ok_event_count_broken(impl, event, c, -1)
402 #define ok_event_broken(impl, event) \
403 do { ok(impl->count[event] || broken(!impl->count[event]), \
405 impl->count[event] = 0; \
408 #define ok_event(impl, event) \
409 do { ok(impl->count[event], "No event %d.\n", event); \
410 impl->count[event] = 0; \
413 /* Process some messages */
414 static void process_msgs(void)
421 while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
423 TranslateMessage(&msg);
424 DispatchMessage(&msg);
429 /* There seem to be a timer that sometimes fires after about
430 500ms, we need to wait for it. Failing to wait can result in
431 seemingly sporadic selection change events. (Timer ID is 87,
432 sending WM_TIMER manually does not seem to help us.) */
435 while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
437 TranslateMessage(&msg);
438 DispatchMessage(&msg);
442 /** Some functions from shell32/tests/shlfolder.c */
443 /* creates a file with the specified name for tests */
444 static void CreateTestFile(const CHAR *name)
449 file = CreateFileA(name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL);
450 if (file != INVALID_HANDLE_VALUE)
452 WriteFile(file, name, strlen(name), &written, NULL);
453 WriteFile(file, "\n", strlen("\n"), &written, NULL);
457 /* initializes the tests */
458 static void CreateFilesFolders(void)
460 CreateDirectoryA(".\\testdir", NULL);
461 CreateTestFile (".\\testdir\\test1.txt ");
462 CreateTestFile (".\\testdir\\test2.txt ");
463 CreateTestFile (".\\testdir\\test3.txt ");
464 CreateDirectoryA(".\\testdir\\testdir2 ", NULL);
465 CreateDirectoryA(".\\testdir\\testdir2\\subdir", NULL);
468 /* cleans after tests */
469 static void Cleanup(void)
471 DeleteFileA(".\\testdir\\test1.txt");
472 DeleteFileA(".\\testdir\\test2.txt");
473 DeleteFileA(".\\testdir\\test3.txt");
474 RemoveDirectoryA(".\\testdir\\testdir2\\subdir");
475 RemoveDirectoryA(".\\testdir\\testdir2");
476 RemoveDirectoryA(".\\testdir");
479 /* Based on PathAddBackslashW from dlls/shlwapi/path.c */
480 static LPWSTR myPathAddBackslashW( LPWSTR lpszPath )
484 if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
490 if (lpszPath[-1] != '\\')
499 static HWND get_treeview_hwnd(INameSpaceTreeControl *pnstc)
503 HWND treeview = NULL;
505 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
506 ok(hr == S_OK, "Got 0x%08x\n", hr);
510 hr = IOleWindow_GetWindow(pow, &host);
511 ok(hr == S_OK, "Got 0x%08x\n", hr);
513 treeview = FindWindowExW(host, NULL, WC_TREEVIEWW, NULL);
514 IOleWindow_Release(pow);
520 static LRESULT WINAPI treeview_subclass_proc(HWND hwnd_tv, UINT message, WPARAM wParam, LPARAM lParam)
522 WNDPROC oldproc = (WNDPROC)GetWindowLongPtrW(hwnd_tv, GWLP_USERDATA);
523 static LONG defwndproc_counter = 0;
527 msg.message = message;
528 msg.flags = sent|wparam|lparam;
529 if (defwndproc_counter) msg.flags |= defwinproc;
533 add_message(sequences, TREEVIEW_SEQ_INDEX, &msg);
535 if(message == TVM_SETITEMW)
537 memcpy(&last_tvi, (void*)lParam, sizeof(TVITEMEXW));
541 defwndproc_counter++;
542 ret = CallWindowProcW(oldproc, hwnd_tv, message, wParam, lParam);
543 defwndproc_counter--;
547 static BOOL subclass_treeview(INameSpaceTreeControl *pnstc)
550 WNDPROC oldproc = NULL;
552 hwnd_tv = get_treeview_hwnd(pnstc);
555 oldproc = (WNDPROC)SetWindowLongPtrW(hwnd_tv, GWLP_WNDPROC,
556 (LONG_PTR)treeview_subclass_proc);
557 SetWindowLongPtrW(hwnd_tv, GWLP_USERDATA, (LONG_PTR)oldproc);
558 ok(oldproc != NULL, "Failed to subclass.\n");
564 static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message)
566 struct msg_sequence *msg_seq = seq[sequence_index];
569 for(i = 0; i < msg_seq->count ; i++)
570 if(msg_seq->sequence[i].message == message)
576 /* Returns FALSE if the NamespaceTreeControl failed to be instantiated. */
577 static BOOL test_initialization(void)
579 INameSpaceTreeControl *pnstc;
587 hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
588 &IID_INameSpaceTreeControl, (void**)&pnstc);
589 ok(hr == S_OK || hr == REGDB_E_CLASSNOTREG, "Got 0x%08x\n", hr);
595 hr = INameSpaceTreeControl_Initialize(pnstc, NULL, NULL, 0);
596 ok(hr == HRESULT_FROM_WIN32(ERROR_TLW_WITH_WSCHILD), "Got (0x%08x)\n", hr);
598 hr = INameSpaceTreeControl_Initialize(pnstc, (HWND)0xDEADBEEF, NULL, 0);
599 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE), "Got (0x%08x)\n", hr);
601 ZeroMemory(&rc, sizeof(RECT));
602 hr = INameSpaceTreeControl_Initialize(pnstc, NULL, &rc, 0);
603 ok(hr == HRESULT_FROM_WIN32(ERROR_TLW_WITH_WSCHILD), "Got (0x%08x)\n", hr);
605 hr = INameSpaceTreeControl_Initialize(pnstc, (HWND)0xDEADBEEF, &rc, 0);
606 ok(hr == HRESULT_FROM_WIN32(ERROR_INVALID_WINDOW_HANDLE), "Got (0x%08x)\n", hr);
608 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
609 ok(hr == S_OK, "Got (0x%08x)\n", hr);
612 hr = IOleWindow_GetWindow(pow, &hwnd_host1);
613 ok(hr == S_OK, "Got (0x%08x)\n", hr);
614 ok(hwnd_host1 == NULL, "hwnd is not null.\n");
616 hr = IOleWindow_ContextSensitiveHelp(pow, TRUE);
617 ok(hr == E_NOTIMPL, "Got (0x%08x)\n", hr);
618 hr = IOleWindow_ContextSensitiveHelp(pow, FALSE);
619 ok(hr == E_NOTIMPL, "Got (0x%08x)\n", hr);
620 IOleWindow_Release(pow);
623 hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, NULL, 0);
624 ok(hr == S_OK, "Got (0x%08x)\n", hr);
625 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
626 ok(hr == S_OK, "Got 0x%08x\n", hr);
629 static const CHAR namespacetree[] = "NamespaceTreeControl";
631 LONG style, expected_style;
633 hr = IOleWindow_GetWindow(pow, &hwnd_host1);
634 ok(hr == S_OK, "Got (0x%08x)\n", hr);
635 ok(hwnd_host1 != NULL, "hwnd_host1 is null.\n");
637 GetClassNameA(hwnd_host1, buf, 1024);
638 ok(!lstrcmpA(namespacetree, buf), "Class name was %s\n", buf);
640 expected_style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
641 style = GetWindowLongPtrW(hwnd_host1, GWL_STYLE);
642 ok(style == expected_style, "Got style %08x\n", style);
645 style = GetWindowLongPtrW(hwnd_host1, GWL_EXSTYLE);
646 ok(style == expected_style, "Got style %08x\n", style);
649 style = SendMessageW(hwnd_host1, TVM_GETEXTENDEDSTYLE, 0, 0);
650 ok(style == expected_style, "Got 0x%08x\n", style);
652 hwnd_tv = FindWindowExW(hwnd_host1, NULL, WC_TREEVIEWW, NULL);
653 ok(hwnd_tv != NULL, "Failed to get treeview hwnd.\n");
656 expected_style = WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
657 WS_CLIPCHILDREN | WS_TABSTOP | TVS_NOHSCROLL |
658 TVS_NONEVENHEIGHT | TVS_INFOTIP | TVS_TRACKSELECT | TVS_EDITLABELS;
659 style = GetWindowLongPtrW(hwnd_tv, GWL_STYLE);
660 ok(style == expected_style, "Got style %08x\n", style);
663 style = GetWindowLongPtrW(hwnd_tv, GWL_EXSTYLE);
664 ok(style == expected_style, "Got style %08x\n", style);
666 expected_style = TVS_EX_NOSINGLECOLLAPSE | TVS_EX_DOUBLEBUFFER |
667 TVS_EX_RICHTOOLTIP | TVS_EX_DRAWIMAGEASYNC;
668 style = SendMessageW(hwnd_tv, TVM_GETEXTENDEDSTYLE, 0, 0);
669 todo_wine ok(style == expected_style, "Got 0x%08x\n", style);
672 IOleWindow_Release(pow);
677 /* The control can be initialized again without crashing, but
678 * the reference counting will break. */
679 hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, &rc, 0);
680 ok(hr == S_OK, "Got (0x%08x)\n", hr);
681 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
685 hr = IOleWindow_GetWindow(pow, &hwnd_host2);
686 ok(hr == S_OK, "Got (0x%08x)\n", hr);
687 ok(hwnd_host1 != hwnd_host2, "Same hwnd.\n");
688 IOleWindow_Release(pow);
692 /* Some "random" interfaces */
693 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceObject, (void**)&punk);
694 ok(hr == E_NOINTERFACE || hr == S_OK /* vista, w2k8 */, "Got (0x%08x)\n", hr);
695 if(SUCCEEDED(hr)) IUnknown_Release(punk);
696 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceActiveObject, (void**)&punk);
697 ok(hr == E_NOINTERFACE || hr == S_OK /* vista, w2k8 */, "Got (0x%08x)\n", hr);
698 if(SUCCEEDED(hr)) IUnknown_Release(punk);
699 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceObjectWindowless, (void**)&punk);
700 ok(hr == E_NOINTERFACE || hr == S_OK /* vista, w2k8 */, "Got (0x%08x)\n", hr);
701 if(SUCCEEDED(hr)) IUnknown_Release(punk);
703 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceUIWindow, (void**)&punk);
704 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
705 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceFrame, (void**)&punk);
706 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
707 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceSite, (void**)&punk);
708 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
709 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceSiteEx, (void**)&punk);
710 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
711 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleInPlaceSiteWindowless, (void**)&punk);
712 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
714 /* On windows, the reference count won't go to zero until the
715 * window is destroyed. */
716 INameSpaceTreeControl_AddRef(pnstc);
717 lres = INameSpaceTreeControl_Release(pnstc);
718 ok(lres > 1, "Reference count was (%d).\n", lres);
720 DestroyWindow(hwnd_host1);
721 lres = INameSpaceTreeControl_Release(pnstc);
722 ok(!lres, "lres was %d\n", lres);
727 static void verify_root_order_(INameSpaceTreeControl *pnstc, IShellItem **roots,
728 const char *file, int line)
731 IShellItemArray *psia;
733 hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
734 ok_(file,line) (hr == S_OK, "GetRootItems: got (0x%08x)\n", hr);
737 DWORD i, expected, count = -1;
738 hr = IShellItemArray_GetCount(psia, &count);
739 ok_(file,line) (hr == S_OK, "Got (0x%08x)\n", hr);
741 for(expected = 0; roots[expected] != NULL; expected++);
742 ok_(file,line) (count == expected, "Got %d roots, expected %d\n", count, expected);
744 for(i = 0; i < count && roots[i] != NULL; i++)
747 hr = IShellItemArray_GetItemAt(psia, i, &psi);
748 ok_(file,line) (hr == S_OK, "GetItemAt %i: got 0x%08x\n", i, hr);
752 hr = IShellItem_Compare(psi, roots[i], SICHINT_DISPLAY, &cmp);
753 ok_(file,line) (hr == S_OK, "Compare %i: got 0x%08x\n", i, hr);
754 IShellItem_Release(psi);
757 IShellItemArray_Release(psia);
760 #define verify_root_order(pnstc, psi_a) \
761 verify_root_order_(pnstc, psi_a, __FILE__, __LINE__)
763 static void test_basics(void)
765 INameSpaceTreeControl *pnstc;
766 INameSpaceTreeControl2 *pnstc2;
767 IShellItemArray *psia;
768 IShellFolder *psfdesktop;
770 IShellItem *psidesktop, *psidesktop2;
771 IShellItem *psitestdir, *psitestdir2, *psitest1;
773 LPITEMIDLIST pidl_desktop;
774 NSTCITEMSTATE istate;
779 IShellItem *roots[10];
782 WCHAR curdirW[MAX_PATH];
784 static const WCHAR testdirW[] = {'t','e','s','t','d','i','r',0};
785 static const WCHAR testdir2W[] =
786 {'t','e','s','t','d','i','r','\\','t','e','s','t','d','i','r','2',0};
787 static const WCHAR test1W[] =
788 {'t','e','s','t','d','i','r','\\','t','e','s','t','1','.','t','x','t',0};
789 static const WCHAR explorerW[] = {'E','x','p','l','o','r','e','r',0};
790 static const WCHAR randomW[] = {'_','_','h','e','l','l','o',0};
792 /* These should exist on platforms supporting the NSTC */
793 ok(pSHCreateShellItem != NULL, "No SHCreateShellItem.\n");
794 ok(pSHCreateItemFromParsingName != NULL, "No SHCreateItemFromParsingName\n");
795 ok(pSHGetIDListFromObject != NULL, "No SHCreateShellItem.\n");
796 ok(pSHCreateItemFromParsingName != NULL, "No SHCreateItemFromParsingName\n");
798 /* Create ShellItems for testing. */
799 SHGetDesktopFolder(&psfdesktop);
800 hr = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl_desktop);
801 ok(hr == S_OK, "Got 0x%08x\n", hr);
804 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop);
805 ok(hr == S_OK, "Got 0x%08x\n", hr);
808 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop2);
809 ok(hr == S_OK, "Got 0x%08x\n", hr);
810 if(FAILED(hr)) IShellItem_Release(psidesktop);
812 ILFree(pidl_desktop);
814 IShellFolder_Release(psfdesktop);
818 win_skip("Test setup failed.\n");
822 ok(psidesktop != psidesktop2, "psidesktop == psidesktop2\n");
824 CreateFilesFolders();
825 GetCurrentDirectoryW(MAX_PATH, curdirW);
826 ok(lstrlenW(curdirW), "Got 0 length string.\n");
828 lstrcpyW(buf, curdirW);
829 myPathAddBackslashW(buf);
830 lstrcatW(buf, testdirW);
831 hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psitestdir);
832 ok(hr == S_OK, "Got 0x%08x\n", hr);
833 if(FAILED(hr)) goto cleanup;
834 lstrcpyW(buf, curdirW);
835 myPathAddBackslashW(buf);
836 lstrcatW(buf, testdir2W);
837 hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psitestdir2);
838 ok(hr == S_OK, "Got 0x%08x\n", hr);
839 if(FAILED(hr)) goto cleanup;
840 lstrcpyW(buf, curdirW);
841 myPathAddBackslashW(buf);
842 lstrcatW(buf, test1W);
843 hr = pSHCreateItemFromParsingName(buf, NULL, &IID_IShellItem, (void**)&psitest1);
844 ok(hr == S_OK, "Got 0x%08x\n", hr);
845 if(FAILED(hr)) goto cleanup;
847 hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
848 &IID_INameSpaceTreeControl, (void**)&pnstc);
849 ok(hr == S_OK, "Failed to initialize control (0x%08x)\n", hr);
851 /* Some tests on an uninitialized control */
852 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
853 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
854 hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
855 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
856 hr = INameSpaceTreeControl_RemoveRoot(pnstc, NULL);
857 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
858 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_NONFOLDERS, 0, NULL);
859 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
862 /* Initialize the control */
863 rc.top = rc.left = 0; rc.right = rc.bottom = 200;
864 hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, &rc, 0);
865 ok(hr == S_OK, "Got (0x%08x)\n", hr);
868 /* Set/GetControlStyle(2) */
869 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_INameSpaceTreeControl2, (void**)&pnstc2);
870 ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Got 0x%08x\n", hr);
876 static const NSTCSTYLE2 styles2[] =
877 { NSTCS2_INTERRUPTNOTIFICATIONS,NSTCS2_SHOWNULLSPACEMENU,
878 NSTCS2_DISPLAYPADDING,NSTCS2_DISPLAYPINNEDONLY,
879 NTSCS2_NOSINGLETONAUTOEXPAND,NTSCS2_NEVERINSERTNONENUMERATED, 0};
882 /* We can use this to differentiate between two versions of
883 * this interface. Windows 7 returns hr == S_OK. */
884 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0, 0);
885 ok(hr == S_OK || broken(hr == E_FAIL), "Got 0x%08x\n", hr);
888 static const NSTCSTYLE styles_setable[] =
889 { NSTCS_HASEXPANDOS,NSTCS_HASLINES,NSTCS_SINGLECLICKEXPAND,
890 NSTCS_FULLROWSELECT,NSTCS_HORIZONTALSCROLL,
891 NSTCS_ROOTHASEXPANDO,NSTCS_SHOWSELECTIONALWAYS,NSTCS_NOINFOTIP,
892 NSTCS_EVENHEIGHT,NSTCS_NOREPLACEOPEN,NSTCS_DISABLEDRAGDROP,
893 NSTCS_NOORDERSTREAM,NSTCS_BORDER,NSTCS_NOEDITLABELS,
894 NSTCS_TABSTOP,NSTCS_FAVORITESMODE,NSTCS_EMPTYTEXT,NSTCS_CHECKBOXES,
895 NSTCS_ALLOWJUNCTIONS,NSTCS_SHOWTABSBUTTON,NSTCS_SHOWDELETEBUTTON,
896 NSTCS_SHOWREFRESHBUTTON, 0};
897 static const NSTCSTYLE styles_nonsetable[] =
898 { NSTCS_SPRINGEXPAND, NSTCS_RICHTOOLTIP, NSTCS_AUTOHSCROLL,
899 NSTCS_FADEINOUTEXPANDOS,
900 NSTCS_PARTIALCHECKBOXES, NSTCS_EXCLUSIONCHECKBOXES,
901 NSTCS_DIMMEDCHECKBOXES, NSTCS_NOINDENTCHECKS,0};
903 /* Set/GetControlStyle */
904 style = style2 = 0xdeadbeef;
905 hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
906 ok(hr == S_OK, "Got 0x%08x\n", hr);
907 ok(style == 0, "Got style %x\n", style);
909 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0, 0xFFFFFFF);
910 ok(hr == S_OK, "Got 0x%08x\n", hr);
912 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0xFFFFFFFF, 0);
913 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
914 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0xFFFFFFFF, 0xFFFFFFFF);
915 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
918 for(i = 0; styles_setable[i] != 0; i++)
920 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_setable[i], styles_setable[i]);
921 ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles_setable[i]);
922 if(SUCCEEDED(hr)) tmp |= styles_setable[i];
924 for(i = 0; styles_nonsetable[i] != 0; i++)
926 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_nonsetable[i], styles_nonsetable[i]);
927 ok(hr == E_FAIL, "Got 0x%08x (%x)\n", hr, styles_nonsetable[i]);
930 hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
931 ok(hr == S_OK, "Got 0x%08x\n", hr);
932 ok(style == tmp, "Got style %x (expected %x)\n", style, tmp);
936 for(i = 0; styles_setable[i] != 0; i++)
938 hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, styles_setable[i], &tmp2);
939 ok(hr == S_OK, "Got 0x%08x\n", hr);
940 ok(tmp2 == (style & styles_setable[i]), "Got %x\n", tmp2);
944 for(i = 0; styles_setable[i] != 0; i++)
946 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_setable[i], 0);
947 ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles_setable[i]);
949 for(i = 0; styles_nonsetable[i] != 0; i++)
951 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_nonsetable[i], 0);
952 ok(hr == E_FAIL, "Got 0x%08x (%x)\n", hr, styles_nonsetable[i]);
954 hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
955 ok(hr == S_OK, "Got 0x%08x\n", hr);
956 ok(style == 0, "Got style %x\n", style);
958 /* Set/GetControlStyle2 */
959 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
960 ok(hr == S_OK, "Got 0x%08x\n", hr);
961 ok(style2 == 0, "Got style %x\n", style2);
963 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0, 0);
964 ok(hr == S_OK, "Got 0x%08x\n", hr);
965 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0, 0xFFFFFFFF);
966 ok(hr == S_OK, "Got 0x%08x\n", hr);
968 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0);
969 ok(hr == S_OK, "Got 0x%08x\n", hr);
970 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0xFFFFFFFF);
971 ok(hr == S_OK, "Got 0x%08x\n", hr);
973 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0);
974 ok(hr == S_OK, "Got 0x%08x\n", hr);
975 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
976 ok(hr == S_OK, "Got 0x%08x\n", hr);
977 ok(style2 == 0x00000000, "Got style %x\n", style2);
979 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
980 ok(hr == S_OK, "Got 0x%08x\n", hr);
981 ok(style2 == 0, "Got style %x\n", style2);
984 for(i = 0; styles2[i] != 0; i++)
986 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], styles2[i]);
987 ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
988 if(SUCCEEDED(hr)) tmp |= styles2[i];
991 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
992 ok(hr == S_OK, "Got 0x%08x\n", hr);
993 ok(style2 == tmp, "Got style %x (expected %x)\n", style2, tmp);
997 for(i = 0; styles2[i] != 0; i++)
999 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, styles2[i], &tmp2);
1000 ok(hr == S_OK, "Got 0x%08x\n", hr);
1001 ok(tmp2 == (style2 & styles2[i]), "Got %x\n", tmp2);
1005 for(i = 0; styles2[i] != 0; i++)
1007 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], 0);
1008 ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
1010 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
1011 ok(hr == S_OK, "Got 0x%08x\n", hr);
1012 ok(style2 == 0, "Got style %x (expected 0)\n", style2);
1016 /* 64-bit Windows Vista (others?) seems to have a somewhat
1017 * different idea of how the methods of this interface
1020 static const NSTCSTYLE styles[] =
1021 { NSTCS_HASEXPANDOS,NSTCS_HASLINES,NSTCS_SINGLECLICKEXPAND,
1022 NSTCS_FULLROWSELECT,NSTCS_SPRINGEXPAND,NSTCS_HORIZONTALSCROLL,
1023 NSTCS_RICHTOOLTIP, NSTCS_AUTOHSCROLL,
1024 NSTCS_FADEINOUTEXPANDOS,
1025 NSTCS_PARTIALCHECKBOXES,NSTCS_EXCLUSIONCHECKBOXES,
1026 NSTCS_DIMMEDCHECKBOXES, NSTCS_NOINDENTCHECKS,
1027 NSTCS_ROOTHASEXPANDO,NSTCS_SHOWSELECTIONALWAYS,NSTCS_NOINFOTIP,
1028 NSTCS_EVENHEIGHT,NSTCS_NOREPLACEOPEN,NSTCS_DISABLEDRAGDROP,
1029 NSTCS_NOORDERSTREAM,NSTCS_BORDER,NSTCS_NOEDITLABELS,
1030 NSTCS_TABSTOP,NSTCS_FAVORITESMODE,NSTCS_EMPTYTEXT,NSTCS_CHECKBOXES,
1031 NSTCS_ALLOWJUNCTIONS,NSTCS_SHOWTABSBUTTON,NSTCS_SHOWDELETEBUTTON,
1032 NSTCS_SHOWREFRESHBUTTON, 0};
1033 trace("Detected broken INameSpaceTreeControl2.\n");
1036 hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
1037 ok(hr == S_OK, "Got 0x%08x\n", hr);
1038 ok(style == 0xdeadbeef, "Got style %x\n", style);
1040 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
1041 ok(hr == S_OK, "Got 0x%08x\n", hr);
1042 ok(style2 == 0, "Got style %x\n", style2);
1045 for(i = 0; styles[i] != 0; i++)
1047 hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles[i], styles[i]);
1048 ok(hr == E_FAIL || ((styles[i] & NSTCS_SPRINGEXPAND) && hr == S_OK),
1049 "Got 0x%08x (%x)\n", hr, styles[i]);
1050 if(SUCCEEDED(hr)) tmp |= styles[i];
1054 hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, tmp, &style);
1055 ok(hr == S_OK, "Got 0x%08x\n", hr);
1056 ok(style == 0xdeadbeef, "Got style %x\n", style);
1059 for(i = 0; styles2[i] != 0; i++)
1061 hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], styles2[i]);
1062 ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
1063 if(SUCCEEDED(hr)) tmp |= styles2[i];
1066 style2 = 0xdeadbeef;
1067 hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
1068 ok(hr == S_OK, "Got 0x%08x\n", hr);
1069 ok(style2 == tmp, "Got style %x\n", style2);
1073 INameSpaceTreeControl2_Release(pnstc2);
1077 skip("INameSpaceTreeControl2 missing.\n");
1080 hr = INameSpaceTreeControl_RemoveRoot(pnstc, NULL);
1081 ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
1083 /* Append / Insert root */
1086 /* Crashes under Windows 7 */
1087 INameSpaceTreeControl_AppendRoot(pnstc, NULL, SHCONTF_FOLDERS, 0, NULL);
1088 INameSpaceTreeControl_InsertRoot(pnstc, 0, NULL, SHCONTF_FOLDERS, 0, NULL);
1091 /* Note the usage of psidesktop and psidesktop2 */
1092 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1093 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1094 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1095 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1096 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop2, SHCONTF_FOLDERS, 0, NULL);
1097 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1100 hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
1101 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1102 hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
1103 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1104 hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
1105 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1107 hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
1108 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
1109 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1110 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
1112 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1113 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1114 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1115 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1117 hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1118 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1119 hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1120 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1121 hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1122 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1123 hr = INameSpaceTreeControl_InsertRoot(pnstc, 50, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1124 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1125 hr = INameSpaceTreeControl_InsertRoot(pnstc, 1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
1126 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1128 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1129 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1134 /* Crashes on native. */
1135 INameSpaceTreeControl_GetRootItems(pnstc, NULL);
1138 hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
1139 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
1141 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0, 0, NULL);
1142 ok(hr == S_OK, "Got 0x%08x\n", hr);
1143 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop2, 0, 0, NULL);
1144 ok(hr == S_OK, "Got 0x%08x\n", hr);
1145 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir, 0, 0, NULL);
1146 ok(hr == S_OK, "Got 0x%08x\n", hr);
1147 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2, 0, 0, NULL);
1148 ok(hr == S_OK, "Got 0x%08x\n", hr);
1150 roots[0] = psidesktop;
1151 roots[1] = psidesktop2;
1152 roots[2] = psitestdir;
1153 roots[3] = psitestdir2;
1155 verify_root_order(pnstc, roots);
1157 hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, psitestdir2, 0, 0, NULL);
1158 ok(hr == S_OK, "Got 0x%08x\n", hr);
1160 roots[0] = psitestdir2;
1161 roots[1] = psidesktop;
1162 roots[2] = psidesktop2;
1163 roots[3] = psitestdir;
1164 roots[4] = psitestdir2;
1166 verify_root_order(pnstc, roots);
1168 hr = INameSpaceTreeControl_InsertRoot(pnstc, 5, psidesktop, 0, 0, NULL);
1169 ok(hr == S_OK, "Got 0x%08x\n", hr);
1171 roots[5] = psidesktop;
1173 verify_root_order(pnstc, roots);
1175 hr = INameSpaceTreeControl_InsertRoot(pnstc, 3, psitestdir2, 0, 0, NULL);
1176 ok(hr == S_OK, "Got 0x%08x\n", hr);
1178 roots[3] = psitestdir2;
1179 roots[4] = psitestdir;
1180 roots[5] = psitestdir2;
1181 roots[6] = psidesktop;
1183 verify_root_order(pnstc, roots);
1185 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2, 0, 0, NULL);
1186 ok(hr == S_OK, "Got 0x%08x\n", hr);
1188 roots[7] = psitestdir2;
1190 verify_root_order(pnstc, roots);
1192 hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, 0, 0, NULL);
1193 ok(hr == S_OK, "Got 0x%08x\n", hr);
1195 roots[0] = psidesktop;
1196 roots[1] = psitestdir2;
1197 roots[2] = psidesktop;
1198 roots[3] = psidesktop2;
1199 roots[4] = psitestdir2;
1200 roots[5] = psitestdir;
1201 roots[6] = psitestdir2;
1202 roots[7] = psidesktop;
1203 roots[8] = psitestdir2;
1205 verify_root_order(pnstc, roots);
1208 hr = INameSpaceTreeControl_CollapseAll(pnstc);
1209 ok(hr == S_OK, "Got 0x%08x\n", hr);
1211 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1212 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1214 hr = INameSpaceTreeControl_CollapseAll(pnstc);
1215 ok(hr == S_OK, "Got 0x%08x\n", hr);
1217 /* SetItemState message checks */
1218 res = subclass_treeview(pnstc);
1219 ok(res, "Failed to subclass treeview.\n");
1222 UINT isMask, isFlags;
1224 hr = INameSpaceTreeControl_AppendRoot(
1225 pnstc, psidesktop, SHCONTF_NONFOLDERS | SHCONTF_FOLDERS, 0, NULL);
1226 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1227 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1230 * The first expansion results in an "unrelated" TVM_SETITEMW being sent
1231 * (mask == 0x50 (TVIF_CHILDREN|TVIF_HANDLE) )
1234 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
1235 NSTCIS_EXPANDED, NSTCIS_EXPANDED);
1236 ok(hr == S_OK, "Got 0x%08x\n", hr);
1239 ok(tvi_count == 1, "Got %d\n", tvi_count);
1240 ok(last_tvi.mask == 0x50, "Got mask %x, expected 0x50\n", last_tvi.mask);
1244 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
1245 NSTCIS_EXPANDED, NSTCIS_EXPANDED);
1246 ok(hr == S_OK, "Got 0x%08x\n", hr);
1247 ok(tvi_count == 0, "Got %d\n", tvi_count);
1249 /* Test all the combinations of NSTCIS_SELECTED to NSTCIS_SELECTEDNOEXPAND */
1250 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1251 for(isMask = 0; isMask <= 0x1f; isMask++)
1253 for(isFlags = 0; isFlags <= 0x1f; isFlags++)
1255 UINT select_sent, select_sent_vista, ensurev_sent, expand_sent;
1259 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1262 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, isMask, isFlags);
1263 ok(hr == S_OK, "(%x|%x)Got 0x%08x\n", isMask, isFlags, hr);
1265 /*****************************/
1266 /* Calculate expected values */
1267 /*****************************/
1269 /* Number of TVM_SELECTITEM/TVM_ENSUREVISIBLE and TVM_EXPAND sent */
1270 select_sent = ((isMask&isFlags) & NSTCIS_SELECTED)?1:0;
1271 select_sent_vista = ensurev_sent = select_sent;
1273 select_sent += ((isMask&isFlags) & NSTCIS_SELECTEDNOEXPAND)?1:0;
1274 select_sent_vista += ((isMask&isFlags) & NSTCIS_EXPANDED)?1:0;
1275 expand_sent = ((isMask|isFlags) & NSTCIS_EXPANDED)?1:0;
1277 /* Possible TWM_SETITEMW message and its contents */
1278 if(isMask & NSTCIS_DISABLED)
1279 tviexp.mask = TVIF_STATE | TVIF_STATEEX;
1280 else if( ((isMask^isFlags) & (NSTCIS_SELECTED|NSTCIS_EXPANDED|NSTCIS_SELECTEDNOEXPAND)) ||
1281 ((isMask|isFlags) & NSTCIS_BOLD) || (isFlags & NSTCIS_DISABLED) )
1282 tviexp.mask = TVIF_STATE;
1288 tviexp.stateMask = tviexp.state = 0;
1289 tviexp.stateMask |= ((isMask^isFlags)&NSTCIS_SELECTED) ? TVIS_SELECTED : 0;
1290 tviexp.stateMask |= (isMask|isFlags)&NSTCIS_BOLD ? TVIS_BOLD:0;
1291 tviexp.state |= (isMask&isFlags)&NSTCIS_BOLD ? TVIS_BOLD:0;
1293 if((isMask&NSTCIS_EXPANDED)^(isFlags&NSTCIS_EXPANDED))
1295 tviexp.stateMask = 0;
1298 tviexp.uStateEx = (isFlags&isMask)&NSTCIS_DISABLED?TVIS_EX_DISABLED:0;
1302 /* Make sure that no tests accidentally succeeded
1303 * (and avoid a gcc warning) */
1304 tviexp.stateMask = tviexp.state = tviexp.uStateEx = -1;
1307 /*****************************/
1308 /* Check the values. */
1309 /*****************************/
1311 msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_SELECTITEM);
1312 ok(msg_count == select_sent || broken(msg_count == select_sent_vista),
1313 "(%x|%x) Got msg_count %d, expected %d (%d)\n",
1314 isMask, isFlags, msg_count, select_sent, select_sent_vista);
1315 msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_ENSUREVISIBLE);
1316 ok(msg_count == ensurev_sent || broken(msg_count == 0 /* Vista */),
1317 "(%x|%x) Got msg_count %d, expected %d\n",
1318 isMask, isFlags, msg_count, ensurev_sent);
1319 msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_EXPAND);
1320 ok(msg_count == expand_sent, "(%x|%x) Got msg_count %d, expected %d\n",
1321 isMask, isFlags, msg_count, expand_sent);
1323 msg_count = get_msg_count(sequences, TREEVIEW_SEQ_INDEX, TVM_SETITEMW);
1326 /* Four special cases for vista */
1327 BOOL vista_check = ( (isMask == 0x10 && isFlags == 0x10) ||
1328 (isMask == 0x11 && isFlags == 0x11) ||
1329 (isMask == 0x12 && isFlags == 0x12) ||
1330 (isMask == 0x13 && isFlags == 0x13) );
1332 ok(msg_count == 0 || broken(msg_count == 1 && vista_check),
1333 "(%x|%x) Got msg_count %d (tviexp.mask %x)\n",
1334 isMask, isFlags, msg_count, tviexp.mask);
1338 ok(msg_count == 1, "(%x|%x) Got msg_count %d, expected 1\n",
1339 isMask, isFlags, msg_count);
1340 ok(last_tvi.mask == tviexp.mask,
1341 "(%x|%x) Got mask %x, expected %x\n",
1342 isMask, isFlags, last_tvi.mask, tviexp.mask);
1343 ok(last_tvi.stateMask == tviexp.stateMask,
1344 "(%x|%x) Got stateMask %x, expected %x\n",
1345 isMask, isFlags, last_tvi.stateMask, tviexp.stateMask);
1346 ok(last_tvi.state == tviexp.state,
1347 "(%x|%x) Got state %x, expected %x\n",
1348 isMask, isFlags, last_tvi.state, tviexp.state);
1349 ok(last_tvi.uStateEx == tviexp.uStateEx,
1350 "(%x|%x) Got uStateEx %x, expected %x\n",
1351 isMask, isFlags, last_tvi.uStateEx, tviexp.uStateEx);
1355 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1356 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1359 /* GetSelectedItems */
1362 /* Crashes under Windows 7 */
1363 INameSpaceTreeControl_GetSelectedItems(pnstc, NULL);
1366 psia = (void*)0xdeadbeef;
1367 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1368 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1369 ok(psia == (void*)0xdeadbeef, "Got %p\n", psia);
1371 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2, SHCONTF_FOLDERS, 0, NULL);
1372 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1375 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir, SHCONTF_FOLDERS, 0, NULL);
1376 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1379 hr = INameSpaceTreeControl_SetItemState(pnstc, psitestdir,
1380 NSTCIS_SELECTED, NSTCIS_SELECTED);
1381 ok(hr == S_OK, "Got 0x%08x\n", hr);
1383 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1384 ok(hr == S_OK, "Got 0x%08x\n", hr);
1388 hr = IShellItemArray_GetCount(psia, &count);
1389 ok(hr == S_OK, "Got 0x%08x\n", hr);
1390 ok(count == 1, "Got %d selected items.\n", count);
1393 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1394 ok(hr == S_OK, "Got 0x%08x\n", hr);
1398 hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
1399 ok(hr == S_OK, "Got 0x%08x\n", hr);
1400 IShellItem_Release(psi);
1403 IShellItemArray_Release(psia);
1406 hr = INameSpaceTreeControl_SetItemState(pnstc, psitestdir2,
1407 NSTCIS_SELECTED, NSTCIS_SELECTED);
1408 ok(hr == S_OK, "Got 0x%08x\n", hr);
1411 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1412 ok(hr == S_OK, "Got 0x%08x\n", hr);
1416 hr = IShellItemArray_GetCount(psia, &count);
1417 ok(hr == S_OK, "Got 0x%08x\n", hr);
1418 ok(count == 1, "Got %d selected items.\n", count);
1421 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1422 ok(hr == S_OK, "Got 0x%08x\n", hr);
1426 hr = IShellItem_Compare(psi, psitestdir2, SICHINT_DISPLAY, &cmp);
1427 ok(hr == S_OK, "Got 0x%08x\n", hr);
1428 IShellItem_Release(psi);
1431 IShellItemArray_Release(psia);
1434 hr = INameSpaceTreeControl_SetItemState(pnstc, psitest1,
1435 NSTCIS_SELECTED, NSTCIS_SELECTED);
1436 todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
1437 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1438 ok(hr == S_OK, "Got 0x%08x\n", hr);
1442 hr = IShellItemArray_GetCount(psia, &count);
1443 ok(hr == S_OK, "Got 0x%08x\n", hr);
1444 ok(count == 1, "Got %d selected items.\n", count);
1447 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1448 ok(hr == S_OK, "Got 0x%08x\n", hr);
1452 hr = IShellItem_Compare(psi, psitest1, SICHINT_DISPLAY, &cmp);
1453 todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
1454 IShellItem_Release(psi);
1457 IShellItemArray_Release(psia);
1460 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1461 ok(hr == S_OK || broken(hr == E_FAIL), "Got 0x%08x\n", hr);
1464 /* For some reason, Vista fails to properly remove both the
1465 * roots here on the first try. */
1466 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1467 ok(hr == S_OK, "Got 0x%08x\n", hr);
1470 /* Adding without NSTCRS_EXPANDED does not set the selection */
1471 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
1472 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1474 ok(hr == S_OK, "Got 0x%08x\n", hr);
1477 hr = INameSpaceTreeControl_GetItemState(pnstc, psitestdir, 0xFF, &istate);
1478 ok(hr == S_OK, "Got 0x%08x\n", hr);
1479 ok(!(istate & NSTCIS_SELECTED), "Got 0x%08x\n", istate);
1480 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1481 ok(hr == E_FAIL, "Got 0x%08x\n", hr);
1482 if(SUCCEEDED(hr)) IShellItemArray_Release(psia);
1484 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1485 ok(hr == S_OK, "Got 0x%08x\n", hr);
1487 /* Adding with NSTCRS_EXPANDED sets the selection */
1488 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
1489 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1490 NSTCRS_EXPANDED, NULL);
1491 ok(hr == S_OK, "Got 0x%08x\n", hr);
1494 hr = INameSpaceTreeControl_GetItemState(pnstc, psitestdir, 0xFF, &istate);
1495 ok(hr == S_OK, "Got 0x%08x\n", hr);
1496 todo_wine ok(istate & NSTCIS_SELECTED, "Got 0x%08x\n", istate);
1497 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1498 todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
1503 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1507 hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
1508 ok(hr == S_OK, "Got 0x%08x\n", hr);
1510 IShellItem_Release(psi);
1513 IShellItemArray_Release(psia);
1516 /* Adding a second root with NSTCRS_EXPANDED does not change the selection */
1517 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir2,
1518 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1519 NSTCRS_EXPANDED, NULL);
1520 ok(hr == S_OK, "Got 0x%08x\n", hr);
1523 hr = INameSpaceTreeControl_GetItemState(pnstc, psitestdir2, 0xFF, &istate);
1524 ok(hr == S_OK, "Got 0x%08x\n", hr);
1525 ok(!(istate & NSTCIS_SELECTED), "Got 0x%08x\n", istate);
1526 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1527 todo_wine ok(hr == S_OK, "Got 0x%08x\n", hr);
1532 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1536 hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
1537 ok(hr == S_OK, "Got 0x%08x\n", hr);
1539 IShellItem_Release(psi);
1542 IShellItemArray_Release(psia);
1545 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1546 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1549 rc.top = rc.left = rc.bottom = rc.right = 0;
1552 /* Crashes under win 7 */
1553 INameSpaceTreeControl_GetItemRect(pnstc, NULL, NULL);
1554 INameSpaceTreeControl_GetItemRect(pnstc, psitestdir, NULL);
1555 INameSpaceTreeControl_GetItemRect(pnstc, NULL, &rc);
1558 hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir, &rc);
1559 ok(hr == E_INVALIDARG, "Got 0x%08x\n", hr);
1561 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
1562 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1563 NSTCRS_EXPANDED, NULL);
1564 ok(hr == S_OK, "Got 0x%08x\n", hr);
1567 hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir, &rc);
1568 ok(hr == S_OK, "Got 0x%08x\n", hr);
1569 ok(rc.top != rc.bottom, "Got 0 height.\n");
1570 ok(rc.left != rc.bottom, "Got 0 width.\n");
1573 hwnd_tv = get_treeview_hwnd(pnstc);
1576 HTREEITEM hroot = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_ROOT, 0);
1577 ok(hroot != NULL, "Failed to get root.\n");
1583 *(HTREEITEM*)&tv_rc = hroot;
1584 bret = SendMessageW(hwnd_tv, TVM_GETITEMRECT, FALSE, (LPARAM)&tv_rc);
1585 ok(bret, "TVM_GETITEMRECT failed.\n");
1587 /* The NamespaceTreeControl returns screen coordinates. */
1588 MapWindowPoints(NULL, hwnd, (POINT*)&rc, 2);
1589 ok(rc.left == tv_rc.left, "Differed, got %d and %d\n", rc.left, tv_rc.left);
1590 ok(rc.top == tv_rc.top, "Differed, got %d and %d\n", rc.top, tv_rc.top);
1591 ok(rc.right == tv_rc.right, "Differed, got %d and %d\n", rc.right, tv_rc.right);
1592 ok(rc.bottom == tv_rc.bottom, "Differed, got %d and %d\n", rc.bottom, tv_rc.bottom);
1594 /* Save the height and compare to that of other items.
1595 Observed values: 18, 19, 21 */
1596 height = rc.bottom - rc.top;
1597 trace("height: %d\n", height);
1601 win_skip("Skipping some GetItemRect tests.\n");
1603 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1604 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1607 hr = INameSpaceTreeControl_HitTest(pnstc, NULL, NULL);
1608 ok(hr == E_POINTER, "Got 0x%08x\n", hr);
1609 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, NULL);
1610 ok(hr == E_POINTER, "Got 0x%08x\n", hr);
1611 hr = INameSpaceTreeControl_HitTest(pnstc, NULL, &psi);
1612 ok(hr == E_POINTER, "Got 0x%08x\n", hr);
1614 psi = (void*)0xdeadbeef;
1616 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1617 ok(hr == S_FALSE, "Got 0x%08x\n", hr);
1618 ok(psi == NULL, "Got psi %p\n", psi);
1620 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
1621 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1622 NSTCRS_EXPANDED, NULL);
1623 ok(hr == S_OK, "Got 0x%08x\n", hr);
1626 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1627 ok(hr == S_OK, "Got 0x%08x\n", hr);
1631 hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
1632 ok(hr == S_OK, "Got 0x%08x\n", hr);
1633 ok(!cmp, "Got cmp %d\n", cmp);
1634 IShellItem_Release(psi);
1638 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1639 ok(hr == S_OK, "Got 0x%08x\n", hr);
1643 hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
1644 ok(hr == S_OK, "Got 0x%08x\n", hr);
1645 ok(!cmp, "Got cmp %d\n", cmp);
1646 IShellItem_Release(psi);
1650 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1651 ok(hr == S_OK, "Got 0x%08x\n", hr);
1657 hr = IShellItem_Compare(psi, psitestdir, SICHINT_DISPLAY, &cmp);
1658 ok(hr == S_FALSE, "Got 0x%08x\n", hr);
1659 ok(cmp, "no cmp value.\n");
1660 hr = IShellItem_Compare(psi, psitestdir2, SICHINT_DISPLAY, &cmp);
1661 ok(hr == S_OK, "Got 0x%08x\n", hr);
1662 ok(!cmp, "Got cmp %d\n", cmp);
1664 IShellItem_Release(psi);
1667 hr = INameSpaceTreeControl_GetItemRect(pnstc, psitestdir2, &rc);
1668 ok(hr == S_OK, "Got 0x%08x\n", hr);
1671 MapWindowPoints(NULL, hwnd, (POINT*)&rc, 2);
1672 pt.x = rc.left; pt.y = rc.top;
1674 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1675 ok(hr == S_OK, "Got 0x%08x\n", hr);
1679 hr = IShellItem_Compare(psi, psitestdir2, SICHINT_DISPLAY, &cmp);
1680 ok(hr == S_OK, "Got 0x%08x\n", hr);
1681 ok(!cmp, "Got cmp %d\n", cmp);
1682 IShellItem_Release(psi);
1686 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1687 ok(hr == S_OK, "Got 0x%08x\n", hr);
1689 /* GetItemCustomState / SetItemCustomState */
1692 /* Crashes under Windows 7 */
1693 INameSpaceTreeControl_GetItemCustomState(pnstc, NULL, NULL);
1694 INameSpaceTreeControl_GetItemCustomState(pnstc, NULL, &cbstate);
1695 INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, NULL);
1696 INameSpaceTreeControl_SetItemCustomState(pnstc, NULL, 0);
1699 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir,
1700 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,
1703 ok(hr == S_OK, "Got 0x%08x\n", hr);
1708 hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, &cbstate);
1709 ok(hr == S_OK, "Got 0x%08x\n", hr);
1710 ok(cbstate == BST_UNCHECKED || broken(cbstate == BST_CHECKED /* Vista x64 */),
1711 "Got %d\n", cbstate);
1713 hr = INameSpaceTreeControl_SetItemCustomState(pnstc, psitestdir, BST_CHECKED);
1714 ok(hr == S_OK, "Got 0x%08x\n", hr);
1717 hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, &cbstate);
1718 ok(hr == S_OK, "Got 0x%08x\n", hr);
1719 ok(cbstate == BST_CHECKED, "Got %d\n", cbstate);
1721 hr = INameSpaceTreeControl_SetItemCustomState(pnstc, psitestdir, 0xFFF);
1722 ok(hr == S_OK, "Got 0x%08x\n", hr);
1725 hr = INameSpaceTreeControl_GetItemCustomState(pnstc, psitestdir, &cbstate);
1726 ok(hr == S_OK, "Got 0x%08x\n", hr);
1727 ok(cbstate == 0xF, "Got %d\n", cbstate);
1733 hr = INameSpaceTreeControl_SetTheme(pnstc, NULL);
1734 ok(hr == S_OK, "Got 0x%08x\n", hr);
1735 hr = INameSpaceTreeControl_SetTheme(pnstc, explorerW);
1736 ok(hr == S_OK, "Got 0x%08x\n", hr);
1737 hr = INameSpaceTreeControl_SetTheme(pnstc, randomW);
1738 ok(hr == S_OK, "Got 0x%08x\n", hr);
1741 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1742 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1744 IShellItem_Release(psidesktop);
1745 IShellItem_Release(psidesktop2);
1746 IShellItem_Release(psitestdir);
1747 IShellItem_Release(psitestdir2);
1748 IShellItem_Release(psitest1);
1750 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
1751 ok(hr == S_OK, "Got 0x%08x\n", hr);
1755 hr = IOleWindow_GetWindow(pow, &hwnd_nstc);
1756 ok(hr == S_OK, "Got 0x%08x\n", hr);
1757 DestroyWindow(hwnd_nstc);
1758 IOleWindow_Release(pow);
1761 res = INameSpaceTreeControl_Release(pnstc);
1762 ok(!res, "res was %d!\n", res);
1768 static void test_events(void)
1770 INameSpaceTreeControl *pnstc;
1771 INameSpaceTreeControlEventsImpl *pnstceimpl, *pnstceimpl2;
1772 INameSpaceTreeControlEvents *pnstce, *pnstce2;
1773 IShellFolder *psfdesktop;
1774 IShellItem *psidesktop;
1776 LPITEMIDLIST pidl_desktop;
1777 LPITEMIDLIST pidl_drives;
1778 NSTCITEMSTATE itemstate;
1780 DWORD cookie1, cookie2;
1785 hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
1786 &IID_INameSpaceTreeControl, (void**)&pnstc);
1787 ok(hr == S_OK, "Failed to initialize control (0x%08x)\n", hr);
1789 ok(pSHCreateShellItem != NULL, "No SHCreateShellItem.\n");
1790 ok(pSHGetIDListFromObject != NULL, "No SHCreateShellItem.\n");
1792 SHGetDesktopFolder(&psfdesktop);
1793 hr = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl_desktop);
1794 IShellFolder_Release(psfdesktop);
1795 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1796 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop);
1797 ok(hr == S_OK, "Got 0x%08x\n", hr);
1798 ILFree(pidl_desktop);
1800 /* Create two instances of INameSpaceTreeControlEvents */
1801 pnstceimpl = create_nstc_events();
1802 pnstce = &pnstceimpl->INameSpaceTreeControlEvents_iface;
1803 ZeroMemory(&pnstceimpl->count, sizeof(UINT)*LastEvent);
1804 pnstceimpl2 = create_nstc_events();
1805 pnstce2 = &pnstceimpl2->INameSpaceTreeControlEvents_iface;
1809 /* Crashes native */
1810 INameSpaceTreeControl_TreeAdvise(pnstc, NULL, NULL);
1811 INameSpaceTreeControl_TreeAdvise(pnstc, NULL, &cookie1);
1812 INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, NULL);
1815 /* TreeAdvise in NameSpaceTreeController seems to support only one
1816 * client at the time.
1819 /* First, respond with E_NOINTERFACE to all QI's */
1820 pnstceimpl->qi_enable_events = FALSE;
1821 pnstceimpl->qi_called_count = 0;
1822 cookie1 = 0xDEADBEEF;
1823 hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie1);
1824 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
1825 ok(cookie1 == 0, "cookie now (0x%08x)\n", cookie1);
1828 ok(pnstceimpl->qi_called_count == 7 || pnstceimpl->qi_called_count == 4 /* Vista */,
1829 "QueryInterface called %d times.\n",
1830 pnstceimpl->qi_called_count);
1832 ok(pnstceimpl->ref == 1, "refcount was %d\n", pnstceimpl->ref);
1834 /* Accept query for IID_INameSpaceTreeControlEvents */
1835 pnstceimpl->qi_enable_events = TRUE;
1836 pnstceimpl->qi_called_count = 0;
1837 cookie1 = 0xDEADBEEF;
1838 hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie1);
1839 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1840 ok(cookie1 == 1, "cookie now (0x%08x)\n", cookie1);
1843 ok(pnstceimpl->qi_called_count == 7 || pnstceimpl->qi_called_count == 4 /* Vista */,
1844 "QueryInterface called %d times.\n",
1845 pnstceimpl->qi_called_count);
1847 ok(pnstceimpl->ref == 2, "refcount was %d\n", pnstceimpl->ref);
1849 /* A second time, query interface will not be called at all. */
1850 pnstceimpl->qi_enable_events = TRUE;
1851 pnstceimpl->qi_called_count = 0;
1852 cookie2 = 0xDEADBEEF;
1853 hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie2);
1854 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
1855 ok(cookie2 == 0, "cookie now (0x%08x)\n", cookie2);
1856 ok(!pnstceimpl->qi_called_count, "QueryInterface called %d times.\n",
1857 pnstceimpl->qi_called_count);
1858 ok(pnstceimpl->ref == 2, "refcount was %d\n", pnstceimpl->ref);
1860 /* Using another "instance" does not help. */
1861 pnstceimpl2->qi_enable_events = TRUE;
1862 pnstceimpl2->qi_called_count = 0;
1863 cookie2 = 0xDEADBEEF;
1864 hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce2, &cookie2);
1865 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
1866 ok(cookie2 == 0, "cookie now (0x%08x)\n", cookie2);
1867 ok(!pnstceimpl2->qi_called_count, "QueryInterface called %d times.\n",
1868 pnstceimpl2->qi_called_count);
1869 ok(pnstceimpl2->ref == 1, "refcount was %d\n", pnstceimpl->ref);
1871 /* Unadvise with bogus cookie (will actually unadvise properly) */
1872 pnstceimpl->qi_enable_events = TRUE;
1873 pnstceimpl->qi_called_count = 0;
1874 hr = INameSpaceTreeControl_TreeUnadvise(pnstc, 1234);
1875 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1876 ok(!pnstceimpl->qi_called_count, "QueryInterface called %d times.\n",
1877 pnstceimpl->qi_called_count);
1878 ok(pnstceimpl->ref == 1, "refcount was %d\n", pnstceimpl->ref);
1880 /* Unadvise "properly" (will have no additional effect) */
1881 pnstceimpl->qi_enable_events = TRUE;
1882 pnstceimpl->qi_called_count = 0;
1883 hr = INameSpaceTreeControl_TreeUnadvise(pnstc, cookie1);
1884 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1885 ok(!pnstceimpl->qi_called_count, "QueryInterface called %d times.\n",
1886 pnstceimpl->qi_called_count);
1887 ok(pnstceimpl->ref == 1, "refcount was %d\n", pnstceimpl->ref);
1889 /* Advise again.. */
1890 pnstceimpl->qi_enable_events = 1;
1891 pnstceimpl->qi_called_count = 0;
1892 hr = INameSpaceTreeControl_TreeAdvise(pnstc, (IUnknown*)pnstce, &cookie2);
1893 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1894 ok(cookie2 == 1, "Cookie is %d\n", cookie2);
1895 ok(cookie1 == cookie2, "Old cookie differs from old cookie.\n");
1898 ok(pnstceimpl->qi_called_count == 7 || pnstceimpl->qi_called_count == 4 /* Vista */,
1899 "QueryInterface called %d times.\n",
1900 pnstceimpl->qi_called_count);
1902 ok(pnstceimpl->ref == 2, "refcount was %d\n", pnstceimpl->ref);
1904 /* Initialize the control */
1905 hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, NULL, 0);
1906 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1907 ok_no_events(pnstceimpl);
1909 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop,
1910 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
1911 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1913 ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
1914 ok_event_count(pnstceimpl, OnGetDefaultIconIndex, 0);
1915 ok_no_events(pnstceimpl);
1917 hwnd_tv = get_treeview_hwnd(pnstc);
1918 ok(hwnd_tv != NULL, "Failed to get hwnd_tv HWND.\n");
1921 HTREEITEM hroot, hitem;
1923 static const UINT kbd_msgs_event[] = {
1924 WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
1926 static const UINT kbd_msgs_noevent[] ={
1927 WM_DEADCHAR, WM_SYSDEADCHAR, WM_UNICHAR, 0 };
1929 /* Test On*Expand */
1930 hroot = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_ROOT, 0);
1931 SendMessage(hwnd_tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)hroot);
1933 ok_event_count(pnstceimpl, OnBeforeExpand, 1);
1934 ok_event_count(pnstceimpl, OnAfterExpand, 1);
1935 ok_event_broken(pnstceimpl, OnItemAdded); /* No event on Vista */
1936 todo_wine ok_event_count(pnstceimpl, OnSelectionChanged, 1);
1937 ok_no_events(pnstceimpl);
1938 SendMessage(hwnd_tv, TVM_EXPAND, TVE_COLLAPSE, (LPARAM)hroot);
1940 ok_no_events(pnstceimpl);
1941 SendMessage(hwnd_tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)hroot);
1943 ok_no_events(pnstceimpl);
1945 /* Test OnSelectionChanged */
1946 hitem = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_CHILD, (LPARAM)hroot);
1947 SendMessageW(hwnd_tv, TVM_SELECTITEM, TVGN_CARET, (LPARAM)hitem);
1949 ok_event_count(pnstceimpl, OnSelectionChanged, 1);
1950 ok_no_events(pnstceimpl);
1952 /* Test OnKeyboardInput */
1953 for(i = 0; kbd_msgs_event[i] != 0; i++)
1955 SendMessageW(hwnd_tv, kbd_msgs_event[i], 0x1234, 0x1234);
1956 ok(pnstceimpl->count[OnKeyboardInput] == 1,
1957 "%d (%x): Got count %d\n",
1958 kbd_msgs_event[i], kbd_msgs_event[i], pnstceimpl->count[OnKeyboardInput]);
1959 pnstceimpl->count[OnKeyboardInput] = 0;
1962 for(i = 0; kbd_msgs_noevent[i] != 0; i++)
1964 SendMessageW(hwnd_tv, kbd_msgs_noevent[i], 0x1234, 0x1234);
1965 ok(pnstceimpl->count[OnKeyboardInput] == 0,
1966 "%d (%x): Got count %d\n",
1967 kbd_msgs_noevent[i], kbd_msgs_noevent[i], pnstceimpl->count[OnKeyboardInput]);
1968 pnstceimpl->count[OnKeyboardInput] = 0;
1970 ok_no_events(pnstceimpl);
1973 skip("Skipping some tests.\n");
1975 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1977 ok(hr == S_OK, "Got 0x%08x\n", hr);
1978 ok_event(pnstceimpl, OnItemDeleted);
1979 ok_no_events(pnstceimpl);
1981 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop,
1982 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
1983 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1985 ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
1986 ok_no_events(pnstceimpl);
1988 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
1989 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1990 ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
1992 ok_no_events(pnstceimpl);
1994 /* Expand the root */
1995 itemstate |= NSTCIS_EXPANDED;
1996 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, itemstate);
1997 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1999 ok_event_count(pnstceimpl, OnBeforeExpand, 1);
2000 ok_event_broken(pnstceimpl, OnItemAdded); /* Does not fire on Vista */
2001 ok_event_count(pnstceimpl, OnAfterExpand, 1);
2004 ok_event_count_broken(pnstceimpl, OnSelectionChanged, 1, 0 /* Vista*/);
2006 ok_no_events(pnstceimpl);
2008 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2009 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2010 ok(itemstate & NSTCIS_EXPANDED, "Item not expanded.\n");
2013 ok(itemstate == (NSTCIS_SELECTED | NSTCIS_EXPANDED)||
2014 broken(itemstate == NSTCIS_EXPANDED) /* Vista */,
2015 "itemstate is 0x%08x\n", itemstate);
2017 ok_event_count_broken(pnstceimpl, OnSelectionChanged, 1, 0 /* Vista*/);
2019 ok_no_events(pnstceimpl);
2021 /* Deselect the root */
2022 itemstate &= ~NSTCIS_SELECTED;
2023 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, itemstate);
2024 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2026 ok_no_events(pnstceimpl);
2028 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2029 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2030 ok(itemstate == (NSTCIS_EXPANDED), "itemstate is 0x%08x\n", itemstate);
2031 ok_no_events(pnstceimpl);
2033 hr = INameSpaceTreeControl_CollapseAll(pnstc);
2034 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2035 ok_no_events(pnstceimpl);
2037 /* Delete all roots */
2038 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
2039 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2040 ok_event_count(pnstceimpl, OnItemDeleted, 1);
2041 ok_no_events(pnstceimpl);
2043 /* Get/SetItemState */
2046 /* Crashes on Windows 7 */
2047 INameSpaceTreeControl_SetItemState(pnstc, NULL, 0, 0);
2048 INameSpaceTreeControl_GetItemState(pnstc, NULL, 0, NULL);
2049 INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0, NULL);
2050 INameSpaceTreeControl_GetItemState(pnstc, NULL, 0, &itemstate);
2051 INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0, NULL);
2052 INameSpaceTreeControl_GetItemState(pnstc, NULL, 0, &itemstate);
2055 itemstate = 0xDEADBEEF;
2056 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2057 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
2058 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
2059 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
2060 ok_no_events(pnstceimpl);
2062 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop,
2063 SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
2064 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2066 ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
2067 ok_no_events(pnstceimpl);
2069 itemstate = 0xDEADBEEF;
2070 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2071 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2072 ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
2073 ok_no_events(pnstceimpl);
2075 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0, 0xffff);
2076 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2080 ok_event_count(pnstceimpl, OnBeforeExpand, 0);
2081 ok_event_count(pnstceimpl, OnAfterExpand, 0);
2082 ok_event_count(pnstceimpl, OnItemAdded, 0);
2084 ok_no_events(pnstceimpl);
2086 itemstate = 0xDEADBEEF;
2087 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2088 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2090 ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
2091 ok_no_events(pnstceimpl);
2093 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
2094 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2096 ok_no_events(pnstceimpl);
2098 itemstate = 0xDEADBEEF;
2099 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2100 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2101 ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
2102 ok_no_events(pnstceimpl);
2104 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, NSTCIS_SELECTED);
2105 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2107 ok_event_count(pnstceimpl, OnSelectionChanged, 1);
2108 ok_no_events(pnstceimpl);
2110 itemstate = 0xDEADBEEF;
2111 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2112 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2113 ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
2114 ok_no_events(pnstceimpl);
2116 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_EXPANDED, NSTCIS_SELECTED);
2117 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2119 ok_no_events(pnstceimpl);
2121 itemstate = 0xDEADBEEF;
2122 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2123 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2124 ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
2125 ok_no_events(pnstceimpl);
2127 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
2128 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2130 ok_no_events(pnstceimpl);
2132 itemstate = 0xDEADBEEF;
2133 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2134 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2135 ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
2136 ok_no_events(pnstceimpl);
2138 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, NSTCIS_SELECTEDNOEXPAND);
2139 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2141 ok_no_events(pnstceimpl);
2143 itemstate = 0xDEADBEEF;
2144 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2145 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2146 ok(itemstate == NSTCIS_SELECTED, "itemstate is 0x%08x\n", itemstate);
2147 ok_no_events(pnstceimpl);
2149 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, NSTCIS_EXPANDED);
2150 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2154 ok_event_count(pnstceimpl, OnBeforeExpand, 1);
2155 ok_event_broken(pnstceimpl, OnItemAdded); /* Does not fire on Vista */
2156 ok_event_count(pnstceimpl, OnAfterExpand, 1);
2158 ok_no_events(pnstceimpl);
2160 itemstate = 0xDEADBEEF;
2161 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2162 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2163 ok(itemstate == NSTCIS_EXPANDED, "itemstate is 0x%08x\n", itemstate);
2164 ok_no_events(pnstceimpl);
2166 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0);
2167 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2169 ok_no_events(pnstceimpl);
2171 itemstate = 0xDEADBEEF;
2172 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2173 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2174 ok(itemstate == NSTCIS_NONE, "itemstate is 0x%08x\n", itemstate);
2175 ok_no_events(pnstceimpl);
2177 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff, 0xffff);
2178 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2180 ok_no_events(pnstceimpl);
2182 itemstate = 0xDEADBEEF;
2183 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2184 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2187 ok(itemstate == (NSTCIS_EXPANDED | NSTCIS_BOLD | NSTCIS_DISABLED),
2188 "itemstate is 0x%08x\n", itemstate);
2190 ok_no_events(pnstceimpl);
2192 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_SELECTED, NSTCIS_SELECTED);
2193 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2195 ok_no_events(pnstceimpl);
2197 itemstate = 0xDEADBEEF;
2198 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2199 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2202 ok(itemstate == (NSTCIS_EXPANDED | NSTCIS_BOLD | NSTCIS_DISABLED),
2203 "itemstate is 0x%08x\n", itemstate);
2205 ok_no_events(pnstceimpl);
2207 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
2208 NSTCIS_SELECTED | NSTCIS_DISABLED, NSTCIS_SELECTED);
2209 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2211 ok_no_events(pnstceimpl);
2213 itemstate = 0xDEADBEEF;
2214 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2215 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2216 ok(itemstate == (NSTCIS_BOLD | NSTCIS_EXPANDED),
2217 "itemstate is 0x%08x\n", itemstate);
2218 ok_no_events(pnstceimpl);
2220 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_SELECTED, NSTCIS_SELECTED);
2221 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2223 ok_no_events(pnstceimpl);
2225 itemstate = 0xDEADBEEF;
2226 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2227 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2228 ok(itemstate == (NSTCIS_BOLD | NSTCIS_EXPANDED),
2229 "itemstate is 0x%08x\n", itemstate);
2230 ok_no_events(pnstceimpl);
2232 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, 0xffff & ~NSTCIS_DISABLED, 0);
2233 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2235 ok_no_events(pnstceimpl);
2237 itemstate = 0xDEADBEEF;
2238 hr = INameSpaceTreeControl_GetItemState(pnstc, psidesktop, 0xffff, &itemstate);
2239 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2240 ok(itemstate == (NSTCIS_BOLD), "itemstate is 0x%08x\n", itemstate);
2241 ok_no_events(pnstceimpl);
2243 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
2244 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2245 ok_event_count(pnstceimpl, OnItemDeleted, 1);
2246 ok_no_events(pnstceimpl);
2249 hr = INameSpaceTreeControl_GetNextItem(pnstc, NULL, 0, NULL);
2250 ok(hr == E_POINTER, "Got (0x%08x)\n", hr);
2251 ok_no_events(pnstceimpl);
2253 hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, 0, NULL);
2254 ok(hr == E_POINTER, "Got (0x%08x)\n", hr);
2255 ok_no_events(pnstceimpl);
2257 hr = INameSpaceTreeControl_GetNextItem(pnstc, NULL, 0, &psi);
2258 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
2259 ok_no_events(pnstceimpl);
2261 hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, 0, &psi);
2262 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
2263 ok_no_events(pnstceimpl);
2265 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
2266 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2268 ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
2269 ok_no_events(pnstceimpl);
2271 /* Get child from unexpanded and unfilled parent */
2272 psi = (void*)0xDEADBEEF;
2273 hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, NSTCGNI_CHILD, &psi);
2274 ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
2275 ok(psi == NULL, "psi is %p\n", psi);
2277 ok_no_events(pnstceimpl);
2279 /* Expand and try again */
2280 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop, NSTCIS_EXPANDED, 0xffff);
2281 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2283 ok_event_count(pnstceimpl, OnBeforeExpand, 1);
2284 ok_event_broken(pnstceimpl, OnItemAdded); /* Does not fire on Vista */
2285 ok_event_count(pnstceimpl, OnAfterExpand, 1);
2286 todo_wine ok_event_count_broken(pnstceimpl, OnSelectionChanged, 1, 0 /*Vista */);
2287 ok_no_events(pnstceimpl);
2288 psi = (void*)0xDEADBEEF;
2289 hr = INameSpaceTreeControl_GetNextItem(pnstc, psidesktop, NSTCGNI_CHILD, &psi);
2290 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2291 ok((psi != NULL) && (psi != (void*)0xDEADBEEF), "psi is %p\n", psi);
2293 ok_no_events(pnstceimpl);
2294 if(SUCCEEDED(hr)) IShellItem_Release(psi);
2296 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
2297 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2298 ok_event_count(pnstceimpl, OnItemDeleted, 1);
2299 ok_no_events(pnstceimpl);
2301 /* EnsureItemVisible */
2304 /* Crashes on Windows 7 */
2305 INameSpaceTreeControl_EnsureItemVisible(pnstc, NULL);
2308 hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psidesktop);
2309 ok(hr == E_INVALIDARG || hr == E_FAIL, "Got (0x%08x)\n", hr);
2310 ok_no_events(pnstceimpl);
2312 hr = pSHGetSpecialFolderLocation(NULL, CSIDL_DRIVES, &pidl_drives);
2313 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2316 hr = pSHCreateShellItem(NULL, NULL, pidl_drives, &psi);
2317 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2320 hr = INameSpaceTreeControl_AppendRoot(pnstc, psi, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
2321 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2323 ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
2324 ok_no_events(pnstceimpl);
2326 hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psidesktop);
2327 ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
2328 ok_no_events(pnstceimpl);
2330 hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psi);
2331 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2332 ok_no_events(pnstceimpl);
2334 hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
2335 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2337 ok_event_count_broken(pnstceimpl, OnItemAdded, 1, 0 /* Vista */);
2338 ok_no_events(pnstceimpl);
2340 hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psidesktop);
2341 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2342 ok_no_events(pnstceimpl);
2344 hr = INameSpaceTreeControl_EnsureItemVisible(pnstc, psi);
2345 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2346 ok_no_events(pnstceimpl);
2350 skip("Failed to create shellitem.\n");
2352 ILFree(pidl_drives);
2355 skip("Failed to get pidl for CSIDL_DRIVES.\n");
2357 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
2358 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2359 ok_event_count(pnstceimpl, OnItemDeleted, 2);
2360 ok_no_events(pnstceimpl);
2362 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
2363 ok(hr == S_OK, "Got 0x%08x\n", hr);
2367 hr = IOleWindow_GetWindow(pow, &hwnd_nstc);
2368 ok(hr == S_OK, "Got 0x%08x\n", hr);
2369 DestroyWindow(hwnd_nstc);
2370 IOleWindow_Release(pow);
2373 hr = INameSpaceTreeControl_TreeUnadvise(pnstc, cookie2);
2374 ok(hr == S_OK, "Got 0x%08x\n", hr);
2376 res = INameSpaceTreeControl_Release(pnstc);
2377 ok(!res, "res was %d!\n", res);
2381 /* Freeing these prematurely causes a crash. */
2382 HeapFree(GetProcessHeap(), 0, pnstceimpl);
2383 HeapFree(GetProcessHeap(), 0, pnstceimpl2);
2386 IShellItem_Release(psi);
2387 IShellItem_Release(psidesktop);
2390 static void setup_window(void)
2393 static const char nstctest_wnd_name[] = "nstctest_wnd";
2395 ZeroMemory(&wc, sizeof(WNDCLASSA));
2396 wc.lpfnWndProc = DefWindowProcA;
2397 wc.lpszClassName = nstctest_wnd_name;
2398 RegisterClassA(&wc);
2399 hwnd = CreateWindowA(nstctest_wnd_name, NULL, WS_TABSTOP,
2400 0, 0, 200, 200, NULL, 0, 0, NULL);
2401 ok(hwnd != NULL, "Failed to create window for test (lasterror: %d).\n",
2405 static void destroy_window(void)
2407 DestroyWindow(hwnd);
2412 OleInitialize(NULL);
2414 init_function_pointers();
2415 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2417 if(test_initialization())
2424 win_skip("No NamespaceTreeControl (or instantiation failed).\n");