[PATCH 4/5] explorerframe/nstc: Implement Set/GetControlStyle(2). (resend)

David Hedberg david.hedberg at gmail.com
Mon Aug 2 20:43:09 CDT 2010


---
 dlls/explorerframe/nstc.c       |   81 +++++++++++--
 dlls/explorerframe/tests/nstc.c |  255 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 327 insertions(+), 9 deletions(-)

diff --git a/dlls/explorerframe/nstc.c b/dlls/explorerframe/nstc.c
index 2c73471..70e7e1c 100644
--- a/dlls/explorerframe/nstc.c
+++ b/dlls/explorerframe/nstc.c
@@ -43,12 +43,16 @@ typedef struct {
     HWND hwnd_tv;
 
     NSTCSTYLE style;
+    NSTCSTYLE2 style2;
 } NSTC2Impl;
 
 static const DWORD unsupported_styles =
     NSTCS_SINGLECLICKEXPAND | NSTCS_NOREPLACEOPEN | NSTCS_NOORDERSTREAM | NSTCS_FAVORITESMODE |
     NSTCS_EMPTYTEXT | NSTCS_ALLOWJUNCTIONS | NSTCS_SHOWTABSBUTTON | NSTCS_SHOWDELETEBUTTON |
     NSTCS_SHOWREFRESHBUTTON | NSTCS_SPRINGEXPAND | NSTCS_RICHTOOLTIP | NSTCS_NOINDENTCHECKS;
