comctl32: Store style bits provided with WM_CREATE.
[wine/multimedia.git] / dlls / explorerframe / tests / nstc.c
blob3ea408fd1f82108e1011e0e7510e789eb888599b
1 /*
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
21 #include <stdio.h>
23 #define COBJMACROS
24 #define CONST_VTABLE
26 #include "shlobj.h"
27 #include "wine/test.h"
29 #include "msg.h"
31 static HWND hwnd;
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;
48 static int tvi_count;
50 static void init_function_pointers(void)
52 HMODULE hmod;
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,
68 LastEvent };
70 typedef struct {
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. */
75 LONG ref;
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,
85 REFIID riid,
86 void **ppvObject)
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);
95 *ppvObject = iface;
96 return S_OK;
99 return E_NOINTERFACE;
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,
120 IShellItem *psi,
121 NSTCEHITTEST nstceHitTest,
122 NSTCECLICKTYPE nstceClickType)
124 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
126 ok(psi != NULL, "NULL IShellItem\n");
127 This->count[OnItemClick]++;
128 return E_NOTIMPL;
131 static HRESULT WINAPI NSTCEvents_fnOnPropertyItemCommit(
132 INameSpaceTreeControlEvents* iface,
133 IShellItem *psi)
135 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
137 ok(psi != NULL, "NULL IShellItem\n");
138 This->count[OnPropertyItemCommit]++;
139 return E_NOTIMPL;
142 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanging(
143 INameSpaceTreeControlEvents* iface,
144 IShellItem *psi,
145 NSTCITEMSTATE nstcisMask,
146 NSTCITEMSTATE nstcisState)
148 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
150 ok(psi != NULL, "NULL IShellItem\n");
151 This->count[OnItemStateChanging]++;
152 return E_NOTIMPL;
155 static HRESULT WINAPI NSTCEvents_fnOnItemStateChanged(
156 INameSpaceTreeControlEvents* iface,
157 IShellItem *psi,
158 NSTCITEMSTATE nstcisMask,
159 NSTCITEMSTATE nstcisState)
161 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
163 ok(psi != NULL, "NULL IShellItem\n");
164 This->count[OnItemStateChanged]++;
165 return E_NOTIMPL;
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");
175 if(psiaSelection)
177 HRESULT hr;
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]++;
184 return E_NOTIMPL;
187 static HRESULT WINAPI NSTCEvents_fnOnKeyboardInput(
188 INameSpaceTreeControlEvents* iface,
189 UINT uMsg,
190 WPARAM wParam,
191 LPARAM lParam)
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);
198 return E_NOTIMPL;
201 static HRESULT WINAPI NSTCEvents_fnOnBeforeExpand(
202 INameSpaceTreeControlEvents* iface,
203 IShellItem *psi)
205 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
207 ok(psi != NULL, "NULL IShellItem\n");
208 This->count[OnBeforeExpand]++;
209 return E_NOTIMPL;
212 static HRESULT WINAPI NSTCEvents_fnOnAfterExpand(
213 INameSpaceTreeControlEvents* iface,
214 IShellItem *psi)
216 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
218 ok(psi != NULL, "NULL IShellItem\n");
219 This->count[OnAfterExpand]++;
220 return E_NOTIMPL;
223 static HRESULT WINAPI NSTCEvents_fnOnBeginLabelEdit(
224 INameSpaceTreeControlEvents* iface,
225 IShellItem *psi)
227 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
229 ok(psi != NULL, "NULL IShellItem\n");
230 This->count[OnBeginLabelEdit]++;
231 return E_NOTIMPL;
234 static HRESULT WINAPI NSTCEvents_fnOnEndLabelEdit(
235 INameSpaceTreeControlEvents* iface,
236 IShellItem *psi)
238 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
240 ok(psi != NULL, "NULL IShellItem\n");
241 This->count[OnEndLabelEdit]++;
242 return E_NOTIMPL;
245 static HRESULT WINAPI NSTCEvents_fnOnGetToolTip(
246 INameSpaceTreeControlEvents* iface,
247 IShellItem *psi,
248 LPWSTR pszTip,
249 int cchTip)
251 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
253 ok(psi != NULL, "NULL IShellItem\n");
254 This->count[OnGetToolTip]++;
255 return E_NOTIMPL;
258 static HRESULT WINAPI NSTCEvents_fnOnBeforeItemDelete(
259 INameSpaceTreeControlEvents* iface,
260 IShellItem *psi)
262 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
264 ok(psi != NULL, "NULL IShellItem\n");
265 This->count[OnBeforeItemDelete]++;
266 return E_NOTIMPL;
269 static HRESULT WINAPI NSTCEvents_fnOnItemAdded(
270 INameSpaceTreeControlEvents* iface,
271 IShellItem *psi,
272 BOOL fIsRoot)
274 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
276 ok(psi != NULL, "NULL IShellItem\n");
277 This->count[OnItemAdded]++;
278 return S_OK;
281 static HRESULT WINAPI NSTCEvents_fnOnItemDeleted(
282 INameSpaceTreeControlEvents* iface,
283 IShellItem *psi,
284 BOOL fIsRoot)
286 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
288 ok(psi != NULL, "NULL IShellItem\n");
289 This->count[OnItemDeleted]++;
290 return S_OK;
293 static HRESULT WINAPI NSTCEvents_fnOnBeforeContextMenu(
294 INameSpaceTreeControlEvents* iface,
295 IShellItem *psi,
296 REFIID riid,
297 void **ppv)
299 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
301 This->count[OnBeforeContextMenu]++;
302 return E_NOTIMPL;
305 static HRESULT WINAPI NSTCEvents_fnOnAfterContextMenu(
306 INameSpaceTreeControlEvents* iface,
307 IShellItem *psi,
308 IContextMenu *pcmIn,
309 REFIID riid,
310 void **ppv)
312 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
314 This->count[OnAfterContextMenu]++;
315 return E_NOTIMPL;
318 static HRESULT WINAPI NSTCEvents_fnOnBeforeStateImageChange(
319 INameSpaceTreeControlEvents* iface,
320 IShellItem *psi)
322 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
324 ok(psi != NULL, "NULL IShellItem\n");
325 This->count[OnBeforeStateImageChange]++;
326 return E_NOTIMPL;
329 static HRESULT WINAPI NSTCEvents_fnOnGetDefaultIconIndex(
330 INameSpaceTreeControlEvents* iface,
331 IShellItem *psi,
332 int *piDefaultIcon,
333 int *piOpenIcon)
335 INameSpaceTreeControlEventsImpl *This = impl_from_INameSpaceTreeControlEvents(iface);
337 ok(psi != NULL, "NULL IShellItem\n");
338 This->count[OnGetDefaultIconIndex]++;
339 return E_NOTIMPL;
342 static const INameSpaceTreeControlEventsVtbl vt_NSTCEvents = {
343 NSTCEvents_fnQueryInterface,
344 NSTCEvents_fnAddRef,
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;
371 This->ref = 1;
373 return This;
376 /*********************************************************************
377 * Event count checking
379 static void ok_no_events_(INameSpaceTreeControlEventsImpl *impl,
380 const char *file, int line)
382 UINT i;
383 for(i = 0; i < LastEvent; i++)
385 ok_(file, line)
386 (!impl->count[i], "Got event %d, count %d\n", i, impl->count[i]);
387 impl->count[i] = 0;
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; \
397 } while(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]), \
404 "No event.\n"); \
405 impl->count[event] = 0; \
406 } while(0)
408 #define ok_event(impl, event) \
409 do { ok(impl->count[event], "No event %d.\n", event); \
410 impl->count[event] = 0; \
411 } while(0)
413 /* Process some messages */
414 static void process_msgs(void)
416 MSG msg;
417 BOOL got_msg;
418 do {
419 got_msg = FALSE;
420 Sleep(100);
421 while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
423 TranslateMessage(&msg);
424 DispatchMessage(&msg);
425 got_msg = TRUE;
427 } while(got_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.) */
433 Sleep(500);
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)
446 HANDLE file;
447 DWORD written;
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);
454 CloseHandle(file);
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 )
482 size_t iLen;
484 if (!lpszPath || (iLen = lstrlenW(lpszPath)) >= MAX_PATH)
485 return NULL;
487 if (iLen)
489 lpszPath += iLen;
490 if (lpszPath[-1] != '\\')
492 *lpszPath++ = '\\';
493 *lpszPath = '\0';
496 return lpszPath;
499 static HWND get_treeview_hwnd(INameSpaceTreeControl *pnstc)
501 IOleWindow *pow;
502 HRESULT hr;
503 HWND treeview = NULL;
505 hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
506 ok(hr == S_OK, "Got 0x%08x\n", hr);
507 if(SUCCEEDED(hr))
509 HWND host;
510 hr = IOleWindow_GetWindow(pow, &host);
511 ok(hr == S_OK, "Got 0x%08x\n", hr);
512 if(SUCCEEDED(hr))
513 treeview = FindWindowExW(host, NULL, WC_TREEVIEWW, NULL);
514 IOleWindow_Release(pow);
517 return treeview;
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;
524 LRESULT ret;
525 struct message msg;
527 msg.message = message;
528 msg.flags = sent|wparam|lparam;
529 if (defwndproc_counter) msg.flags |= defwinproc;
530 msg.wParam = wParam;
531 msg.lParam = lParam;
532 msg.id = 0;
533 add_message(sequences, TREEVIEW_SEQ_INDEX, &msg);
535 if(message == TVM_SETITEMW)
537 memcpy(&last_tvi, (void*)lParam, sizeof(TVITEMEXW));
538 tvi_count++;
541 defwndproc_counter++;
542 ret = CallWindowProcW(oldproc, hwnd_tv, message, wParam, lParam);
543 defwndproc_counter--;
544 return ret;
547 static BOOL subclass_treeview(INameSpaceTreeControl *pnstc)
549 HWND hwnd_tv;
550 WNDPROC oldproc = NULL;
552 hwnd_tv = get_treeview_hwnd(pnstc);
553 if(hwnd_tv)
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");
561 return oldproc?TRUE:FALSE;
564 static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message)
566 struct msg_sequence *msg_seq = seq[sequence_index];
567 UINT i, count = 0;
569 for(i = 0; i < msg_seq->count ; i++)
570 if(msg_seq->sequence[i].message == message)
571 count++;
573 return count;
576 /* Returns FALSE if the NamespaceTreeControl failed to be instantiated. */
577 static BOOL test_initialization(void)
579 INameSpaceTreeControl *pnstc;
580 IOleWindow *pow;
581 IUnknown *punk;
582 HWND hwnd_host1;
583 LONG lres;
584 HRESULT hr;
585 RECT rc;
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);
590 if(FAILED(hr))
592 return FALSE;
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);
610 if(SUCCEEDED(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);
627 if(SUCCEEDED(hr))
629 static const CHAR namespacetree[] = "NamespaceTreeControl";
630 char buf[1024];
631 LONG style, expected_style;
632 HWND hwnd_tv;
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");
636 buf[0] = '\0';
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);
644 expected_style = 0;
645 style = GetWindowLongPtrW(hwnd_host1, GWL_EXSTYLE);
646 ok(style == expected_style, "Got style %08x\n", style);
648 expected_style = 0;
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");
654 if(hwnd_tv)
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);
662 expected_style = 0;
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);
675 if(0)
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);
682 if(SUCCEEDED(hr))
684 HWND hwnd_host2;
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);
724 return TRUE;
727 static void verify_root_order_(INameSpaceTreeControl *pnstc, IShellItem **roots,
728 const char *file, int line)
730 HRESULT hr;
731 IShellItemArray *psia;
733 hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
734 ok_(file,line) (hr == S_OK, "GetRootItems: got (0x%08x)\n", hr);
735 if(SUCCEEDED(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++)
746 IShellItem *psi;
747 hr = IShellItemArray_GetItemAt(psia, i, &psi);
748 ok_(file,line) (hr == S_OK, "GetItemAt %i: got 0x%08x\n", i, hr);
749 if(SUCCEEDED(hr))
751 int cmp;
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 IShellItem_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;
769 IShellItem *psi;
770 IShellItem *psidesktop, *psidesktop2;
771 IShellItem *psitestdir, *psitestdir2, *psitest1;
772 IOleWindow *pow;
773 LPITEMIDLIST pidl_desktop;
774 NSTCITEMSTATE istate;
775 HRESULT hr;
776 UINT i, res, height;
777 HWND hwnd_tv;
778 RECT rc;
779 IShellItem *roots[10];
780 POINT pt;
781 int cbstate;
782 WCHAR curdirW[MAX_PATH];
783 WCHAR buf[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);
802 if(SUCCEEDED(hr))
804 hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop);
805 ok(hr == S_OK, "Got 0x%08x\n", hr);
806 if(SUCCEEDED(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);
816 if(FAILED(hr))
818 win_skip("Test setup failed.\n");
819 return;
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);
860 process_msgs();
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);
871 if(SUCCEEDED(hr))
873 DWORD tmp;
874 NSTCSTYLE style;
875 NSTCSTYLE2 style2;
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);
886 if(hr == S_OK)
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);
917 tmp = 0;
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);
933 if(SUCCEEDED(hr))
935 DWORD tmp2;
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);
983 tmp = 0;
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);
994 if(SUCCEEDED(hr))
996 DWORD tmp2;
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);
1014 else
1016 /* 64-bit Windows Vista (others?) seems to have a somewhat
1017 * different idea of how the methods of this interface
1018 * should behave. */
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");
1035 style = 0xdeadbeef;
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);
1044 tmp = 0;
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];
1053 style = 0xdeadbeef;
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);
1058 tmp = 0;
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);
1075 else
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 */
1084 if(0)
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);
1098 process_msgs();
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);
1131 /* GetRootItems */
1132 if(0)
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;
1154 roots[4] = NULL;
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;
1165 roots[5] = NULL;
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;
1172 roots[6] = NULL;
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;
1182 roots[7] = NULL;
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;
1189 roots[8] = NULL;
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;
1204 roots[9] = NULL;
1205 verify_root_order(pnstc, roots);
1207 /* CollapseAll */
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");
1220 if(res)
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);
1229 /* A special case -
1230 * The first expansion results in an "unrelated" TVM_SETITEMW being sent
1231 * (mask == 0x50 (TVIF_CHILDREN|TVIF_HANDLE) )
1233 tvi_count = 0;
1234 hr = INameSpaceTreeControl_SetItemState(pnstc, psidesktop,
1235 NSTCIS_EXPANDED, NSTCIS_EXPANDED);
1236 ok(hr == S_OK, "Got 0x%08x\n", hr);
1237 todo_wine
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);
1243 tvi_count = 0;
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;
1256 TVITEMEXW tviexp;
1257 UINT msg_count;
1259 flush_sequences(sequences, NUM_MSG_SEQUENCES);
1260 tvi_count = 0;
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;
1283 else
1284 tviexp.mask = 0;
1286 if(tviexp.mask)
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;
1300 else
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);
1324 if(!tviexp.mask)
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);
1336 else
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 */
1360 if(0)
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);
1373 process_msgs();
1375 hr = INameSpaceTreeControl_AppendRoot(pnstc, psitestdir, SHCONTF_FOLDERS, 0, NULL);
1376 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1377 process_msgs();
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);
1385 if(SUCCEEDED(hr))
1387 UINT count;
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);
1391 if(count)
1393 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1394 ok(hr == S_OK, "Got 0x%08x\n", hr);
1395 if(SUCCEEDED(hr))
1397 int cmp;
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);
1409 process_msgs();
1411 hr = INameSpaceTreeControl_GetSelectedItems(pnstc, &psia);
1412 ok(hr == S_OK, "Got 0x%08x\n", hr);
1413 if(SUCCEEDED(hr))
1415 UINT count;
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);
1419 if(count)
1421 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1422 ok(hr == S_OK, "Got 0x%08x\n", hr);
1423 if(SUCCEEDED(hr))
1425 int cmp;
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);
1439 if(SUCCEEDED(hr))
1441 UINT count;
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);
1445 if(count)
1447 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1448 ok(hr == S_OK, "Got 0x%08x\n", hr);
1449 if(SUCCEEDED(hr))
1451 int cmp;
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);
1462 if(hr == E_FAIL)
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,
1473 0, NULL);
1474 ok(hr == S_OK, "Got 0x%08x\n", hr);
1475 process_msgs();
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);
1492 process_msgs();
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);
1499 if(SUCCEEDED(hr))
1501 IShellItem *psi;
1503 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1504 if(SUCCEEDED(hr))
1506 INT cmp;
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);
1521 process_msgs();
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);
1528 if(SUCCEEDED(hr))
1530 IShellItem *psi;
1532 hr = IShellItemArray_GetItemAt(psia, 0, &psi);
1533 if(SUCCEEDED(hr))
1535 INT cmp;
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);
1548 /* GetItemRect */
1549 rc.top = rc.left = rc.bottom = rc.right = 0;
1550 if(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);
1565 process_msgs();
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");
1572 height = 0;
1573 hwnd_tv = get_treeview_hwnd(pnstc);
1574 if(hwnd_tv)
1576 HTREEITEM hroot = (HTREEITEM)SendMessageW(hwnd_tv, TVM_GETNEXTITEM, TVGN_ROOT, 0);
1577 ok(hroot != NULL, "Failed to get root.\n");
1578 if(hroot)
1580 RECT tv_rc;
1581 BOOL bret;
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);
1600 else
1601 win_skip("Skipping some GetItemRect tests.\n");
1603 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1604 ok(hr == S_OK, "Got (0x%08x)\n", hr);
1606 /* HitTest */
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;
1615 pt.x = pt.y = 0;
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);
1624 process_msgs();
1626 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1627 ok(hr == S_OK, "Got 0x%08x\n", hr);
1628 if(SUCCEEDED(hr))
1630 int cmp;
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);
1637 pt.y += height - 1;
1638 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1639 ok(hr == S_OK, "Got 0x%08x\n", hr);
1640 if(SUCCEEDED(hr))
1642 int cmp;
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);
1649 pt.y += 1;
1650 hr = INameSpaceTreeControl_HitTest(pnstc, &pt, &psi);
1651 ok(hr == S_OK, "Got 0x%08x\n", hr);
1652 if(SUCCEEDED(hr))
1654 int cmp;
1655 todo_wine
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);
1669 if(SUCCEEDED(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);
1676 if(SUCCEEDED(hr))
1678 int cmp;
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 */
1690 if(0)
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,
1701 0, NULL);
1702 process_msgs();
1703 ok(hr == S_OK, "Got 0x%08x\n", hr);
1705 todo_wine
1707 cbstate = -1;
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);
1716 cbstate = -1;
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);
1724 cbstate = -1;
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);
1730 /* SetTheme */
1731 todo_wine
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);
1752 if(SUCCEEDED(hr))
1754 HWND hwnd_nstc;
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);
1764 cleanup:
1765 Cleanup();
1768 static void test_events(void)
1770 INameSpaceTreeControl *pnstc;
1771 INameSpaceTreeControlEventsImpl *pnstceimpl, *pnstceimpl2;
1772 INameSpaceTreeControlEvents *pnstce, *pnstce2;
1773 IShellFolder *psfdesktop;
1774 IShellItem *psidesktop;
1775 IOleWindow *pow;
1776 LPITEMIDLIST pidl_desktop;
1777 LPITEMIDLIST pidl_drives;
1778 NSTCITEMSTATE itemstate;
1779 IShellItem *psi;
1780 DWORD cookie1, cookie2;
1781 HWND hwnd_tv;
1782 HRESULT hr;
1783 UINT res;
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;
1807 if(0)
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);
1826 todo_wine
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);
1841 todo_wine
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");
1896 todo_wine
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);
1912 process_msgs();
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");
1919 if(hwnd_tv)
1921 HTREEITEM hroot, hitem;
1922 UINT i;
1923 static const UINT kbd_msgs_event[] = {
1924 WM_KEYDOWN, WM_KEYUP, WM_CHAR, WM_SYSKEYDOWN, WM_SYSKEYUP,
1925 WM_SYSCHAR, 0 };
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);
1932 process_msgs();
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);
1939 process_msgs();
1940 ok_no_events(pnstceimpl);
1941 SendMessage(hwnd_tv, TVM_EXPAND, TVE_EXPAND, (LPARAM)hroot);
1942 process_msgs();
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);
1948 process_msgs();
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);
1972 else
1973 skip("Skipping some tests.\n");
1975 hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
1976 process_msgs();
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);
1984 process_msgs();
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);
1991 process_msgs();
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);
1998 process_msgs();
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);
2002 todo_wine
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");
2011 todo_wine
2013 ok(itemstate == (NSTCIS_SELECTED | NSTCIS_EXPANDED)||
2014 broken(itemstate == NSTCIS_EXPANDED) /* Vista */,
2015 "itemstate is 0x%08x\n", itemstate);
2016 process_msgs();
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);
2025 process_msgs();
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 */
2044 if(0)
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);
2065 process_msgs();
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);
2077 process_msgs();
2078 todo_wine
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);
2089 todo_wine
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);
2095 process_msgs();
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);
2106 process_msgs();
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);
2118 process_msgs();
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);
2129 process_msgs();
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);
2140 process_msgs();
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);
2151 process_msgs();
2152 todo_wine
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);
2168 process_msgs();
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);
2179 process_msgs();
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);
2185 todo_wine
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);
2194 process_msgs();
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);
2200 todo_wine
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);
2210 process_msgs();
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);
2222 process_msgs();
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);
2234 process_msgs();
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);
2248 /* GetNextItem */
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);
2267 process_msgs();
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);
2276 process_msgs();
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);
2282 process_msgs();
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);
2292 process_msgs();
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 */
2302 if(0)
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);
2314 if(SUCCEEDED(hr))
2316 hr = pSHCreateShellItem(NULL, NULL, pidl_drives, &psi);
2317 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2318 if(SUCCEEDED(hr))
2320 hr = INameSpaceTreeControl_AppendRoot(pnstc, psi, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, 0, NULL);
2321 ok(hr == S_OK, "Got (0x%08x)\n", hr);
2322 process_msgs();
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);
2336 process_msgs();
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);
2349 else
2350 skip("Failed to create shellitem.\n");
2352 ILFree(pidl_drives);
2354 else
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);
2364 if(SUCCEEDED(hr))
2366 HWND hwnd_nstc;
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);
2379 if(!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)
2392 WNDCLASSA wc;
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",
2402 GetLastError());
2405 static void destroy_window(void)
2407 DestroyWindow(hwnd);
2410 START_TEST(nstc)
2412 OleInitialize(NULL);
2413 setup_window();
2414 init_function_pointers();
2415 init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
2417 if(test_initialization())
2419 test_basics();
2420 test_events();
2422 else
2424 win_skip("No NamespaceTreeControl (or instantiation failed).\n");
2427 destroy_window();
2428 OleUninitialize();