[PATCH 7/8] explorerframe/nstc: Add/remove roots.
David Hedberg
david.hedberg at gmail.com
Thu Jul 29 14:26:06 CDT 2010
---
dlls/explorerframe/nstc.c | 316 +++++++++++++++++++++++++++++++++++++--
dlls/explorerframe/tests/nstc.c | 160 ++++++++++++++++++++
2 files changed, 466 insertions(+), 10 deletions(-)
diff --git a/dlls/explorerframe/nstc.c b/dlls/explorerframe/nstc.c
index ca8595d..a6793b0 100644
--- a/dlls/explorerframe/nstc.c
+++ b/dlls/explorerframe/nstc.c
@@ -25,13 +25,25 @@
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
+#include "winuser.h"
+#include "shellapi.h"
+#include "wine/list.h"
#include "wine/debug.h"
#include "explorerframe_main.h"
WINE_DEFAULT_DEBUG_CHANNEL(nstc);
+typedef struct nstc_root {
+ IShellItem *psi;
+ HTREEITEM htreeitem;
+ SHCONTF enum_flags;
+ NSTCROOTSTYLE root_style;
+ IShellItemFilter *pif;
+ struct list entry;
+} nstc_root;
+
typedef struct {
const INameSpaceTreeControl2Vtbl *lpVtbl;
const IOleWindowVtbl *lpowVtbl;
@@ -42,6 +54,7 @@ typedef struct {
NSTCSTYLE style;
NSTCSTYLE2 style2;
+ struct list roots;
INameSpaceTreeControlEvents *pnstce;
} NSTC2Impl;
@@ -55,6 +68,34 @@ static const DWORD unsupported_styles2 =
NSTCS2_DISPLAYPINNEDONLY | NTSCS2_NOSINGLETONAUTOEXPAND | NTSCS2_NEVERINSERTNONENUMERATED;
/*************************************************************************
+* NamespaceTree Event Wrappers
+*/
+static HRESULT events_OnGetDefaultIconIndex(NSTC2Impl *This, IShellItem *psi,
+ int *piDefaultIcon, int *piOpenIcon)
+{
+ if(!This->pnstce)
+ return E_NOTIMPL;
+ return INameSpaceTreeControlEvents_OnGetDefaultIconIndex(
+ This->pnstce, psi, piDefaultIcon, piOpenIcon);
+}
+
+static HRESULT events_OnItemAdded(NSTC2Impl *This, IShellItem *psi, BOOL fIsRoot)
+{
+ if(!This->pnstce)
+ return S_OK;
+ return INameSpaceTreeControlEvents_OnItemAdded(
+ This->pnstce, psi, fIsRoot);
+}
+
+static HRESULT events_OnItemDeleted(NSTC2Impl *This, IShellItem *psi, BOOL fIsRoot)
+{
+ if(!This->pnstce)
+ return S_OK;
+ return INameSpaceTreeControlEvents_OnItemDeleted(
+ This->pnstce, psi, fIsRoot);
+}
+
+/*************************************************************************
* NamespaceTree helper functions
*/
static DWORD treeview_style_from_nstcs(NSTC2Impl *This, NSTCSTYLE nstcs,
@@ -102,6 +143,85 @@ static DWORD treeview_style_from_nstcs(NSTC2Impl *This, NSTCSTYLE nstcs,
return old_style^*new_style;
}
+static IShellItem *shellitem_from_treeitem(NSTC2Impl *This, HTREEITEM hitem)
+{
+ TVITEMEXW tvi;
+
+ tvi.mask = TVIF_PARAM;
+ tvi.lParam = (LPARAM)NULL;
+ tvi.hItem = hitem;
+
+ SendMessageW(This->hwnd_tv, TVM_GETITEMW, 0, (LPARAM)&tvi);
+
+ TRACE("ShellItem: %p\n", (void*)tvi.lParam);
+ return (IShellItem*)tvi.lParam;
+}
+
+/* From brsfolder.c */
+static int GetIcon(LPCITEMIDLIST lpi, UINT extra_flags)
+{
+ SHFILEINFOW sfi;
+ UINT flags = SHGFI_PIDL | SHGFI_SYSICONINDEX | SHGFI_SMALLICON;
+ SHGetFileInfoW((LPCWSTR)lpi, 0 ,&sfi, sizeof(SHFILEINFOW), flags | extra_flags);
+ return sfi.iIcon;
+}
+
+static HTREEITEM insert_shellitem(NSTC2Impl *This, IShellItem *psi,
+ HTREEITEM hParent, HTREEITEM hInsertAfter)
+{
+ TVINSERTSTRUCTW tvins;
+ TVITEMEXW tvi;
+ LPWSTR display_name;
+ HTREEITEM hinserted;
+ LPITEMIDLIST pidl;
+ TRACE("%p (%p, %p)\n", psi, hParent, hInsertAfter);
+
+ tvi.mask = TVIF_PARAM | TVIF_CHILDREN;
+ tvi.cChildren = I_CHILDRENCALLBACK;
+
+ if(SUCCEEDED(IShellItem_GetDisplayName(psi, SIGDN_NORMALDISPLAY, &display_name)))
+ {
+ tvi.mask |= TVIF_TEXT;
+ tvi.pszText = display_name;
+ }
+ else
+ ERR("Failed to get display name from ShellItem.\n");
+
+ if(SUCCEEDED(events_OnGetDefaultIconIndex(This, psi, &tvi.iImage, &tvi.iSelectedImage)))
+ {
+ /* icons provided by the client */
+ tvi.iExpandedImage = tvi.iSelectedImage;
+ }
+ else
+ {
+ if(SUCCEEDED(SHGetIDListFromObject((IUnknown*)psi, &pidl)))
+ {
+ tvi.mask |= TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_EXPANDEDIMAGE;
+ tvi.iImage = tvi.iSelectedImage = GetIcon(pidl, 0);
+ tvi.iExpandedImage = GetIcon(pidl,SHGFI_OPENICON);
+ ILFree(pidl);
+ }
+ else
+ ERR("Failed to get pidl from ShellItem.\n");
+ }
+
+ /* Add a pointer to the ShellItem */
+ tvi.lParam = (LPARAM)psi;
+ tvins.itemex = tvi;
+ tvins.hParent = hParent;
+ tvins.hInsertAfter = hInsertAfter;
+
+ /* Insert it. */
+ hinserted = (HTREEITEM)SendMessageW(This->hwnd_tv, TVM_INSERTITEMW,
+ 0, (LPARAM)(LPTVINSERTSTRUCTW)&tvins);
+
+ if(hinserted)
+ IShellItem_AddRef(psi);
+
+ CoTaskMemFree(display_name);
+ return hinserted;
+}
+
/*************************************************************************
* NamespaceTree Window Functions
*/
@@ -178,20 +298,64 @@ static LRESULT destroy_namespacetree(NSTC2Impl *This)
{
TRACE("%p\n", This);
+ INameSpaceTreeControl_RemoveAllRoots((INameSpaceTreeControl*)This);
INameSpaceTreeControl_Release((INameSpaceTreeControl*)This);
return TRUE;
}
+static LRESULT on_tvn_deleteitemw(NSTC2Impl *This, LPARAM lParam)
+{
+ NMTREEVIEWW *nmtv = (NMTREEVIEWW*)lParam;
+ TRACE("%p\n", This);
+
+ /* Release the associated shellitem */
+ IShellItem_Release((IShellItem*)nmtv->itemOld.lParam);
+ return TRUE;
+}
+
+static LRESULT on_tvn_getdispinfow(NSTC2Impl *This, LPARAM lParam)
+{
+ NMTVDISPINFOW *dispinfo = (NMTVDISPINFOW*)lParam;
+ HRESULT hr;
+
+ TRACE("%p, %p (mask: %x)\n", This, dispinfo, dispinfo->item.mask);
+
+ if(dispinfo->item.mask & TVIF_CHILDREN)
+ {
+ IShellItem *psi = shellitem_from_treeitem(This, dispinfo->item.hItem);
+ SFGAOF sfgao;
+
+ hr = IShellItem_GetAttributes(psi, SFGAO_HASSUBFOLDER, &sfgao);
+ if(FAILED(hr))
+ dispinfo->item.cChildren = 1;
+ else
+ dispinfo->item.cChildren = (sfgao & SFGAO_HASSUBFOLDER)?1:0;
+
+ dispinfo->item.mask |= TVIF_DI_SETITEM;
+ }
+ return FALSE;
+}
+
static LRESULT CALLBACK NSTC2_WndProc(HWND hWnd, UINT uMessage,
WPARAM wParam, LPARAM lParam)
{
NSTC2Impl *This = (NSTC2Impl*)GetWindowLongPtrW(hWnd, GWLP_USERDATA);
+ NMHDR *nmhdr;
switch(uMessage)
{
case WM_NCCREATE: return create_namespacetree(hWnd, (CREATESTRUCTW*)lParam);
case WM_SIZE: return resize_namespacetree(This);
case WM_DESTROY: return destroy_namespacetree(This);
+ case WM_NOTIFY:
+ nmhdr = (NMHDR*)lParam;
+ switch(nmhdr->code)
+ {
+ case TVN_DELETEITEMW: return on_tvn_deleteitemw(This, lParam);
+ case TVN_GETDISPINFOW: return on_tvn_getdispinfow(This, lParam);
+ default: break;
+ }
+ break;
default: return DefWindowProcW(hWnd, uMessage, wParam, lParam);
}
return 0;
@@ -371,9 +535,65 @@ static HRESULT WINAPI NSTC2_fnInsertRoot(INameSpaceTreeControl2* iface,
IShellItemFilter *pif)
{
NSTC2Impl *This = (NSTC2Impl*)iface;
- FIXME("stub, %p, %p, %x, %x, %p\n",
+ nstc_root *new_root;
+ struct list *add_after;
+ HTREEITEM hti_add_after;
+ UINT i;
+
+ TRACE("%p, %p, %x, %x, %p\n",
This, psiRoot, grfEnumFlags, grfRootStyle, pif);
- return E_NOTIMPL;
+
+ new_root = HeapAlloc(GetProcessHeap(), 0, sizeof(nstc_root));
+ if(!new_root)
+ return E_OUTOFMEMORY;
+
+ new_root->psi = psiRoot;
+ new_root->enum_flags = grfEnumFlags;
+ new_root->root_style = grfRootStyle;
+ new_root->pif = pif;
+
+ /* Find the right place in the list of roots. */
+ for(i = 0, add_after = &This->roots;
+ (add_after->next != &This->roots) && (i < iIndex);
+ add_after = add_after->next, i++) {}
+
+ /* Insert the root into the treeview */
+ if(add_after != &This->roots)
+ {
+ nstc_root *root_add_after = LIST_ENTRY(add_after, nstc_root, entry);
+ hti_add_after = root_add_after->htreeitem;
+ }
+ else
+ hti_add_after = TVI_FIRST;
+
+ new_root->htreeitem = insert_shellitem(This, psiRoot, TVI_ROOT,
+ hti_add_after);
+ if(!new_root->htreeitem)
+ {
+ ERR("Failed to add the root.\n");
+ HeapFree(GetProcessHeap(), 0, new_root);
+ return E_FAIL;
+ }
+
+ list_add_after(add_after, &new_root->entry);
+ events_OnItemAdded(This, psiRoot, TRUE);
+
+ if(grfRootStyle & NSTCRS_HIDDEN)
+ {
+ TVITEMEXW tvi;
+ tvi.mask = TVIF_STATEEX;
+ tvi.uStateEx = TVIS_EX_FLAT;
+ tvi.hItem = new_root->htreeitem;
+
+ SendMessageW(This->hwnd_tv, TVM_SETITEMW, 0, (LPARAM)&tvi);
+ }
+
+ if(grfRootStyle & NSTCRS_EXPANDED)
+ SendMessageW(This->hwnd_tv, TVM_EXPAND, TVE_EXPAND,
+ (LPARAM)new_root->htreeitem);
+
+
+ return S_OK;
}
static HRESULT WINAPI NSTC2_fnAppendRoot(INameSpaceTreeControl2* iface,
@@ -383,32 +603,106 @@ static HRESULT WINAPI NSTC2_fnAppendRoot(INameSpaceTreeControl2* iface,
IShellItemFilter *pif)
{
NSTC2Impl *This = (NSTC2Impl*)iface;
- FIXME("stub, %p, %p, %x, %x, %p\n",
+ UINT root_count;
+ TRACE("%p, %p, %x, %x, %p\n",
This, psiRoot, grfEnumFlags, grfRootStyle, pif);
- return E_NOTIMPL;
+
+ root_count = list_count(&This->roots);
+
+ return NSTC2_fnInsertRoot(iface, root_count, psiRoot, grfEnumFlags, grfRootStyle, pif);
}
static HRESULT WINAPI NSTC2_fnRemoveRoot(INameSpaceTreeControl2* iface,
IShellItem *psiRoot)
{
NSTC2Impl *This = (NSTC2Impl*)iface;
- FIXME("stub, %p (%p)\n", This, psiRoot);
- return E_NOTIMPL;
+ nstc_root *cursor, *root = NULL;
+ TRACE("%p (%p)\n", This, psiRoot);
+
+ if(!psiRoot)
+ return E_NOINTERFACE;
+
+ LIST_FOR_EACH_ENTRY(cursor, &This->roots, nstc_root, entry)
+ {
+ HRESULT hr;
+ int order;
+ TRACE("cursor->psi is %p\n", cursor->psi);
+ hr = IShellItem_Compare(psiRoot, cursor->psi, SICHINT_DISPLAY, &order);
+ if(hr == S_OK)
+ {
+ root = cursor;
+ break;
+ }
+ }
+
+ TRACE("root %p\n", root);
+ if(root)
+ {
+ SendMessageW(This->hwnd_tv, TVM_DELETEITEM, 0, (LPARAM)root->htreeitem);
+ events_OnItemDeleted(This, root->psi, TRUE);
+ list_remove(&root->entry);
+ HeapFree(GetProcessHeap(), 0, root);
+ return S_OK;
+ }
+ else
+ {
+ ERR("No matching root found.\n");
+ return E_FAIL;
+ }
}
static HRESULT WINAPI NSTC2_fnRemoveAllRoots(INameSpaceTreeControl2* iface)
{
NSTC2Impl *This = (NSTC2Impl*)iface;
- FIXME("stub, %p\n", This);
- return E_NOTIMPL;
+ nstc_root *cur1, *cur2;
+ UINT removed = 0;
+ TRACE("%p\n", This);
+
+ LIST_FOR_EACH_ENTRY_SAFE(cur1, cur2, &This->roots, nstc_root, entry)
+ {
+ NSTC2_fnRemoveRoot(iface, cur1->psi);
+ removed++;
+ }
+
+ if(removed)
+ return S_OK;
+ else
+ return E_INVALIDARG;
}
static HRESULT WINAPI NSTC2_fnGetRootItems(INameSpaceTreeControl2* iface,
IShellItemArray **ppsiaRootItems)
{
NSTC2Impl *This = (NSTC2Impl*)iface;
- FIXME("stub, %p (%p)\n", This, ppsiaRootItems);
- return E_NOTIMPL;
+ IShellFolder *psf;
+ LPITEMIDLIST *array;
+ nstc_root *root;
+ UINT count, i;
+ HRESULT hres;
+ TRACE("%p (%p)\n", This, ppsiaRootItems);
+
+ count = list_count(&This->roots);
+
+ if(!count)
+ return E_INVALIDARG;
+
+ array = HeapAlloc(GetProcessHeap(), 0, sizeof(LPITEMIDLIST*)*count);
+
+ i = 0;
+ LIST_FOR_EACH_ENTRY(root, &This->roots, nstc_root, entry)
+ SHGetIDListFromObject((IUnknown*)root->psi, &array[i++]);
+
+ SHGetDesktopFolder(&psf);
+ hres = SHCreateShellItemArray(NULL, psf, count, (PCUITEMID_CHILD_ARRAY)array,
+ ppsiaRootItems);
+ IShellFolder_Release(psf);
+
+ for(i = 0; i < count; i++)
+ ILFree(array[i]);
+
+ HeapFree(GetProcessHeap(), 0, array);
+
+ return hres;
}
static HRESULT WINAPI NSTC2_fnSetItemState(INameSpaceTreeControl2* iface,
@@ -709,6 +1003,8 @@ HRESULT NamespaceTreeControl_Constructor(IUnknown *pUnkOuter, REFIID riid, void
nstc->lpVtbl = &vt_INameSpaceTreeControl2;
nstc->lpowVtbl = &vt_IOleWindow;
+ list_init(&nstc->roots);
+
ret = INameSpaceTreeControl_QueryInterface((INameSpaceTreeControl*)nstc, riid, ppv);
INameSpaceTreeControl_Release((INameSpaceTreeControl*)nstc);
diff --git a/dlls/explorerframe/tests/nstc.c b/dlls/explorerframe/tests/nstc.c
index a3999b1..67ed2a6 100644
--- a/dlls/explorerframe/tests/nstc.c
+++ b/dlls/explorerframe/tests/nstc.c
@@ -320,6 +320,35 @@ const INameSpaceTreeControlEventsVtbl vt_NSTCEvents = {
};
#undef NSTCE_IMPL
+/* Process some messages */
+static void process_msgs(void)
+{
+ MSG msg;
+ BOOL got_msg;
+ do {
+ got_msg = FALSE;
+ Sleep(100);
+ while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ got_msg = TRUE;
+ }
+ } while(got_msg);
+
+ /* There is a timer that sometimes fires after about 500ms, sadly
+ we need to wait for it (Timer ID is 87, sending WM_TIMER
+ manually does not seem to help us.). Failing to wait can
+ results in seemingly sporadic selection changes. */
+ Sleep(500);
+
+ while(PeekMessage( &msg, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+
static void test_initialization(void)
{
INameSpaceTreeControl2 *pnstc;
@@ -471,20 +500,148 @@ static void test_basics(void)
{
INameSpaceTreeControl *pnstc;
INameSpaceTreeControl2 *pnstc2;
+ IShellItemArray *psia;
+ IShellFolder *psfdesktop;
+ IShellItem *psidesktop, *psidesktop2;
IOleWindow *pow;
+ LPITEMIDLIST pidl_desktop;
HRESULT hr;
UINT i, res;
RECT rc;
+ /* These should exist on platforms supporting the NSTC */
+ ok(pSHCreateShellItem != NULL, "No SHCreateShellItem.\n");
+ ok(pSHGetIDListFromObject != NULL, "No SHCreateShellItem.\n");
+
+ /* Create ShellItems for testing. */
+ SHGetDesktopFolder(&psfdesktop);
+ hr = pSHGetIDListFromObject((IUnknown*)psfdesktop, &pidl_desktop);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ if(SUCCEEDED(hr)) {
+ hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ hr = pSHCreateShellItem(NULL, NULL, pidl_desktop, &psidesktop2);
+ ok(hr == S_OK, "Got 0x%08x\n", hr);
+ ILFree(pidl_desktop);
+ }
+ ok(psidesktop != psidesktop2, "psidesktop == psidesktop2\n");
+ IShellFolder_Release(psfdesktop);
+
hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
&IID_INameSpaceTreeControl, (void**)&pnstc);
ok(hr == S_OK, "Failed to initialize control (0x%08x)\n", hr);
+ /* Some tests on an uninitialized control */
+ hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
+ ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
+ ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, NULL);
+ ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_NONFOLDERS, 0, NULL);
+ ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
+ process_msgs();
+
/* Initialize the control */
rc.top = rc.left = 0; rc.right = rc.bottom = 200;
hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, &rc, 0);
ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, NULL);
+ ok(hr == E_NOINTERFACE, "Got (0x%08x)\n", hr);
+
+ if(0)
+ {
+ /* Crashes with native */
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, NULL, SHCONTF_FOLDERS, 0, NULL);
+ hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, NULL, SHCONTF_FOLDERS, 0, NULL);
+
+ }
+
+ /* Note the usage of psidesktop and psidesktop2 */
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop2, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ process_msgs();
+
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+
+ hr = INameSpaceTreeControl_RemoveRoot(pnstc, psidesktop);
+ ok(hr == E_FAIL, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
+ ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
+
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+
+ hr = INameSpaceTreeControl_InsertRoot(pnstc, 0, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_InsertRoot(pnstc, -1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_InsertRoot(pnstc, 50, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_InsertRoot(pnstc, 1, psidesktop, SHCONTF_FOLDERS, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+
+ hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+
+ if(0)
+ {
+ /* Crashes on native. */
+ hr = INameSpaceTreeControl_GetRootItems(pnstc, NULL);
+ }
+
+ hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
+ ok(hr == E_INVALIDARG, "Got (0x%08x)\n", hr);
+
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0x1234, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0xDEADBEEF, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0, 0, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0, 1234, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ hr = INameSpaceTreeControl_AppendRoot(pnstc, psidesktop, 0, 0xDEADBEEF, NULL);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ process_msgs();
+
+ hr = INameSpaceTreeControl_GetRootItems(pnstc, &psia);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ if(SUCCEEDED(hr))
+ {
+ DWORD count, i;
+ hr = IShellItemArray_GetCount(psia, &count);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ ok(count == 6, "Got %d roots.\n", hr);
+ for(i = 0; i < count; i++)
+ {
+ IShellItem *psi;
+ hr = IShellItemArray_GetItemAt(psia, i, &psi);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
+ if(SUCCEEDED(hr)) IShellItem_Release(psi);
+ }
+
+ IShellItemArray_Release(psia);
+ }
+
+ hr = INameSpaceTreeControl_RemoveAllRoots(pnstc);
+ ok(hr == S_OK, "Got (0x%08x)\n", hr);
/* Set/GetControlStyle(2) */
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_INameSpaceTreeControl2, (void**)&pnstc2);
@@ -696,6 +853,9 @@ static void test_basics(void)
skip("INameSpaceTreeControl2 missing.\n");
}
+ IShellItem_Release(psidesktop);
+ IShellItem_Release(psidesktop2);
+
hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
ok(hr == S_OK, "Got 0x%08x\n", hr);
if(SUCCEEDED(hr))
--
1.7.2
More information about the wine-patches
mailing list