+static const DWORD unsupported_styles2 =
+    NSTCS2_INTERRUPTNOTIFICATIONS | NSTCS2_SHOWNULLSPACEMENU | NSTCS2_DISPLAYPADDING |
+    NSTCS2_DISPLAYPINNEDONLY | NTSCS2_NOSINGLETONAUTOEXPAND | NTSCS2_NEVERINSERTNONENUMERATED;
 
 /*************************************************************************
  * NamespaceTree helper functions
@@ -477,8 +481,54 @@ static HRESULT WINAPI NSTC2_fnSetControlStyle(INameSpaceTreeControl2* iface,
                                               NSTCSTYLE nstcsStyle)
 {
     NSTC2Impl *This = (NSTC2Impl*)iface;
-    FIXME("stub, %p (%x, %x)\n", This, nstcsMask, nstcsStyle);
-    return E_NOTIMPL;
+    static const DWORD tv_style_flags =
+        NSTCS_HASEXPANDOS | NSTCS_HASLINES | NSTCS_FULLROWSELECT |
+        NSTCS_HORIZONTALSCROLL | NSTCS_ROOTHASEXPANDO |
+        NSTCS_SHOWSELECTIONALWAYS | NSTCS_NOINFOTIP | NSTCS_EVENHEIGHT |
+        NSTCS_DISABLEDRAGDROP | NSTCS_NOEDITLABELS | NSTCS_CHECKBOXES;
+    static const DWORD host_style_flags = NSTCS_TABSTOP | NSTCS_BORDER;
+    static const DWORD nstc_flags =
+        NSTCS_SINGLECLICKEXPAND | NSTCS_NOREPLACEOPEN | NSTCS_NOORDERSTREAM |
+        NSTCS_FAVORITESMODE | NSTCS_EMPTYTEXT | NSTCS_ALLOWJUNCTIONS |
+        NSTCS_SHOWTABSBUTTON | NSTCS_SHOWDELETEBUTTON | NSTCS_SHOWREFRESHBUTTON;
+    TRACE("%p (%x, %x)\n", This, nstcsMask, nstcsStyle);
+
+    /* Fail if there is an attempt to set an unknown style. */
+    if(nstcsMask & ~(tv_style_flags | host_style_flags | nstc_flags))
+        return E_FAIL;
+
+    if(nstcsMask & tv_style_flags)
+    {
+        DWORD new_style;
+        treeview_style_from_nstcs(This, nstcsStyle, nstcsMask, &new_style);
+        SetWindowLongPtrW(This->hwnd_tv, GWL_STYLE, new_style);
+    }
+
+    /* Flags affecting the host window */
+    if(nstcsMask & NSTCS_BORDER)
+    {
+        DWORD new_style = GetWindowLongPtrW(This->hwnd_main, GWL_STYLE);
+        new_style &= ~WS_BORDER;
+        new_style |= nstcsStyle & NSTCS_BORDER ? WS_BORDER : 0;
+        SetWindowLongPtrW(This->hwnd_main, GWL_STYLE, new_style);
+    }
+    if(nstcsMask & NSTCS_TABSTOP)
+    {
+        DWORD new_style = GetWindowLongPtrW(This->hwnd_main, GWL_EXSTYLE);
+        new_style &= ~WS_EX_CONTROLPARENT;
+        new_style |= nstcsStyle & NSTCS_TABSTOP ? WS_EX_CONTROLPARENT : 0;
+        SetWindowLongPtrW(This->hwnd_main, GWL_EXSTYLE, new_style);
+    }
+
+    if((nstcsStyle & nstcsMask) & unsupported_styles)
+        FIXME("mask & style (0x%08x) contains unsupported style(s): 0x%08x\n",
+              (nstcsStyle & nstcsMask),
+              (nstcsStyle & nstcsMask) & unsupported_styles);
+
+    This->style &= ~nstcsMask;
+    This->style |= (nstcsStyle & nstcsMask);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI NSTC2_fnGetControlStyle(INameSpaceTreeControl2* iface,
@@ -486,8 +536,11 @@ static HRESULT WINAPI NSTC2_fnGetControlStyle(INameSpaceTreeControl2* iface,
                                               NSTCSTYLE *pnstcsStyle)
 {
     NSTC2Impl *This = (NSTC2Impl*)iface;
-    FIXME("stub, %p (%x, %p)\n", This, nstcsMask, pnstcsStyle);
-    return E_NOTIMPL;
+    TRACE("%p (%x, %p)\n", This, nstcsMask, pnstcsStyle);
+
+    *pnstcsStyle = (This->style & nstcsMask);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI NSTC2_fnSetControlStyle2(INameSpaceTreeControl2* iface,
@@ -495,8 +548,17 @@ static HRESULT WINAPI NSTC2_fnSetControlStyle2(INameSpaceTreeControl2* iface,
                                                NSTCSTYLE2 nstcsStyle)
 {
     NSTC2Impl *This = (NSTC2Impl*)iface;
-    FIXME("stub, %p (%x, %x)\n", This, nstcsMask, nstcsStyle);
-    return E_NOTIMPL;
+    TRACE("%p (%x, %x)\n", This, nstcsMask, nstcsStyle);
+
+    if((nstcsStyle & nstcsMask) & unsupported_styles2)
+        FIXME("mask & style (0x%08x) contains unsupported style(s): 0x%08x\n",
+              (nstcsStyle & nstcsMask),
+              (nstcsStyle & nstcsMask) & unsupported_styles2);
+
+    This->style2 &= ~nstcsMask;
+    This->style2 |= (nstcsStyle & nstcsMask);
+
+    return S_OK;
 }
 
 static HRESULT WINAPI NSTC2_fnGetControlStyle2(INameSpaceTreeControl2* iface,
@@ -504,8 +566,11 @@ static HRESULT WINAPI NSTC2_fnGetControlStyle2(INameSpaceTreeControl2* iface,
                                                NSTCSTYLE2 *pnstcsStyle)
 {
     NSTC2Impl *This = (NSTC2Impl*)iface;
-    FIXME("stub, %p (%x, %p)\n", This, nstcsMask, pnstcsStyle);
-    return E_NOTIMPL;
+    TRACE("%p (%x, %p)\n", This, nstcsMask, pnstcsStyle);
+
+    *pnstcsStyle = (This->style2 & nstcsMask);
+
+    return S_OK;
 }
 
 static const INameSpaceTreeControl2Vtbl vt_INameSpaceTreeControl2 = {
diff --git a/dlls/explorerframe/tests/nstc.c b/dlls/explorerframe/tests/nstc.c
index 6a72eb3..dc8f8f3 100644
--- a/dlls/explorerframe/tests/nstc.c
+++ b/dlls/explorerframe/tests/nstc.c
@@ -181,6 +181,252 @@ static BOOL test_initialization(void)
     return TRUE;
 }
 
+static void test_basics(void)
+{
+    INameSpaceTreeControl *pnstc;
+    INameSpaceTreeControl2 *pnstc2;
+    IOleWindow *pow;
+    HRESULT hr;
+    UINT i, res;
+    RECT rc;
+
+    hr = CoCreateInstance(&CLSID_NamespaceTreeControl, NULL, CLSCTX_INPROC_SERVER,
+                          &IID_INameSpaceTreeControl, (void**)&pnstc);
+    ok(hr == S_OK, "Failed to initialize control (0x%08x)\n", hr);
+
+    /* Initialize the control */
+    rc.top = rc.left = 0; rc.right = rc.bottom = 200;
+    hr = INameSpaceTreeControl_Initialize(pnstc, hwnd, &rc, 0);
+    ok(hr == S_OK, "Got (0x%08x)\n", hr);
+
+
+    /* Set/GetControlStyle(2) */
+    hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_INameSpaceTreeControl2, (void**)&pnstc2);
+    ok(hr == S_OK || broken(hr == E_NOINTERFACE), "Got 0x%08x\n", hr);
+    if(SUCCEEDED(hr))
+    {
+        DWORD tmp;
+        NSTCSTYLE style;
+        NSTCSTYLE2 style2;
+        static const NSTCSTYLE2 styles2[] =
+            { NSTCS2_INTERRUPTNOTIFICATIONS,NSTCS2_SHOWNULLSPACEMENU,
+              NSTCS2_DISPLAYPADDING,NSTCS2_DISPLAYPINNEDONLY,
+              NTSCS2_NOSINGLETONAUTOEXPAND,NTSCS2_NEVERINSERTNONENUMERATED, 0};
+
+
+        /* We can use this to differentiate between two versions of
+         * this interface. Windows 7 returns hr == S_OK. */
+        hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0, 0);
+        ok(hr == S_OK || broken(hr == E_FAIL), "Got 0x%08x\n", hr);
+        if(hr == S_OK)
+        {
+            static const NSTCSTYLE styles_setable[] =
+                { NSTCS_HASEXPANDOS,NSTCS_HASLINES,NSTCS_SINGLECLICKEXPAND,
+                  NSTCS_FULLROWSELECT,NSTCS_HORIZONTALSCROLL,
+                  NSTCS_ROOTHASEXPANDO,NSTCS_SHOWSELECTIONALWAYS,NSTCS_NOINFOTIP,
+                  NSTCS_EVENHEIGHT,NSTCS_NOREPLACEOPEN,NSTCS_DISABLEDRAGDROP,
+                  NSTCS_NOORDERSTREAM,NSTCS_BORDER,NSTCS_NOEDITLABELS,
+                  NSTCS_TABSTOP,NSTCS_FAVORITESMODE,NSTCS_EMPTYTEXT,NSTCS_CHECKBOXES,
+                  NSTCS_ALLOWJUNCTIONS,NSTCS_SHOWTABSBUTTON,NSTCS_SHOWDELETEBUTTON,
+                  NSTCS_SHOWREFRESHBUTTON, 0};
+            static const NSTCSTYLE styles_nonsetable[] =
+                { NSTCS_SPRINGEXPAND, NSTCS_RICHTOOLTIP, NSTCS_AUTOHSCROLL,
+                  NSTCS_FADEINOUTEXPANDOS,
+                  NSTCS_PARTIALCHECKBOXES, NSTCS_EXCLUSIONCHECKBOXES,
+                  NSTCS_DIMMEDCHECKBOXES, NSTCS_NOINDENTCHECKS,0};
+
+            /* Set/GetControlStyle */
+            style = style2 = 0xdeadbeef;
+            hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style == 0, "Got style %x\n", style);
+
+            hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0, 0xFFFFFFF);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+
+            hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0xFFFFFFFF, 0);
+            ok(hr == E_FAIL, "Got 0x%08x\n", hr);
+            hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, 0xFFFFFFFF, 0xFFFFFFFF);
+            ok(hr == E_FAIL, "Got 0x%08x\n", hr);
+
+            tmp = 0;
+            for(i = 0; styles_setable[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_setable[i], styles_setable[i]);
+                ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles_setable[i]);
+                if(SUCCEEDED(hr)) tmp |= styles_setable[i];
+            }
+            for(i = 0; styles_nonsetable[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_nonsetable[i], styles_nonsetable[i]);
+                ok(hr == E_FAIL, "Got 0x%08x (%x)\n", hr, styles_nonsetable[i]);
+            }
+
+            hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style == tmp, "Got style %x (expected %x)\n", style, tmp);
+            if(SUCCEEDED(hr))
+            {
+                DWORD tmp2;
+                for(i = 0; styles_setable[i] != 0; i++)
+                {
+                    hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, styles_setable[i], &tmp2);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    ok(tmp2 == (style & styles_setable[i]), "Got %x\n", tmp2);
+                }
+            }
+
+            for(i = 0; styles_setable[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_setable[i], 0);
+                ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles_setable[i]);
+            }
+            for(i = 0; styles_nonsetable[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles_nonsetable[i], 0);
+                ok(hr == E_FAIL, "Got 0x%08x (%x)\n", hr, styles_nonsetable[i]);
+            }
+            hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style == 0, "Got style %x\n", style);
+
+            /* Set/GetControlStyle2 */
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == 0, "Got style %x\n", style2);
+
+            hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0, 0);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0, 0xFFFFFFFF);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+
+            hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0xFFFFFFFF);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+
+            hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, 0xFFFFFFFF, 0);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == 0x00000000, "Got style %x\n", style2);
+
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == 0, "Got style %x\n", style2);
+
+            tmp = 0;
+            for(i = 0; styles2[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], styles2[i]);
+                ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
+                if(SUCCEEDED(hr)) tmp |= styles2[i];
+            }
+
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == tmp, "Got style %x (expected %x)\n", style2, tmp);
+            if(SUCCEEDED(hr))
+            {
+                DWORD tmp2;
+                for(i = 0; styles2[i] != 0; i++)
+                {
+                    hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, styles2[i], &tmp2);
+                    ok(hr == S_OK, "Got 0x%08x\n", hr);
+                    ok(tmp2 == (style2 & styles2[i]), "Got %x\n", tmp2);
+                }
+            }
+
+            for(i = 0; styles2[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], 0);
+                ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
+            }
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == 0, "Got style %x (expected 0)\n", style2);
+        }
+        else
+        {
+            /* 64-bit Windows Vista (others?) seems to have a somewhat
+             * different idea of how the methods of this interface
+             * should behave. */
+
+            static const NSTCSTYLE styles[] =
+                { NSTCS_HASEXPANDOS,NSTCS_HASLINES,NSTCS_SINGLECLICKEXPAND,
+                  NSTCS_FULLROWSELECT,NSTCS_SPRINGEXPAND,NSTCS_HORIZONTALSCROLL,
+                  NSTCS_RICHTOOLTIP, NSTCS_AUTOHSCROLL,
+                  NSTCS_FADEINOUTEXPANDOS,
+                  NSTCS_PARTIALCHECKBOXES,NSTCS_EXCLUSIONCHECKBOXES,
+                  NSTCS_DIMMEDCHECKBOXES, NSTCS_NOINDENTCHECKS,
+                  NSTCS_ROOTHASEXPANDO,NSTCS_SHOWSELECTIONALWAYS,NSTCS_NOINFOTIP,
+                  NSTCS_EVENHEIGHT,NSTCS_NOREPLACEOPEN,NSTCS_DISABLEDRAGDROP,
+                  NSTCS_NOORDERSTREAM,NSTCS_BORDER,NSTCS_NOEDITLABELS,
+                  NSTCS_TABSTOP,NSTCS_FAVORITESMODE,NSTCS_EMPTYTEXT,NSTCS_CHECKBOXES,
+                  NSTCS_ALLOWJUNCTIONS,NSTCS_SHOWTABSBUTTON,NSTCS_SHOWDELETEBUTTON,
+                  NSTCS_SHOWREFRESHBUTTON, 0};
+            trace("Detected broken INameSpaceTreeControl2.\n");
+
+            style = 0xdeadbeef;
+            hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, 0xFFFFFFFF, &style);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style == 0xdeadbeef, "Got style %x\n", style);
+
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == 0, "Got style %x\n", style2);
+
+            tmp = 0;
+            for(i = 0; styles[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle(pnstc2, styles[i], styles[i]);
+                ok(hr == E_FAIL || ((styles[i] & NSTCS_SPRINGEXPAND) && hr == S_OK),
+                   "Got 0x%08x (%x)\n", hr, styles[i]);
+                if(SUCCEEDED(hr)) tmp |= styles[i];
+            }
+
+            style = 0xdeadbeef;
+            hr = INameSpaceTreeControl2_GetControlStyle(pnstc2, tmp, &style);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style == 0xdeadbeef, "Got style %x\n", style);
+
+            tmp = 0;
+            for(i = 0; styles2[i] != 0; i++)
+            {
+                hr = INameSpaceTreeControl2_SetControlStyle2(pnstc2, styles2[i], styles2[i]);
+                ok(hr == S_OK, "Got 0x%08x (%x)\n", hr, styles2[i]);
+                if(SUCCEEDED(hr)) tmp |= styles2[i];
+            }
+
+            style2 = 0xdeadbeef;
+            hr = INameSpaceTreeControl2_GetControlStyle2(pnstc2, 0xFFFFFFFF, &style2);
+            ok(hr == S_OK, "Got 0x%08x\n", hr);
+            ok(style2 == tmp, "Got style %x\n", style2);
+
+        }
+
+        INameSpaceTreeControl2_Release(pnstc2);
+    }
+    else
+    {
+        skip("INameSpaceTreeControl2 missing.\n");
+    }
+
+    hr = INameSpaceTreeControl_QueryInterface(pnstc, &IID_IOleWindow, (void**)&pow);
+    ok(hr == S_OK, "Got 0x%08x\n", hr);
+    if(SUCCEEDED(hr))
+    {
+        HWND hwnd_nstc;
+        hr = IOleWindow_GetWindow(pow, &hwnd_nstc);
+        ok(hr == S_OK, "Got 0x%08x\n", hr);
+        DestroyWindow(hwnd_nstc);
+        IOleWindow_Release(pow);
+    }
+
+    res = INameSpaceTreeControl_Release(pnstc);
+    ok(!res, "res was %d!\n", res);
+}
+
 static void setup_window(void)
 {
     WNDCLASSA wc;
@@ -206,7 +452,14 @@ START_TEST(nstc)
     OleInitialize(NULL);
     setup_window();
 
-    test_initialization();
+    if(test_initialization())
+    {
+        test_basics();
+    }
+    else
+    {
+        win_skip("No NamespaceTreeControl (or instantiation failed).\n");
+    }
 
     destroy_window();
     OleUninitialize();
-- 
1.7.2




More information about the wine-patches mailing list