https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c0020b68219c438d47f80f9580d82710ab514f26

commit c0020b68219c438d47f80f9580d82710ab514f26
Author:     Katayama Hirofumi MZ <katayama.hirofumi...@gmail.com>
AuthorDate: Sun Jan 28 11:35:44 2024 +0900
Commit:     GitHub <nore...@github.com>
CommitDate: Sun Jan 28 11:35:44 2024 +0900

    [MSUTB] Add CTipbarAccessible (#6417)
    
    Supporting Language Bar...
    JIRA issue: CORE-19363
    - Implement CTipbarAccessible class.
    - Add delay link to oleacc.dll.
---
 dll/win32/msutb/CMakeLists.txt |   2 +-
 dll/win32/msutb/msutb.cpp      | 628 ++++++++++++++++++++++++++++++++++++++++-
 dll/win32/msutb/precomp.h      |   1 +
 3 files changed, 619 insertions(+), 12 deletions(-)

diff --git a/dll/win32/msutb/CMakeLists.txt b/dll/win32/msutb/CMakeLists.txt
index dd79a30d8c5..978742390a4 100644
--- a/dll/win32/msutb/CMakeLists.txt
+++ b/dll/win32/msutb/CMakeLists.txt
@@ -15,5 +15,5 @@ set_module_type(msutb win32dll)
 add_dependencies(msutb msctf psdk)
 target_link_libraries(msutb wine uuid atl_classes)
 add_importlibs(msutb user32 gdi32 advapi32 msvcrt kernel32 ntdll)
-add_delay_importlibs(msutb comctl32 msctf ole32 oleaut32 shell32)
+add_delay_importlibs(msutb comctl32 msctf ole32 oleacc oleaut32 shell32)
 add_cd_file(TARGET msutb DESTINATION reactos/system32 FOR all)
diff --git a/dll/win32/msutb/msutb.cpp b/dll/win32/msutb/msutb.cpp
index 605fc6130d4..6ab8eb45b21 100644
--- a/dll/win32/msutb/msutb.cpp
+++ b/dll/win32/msutb/msutb.cpp
@@ -2,7 +2,7 @@
  * PROJECT:     ReactOS msutb.dll
  * LICENSE:     LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later)
  * PURPOSE:     Language Bar (Tipbar)
- * COPYRIGHT:   Copyright 2023 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
+ * COPYRIGHT:   Copyright 2023-2024 Katayama Hirofumi MZ 
<katayama.hirofumi...@gmail.com>
  */
 
 #include "precomp.h"
@@ -14,6 +14,7 @@ UINT g_wmTaskbarCreated = 0;
 UINT g_uACP = CP_ACP;
 DWORD g_dwOSInfo = 0;
 CRITICAL_SECTION g_cs;
+LONG g_DllRefCount = 0;
 
 EXTERN_C void __cxa_pure_virtual(void)
 {
@@ -31,12 +32,13 @@ END_OBJECT_MAP()
 CMsUtbModule gModule;
 
 class CCicLibMenuItem;
+class CTipbarAccItem;
 
 /***********************************************************************/
 
 class CCicLibMenu : public ITfMenu
 {
-public:
+protected:
     CicArray<CCicLibMenuItem*> m_MenuItems;
     LONG m_cRefs;
 
@@ -63,7 +65,7 @@ public:
 
 class CCicLibMenuItem
 {
-public:
+protected:
     DWORD m_uId;
     DWORD m_dwFlags;
     HBITMAP m_hbmp;
@@ -88,6 +90,92 @@ public:
 
 /***********************************************************************/
 
+class CTipbarAccessible : public IAccessible
+{
+protected:
+    LONG m_cRefs;
+    HWND m_hWnd;
+    IAccessible *m_pStdAccessible;
+    ITypeInfo *m_pTypeInfo;
+    BOOL m_bInitialized;
+    CicArray<CTipbarAccItem*> m_AccItems;
+    LONG m_cSelection;
+
+public:
+    CTipbarAccessible(CTipbarAccItem *pItem);
+    virtual ~CTipbarAccessible();
+
+    HRESULT Initialize();
+
+    BOOL AddAccItem(CTipbarAccItem *pItem);
+    HRESULT RemoveAccItem(CTipbarAccItem *pItem);
+    void ClearAccItems();
+    CTipbarAccItem *AccItemFromID(INT iItem);
+    INT GetIDOfItem(CTipbarAccItem *pTarget);
+
+    LONG_PTR CreateRefToAccObj(WPARAM wParam);
+    BOOL DoDefaultActionReal(INT nID);
+    void NotifyWinEvent(DWORD event, CTipbarAccItem *pItem);
+    void SetWindow(HWND hWnd);
+
+    // IUnknown methods
+    STDMETHOD(QueryInterface)(REFIID riid, void **ppvObject);
+    STDMETHOD_(ULONG, AddRef)();
+    STDMETHOD_(ULONG, Release)();
+
+    // IDispatch methods
+    STDMETHOD(GetTypeInfoCount)(UINT *pctinfo);
+    STDMETHOD(GetTypeInfo)(
+        UINT iTInfo,
+        LCID lcid,
+        ITypeInfo **ppTInfo);
+    STDMETHOD(GetIDsOfNames)(
+        REFIID riid,
+        LPOLESTR *rgszNames,
+        UINT cNames,
+        LCID lcid,
+        DISPID *rgDispId);
+    STDMETHOD(Invoke)(
+        DISPID dispIdMember,
+        REFIID riid,
+        LCID lcid,
+        WORD wFlags,
+        DISPPARAMS *pDispParams,
+        VARIANT *pVarResult,
+        EXCEPINFO *pExcepInfo,
+        UINT *puArgErr);
+
+    // IAccessible methods
+    STDMETHOD(get_accParent)(IDispatch **ppdispParent);
+    STDMETHOD(get_accChildCount)(LONG *pcountChildren);
+    STDMETHOD(get_accChild)(VARIANT varChildID, IDispatch **ppdispChild);
+    STDMETHOD(get_accName)(VARIANT varID, BSTR *pszName);
+    STDMETHOD(get_accValue)(VARIANT varID, BSTR *pszValue);
+    STDMETHOD(get_accDescription)(VARIANT varID, BSTR *description);
+    STDMETHOD(get_accRole)(VARIANT varID, VARIANT *role);
+    STDMETHOD(get_accState)(VARIANT varID, VARIANT *state);
+    STDMETHOD(get_accHelp)(VARIANT varID, BSTR *help);
+    STDMETHOD(get_accHelpTopic)(BSTR *helpfile, VARIANT varID, LONG *pidTopic);
+    STDMETHOD(get_accKeyboardShortcut)(VARIANT varID, BSTR *shortcut);
+    STDMETHOD(get_accFocus)(VARIANT *pvarID);
+    STDMETHOD(get_accSelection)(VARIANT *pvarID);
+    STDMETHOD(get_accDefaultAction)(VARIANT varID, BSTR *action);
+    STDMETHOD(accSelect)(LONG flagsSelect, VARIANT varID);
+    STDMETHOD(accLocation)(
+        LONG *left,
+        LONG *top,
+        LONG *width,
+        LONG *height,
+        VARIANT varID);
+    STDMETHOD(accNavigate)(LONG dir, VARIANT varStart, VARIANT *pvarEnd);
+    STDMETHOD(accHitTest)(LONG left, LONG top, VARIANT *pvarID);
+    STDMETHOD(accDoDefaultAction)(VARIANT varID);
+    STDMETHOD(put_accName)(VARIANT varID, BSTR name);
+    STDMETHOD(put_accValue)(VARIANT varID, BSTR value);
+};
+
+/***********************************************************************/
+
 class CTipbarAccItem
 {
 public:
@@ -98,9 +186,9 @@ public:
     {
         return SysAllocString(L"");
     }
-    STDMETHOD(UnknownMethod1)() // FIXME: Name
+    STDMETHOD_(BSTR, GetAccValue)()
     {
-        return S_OK;
+        return NULL;
     }
     STDMETHOD_(INT, GetAccRole)()
     {
@@ -114,17 +202,17 @@ public:
     {
         *lprc = { 0, 0, 0, 0 };
     }
-    STDMETHOD(UnknownMethod2)() // FIXME: Name
+    STDMETHOD_(BSTR, GetAccDefaultAction)()
     {
-        return S_OK;
+        return NULL;
     }
-    STDMETHOD(UnknownMethod3)() // FIXME: Name
+    STDMETHOD(DoAccDefaultAction)()
     {
         return S_OK;
     }
-    STDMETHOD(UnknownMethod4)() // FIXME: Name
+    STDMETHOD_(BOOL, DoAccDefaultActionReal)()
     {
-        return S_OK;
+        return FALSE;
     }
 };
 
@@ -361,6 +449,524 @@ HBITMAP CCicLibMenuItem::CreateBitmap(HANDLE hBitmap)
     return hbmMem;
 }
 
+/***********************************************************************
+ * CTipbarAccessible
+ */
+
+CTipbarAccessible::CTipbarAccessible(CTipbarAccItem *pItem)
+{
+    m_cRefs = 1;
+    m_hWnd = NULL;
+    m_pTypeInfo = NULL;
+    m_pStdAccessible = NULL;
+    m_bInitialized = FALSE;
+    m_cSelection = 1;
+    m_AccItems.Add(pItem);
+    ++g_DllRefCount;
+}
+
+CTipbarAccessible::~CTipbarAccessible()
+{
+    m_pTypeInfo = m_pTypeInfo;
+    if (m_pTypeInfo)
+    {
+        m_pTypeInfo->Release();
+        m_pTypeInfo = NULL;
+    }
+    if (m_pStdAccessible)
+    {
+        m_pStdAccessible->Release();
+        m_pStdAccessible = NULL;
+    }
+    --g_DllRefCount;
+}
+
+HRESULT CTipbarAccessible::Initialize()
+{
+    m_bInitialized = TRUE;
+
+    HRESULT hr = ::CreateStdAccessibleObject(m_hWnd, OBJID_CLIENT, 
IID_IAccessible,
+                                             (void **)&m_pStdAccessible);
+    if (FAILED(hr))
+        return hr;
+
+    ITypeLib *pTypeLib;
+    hr = ::LoadRegTypeLib(LIBID_Accessibility, 1, 0, 0, &pTypeLib);
+    if (FAILED(hr))
+        hr = ::LoadTypeLib(L"OLEACC.DLL", &pTypeLib);
+
+    if (SUCCEEDED(hr))
+    {
+        hr = pTypeLib->GetTypeInfoOfGuid(IID_IAccessible, &m_pTypeInfo);
+        pTypeLib->Release();
+    }
+
+    return hr;
+}
+
+BOOL CTipbarAccessible::AddAccItem(CTipbarAccItem *pItem)
+{
+    return m_AccItems.Add(pItem);
+}
+
+HRESULT CTipbarAccessible::RemoveAccItem(CTipbarAccItem *pItem)
+{
+    for (size_t iItem = 0; iItem < m_AccItems.size(); ++iItem)
+    {
+        if (m_AccItems[iItem] == pItem)
+        {
+            m_AccItems.Remove(iItem, 1);
+            break;
+        }
+    }
+    return S_OK;
+}
+
+void CTipbarAccessible::ClearAccItems()
+{
+    m_AccItems.clear();
+}
+
+CTipbarAccItem *CTipbarAccessible::AccItemFromID(INT iItem)
+{
+    if (iItem < 0 || (INT)m_AccItems.size() <= iItem)
+        return NULL;
+    return m_AccItems[iItem];
+}
+
+INT CTipbarAccessible::GetIDOfItem(CTipbarAccItem *pTarget)
+{
+    for (size_t iItem = 0; iItem < m_AccItems.size(); ++iItem)
+    {
+        if (pTarget == m_AccItems[iItem])
+            return (INT)iItem;
+    }
+    return -1;
+}
+
+LONG_PTR CTipbarAccessible::CreateRefToAccObj(WPARAM wParam)
+{
+    return ::LresultFromObject(IID_IAccessible, wParam, this);
+}
+
+BOOL CTipbarAccessible::DoDefaultActionReal(INT nID)
+{
+    CTipbarAccItem *pItem = AccItemFromID(nID);
+    if (!pItem)
+        return FALSE;
+    return pItem->DoAccDefaultActionReal();
+}
+
+void CTipbarAccessible::NotifyWinEvent(DWORD event, CTipbarAccItem *pItem)
+{
+    INT nID = GetIDOfItem(pItem);
+    if (nID < 0)
+        return;
+
+    ::NotifyWinEvent(event, m_hWnd, -4, nID);
+}
+
+void CTipbarAccessible::SetWindow(HWND hWnd)
+{
+    m_hWnd = hWnd;
+}
+
+STDMETHODIMP CTipbarAccessible::QueryInterface(
+    REFIID riid,
+    void **ppvObject)
+{
+    if (IsEqualIID(riid, IID_IUnknown) ||
+        IsEqualIID(riid, IID_IDispatch) ||
+        IsEqualIID(riid, IID_IAccessible))
+    {
+        *ppvObject = this;
+        AddRef();
+        return S_OK;
+    }
+    return E_NOINTERFACE;
+}
+
+STDMETHODIMP_(ULONG) CTipbarAccessible::AddRef()
+{
+    return ::InterlockedIncrement(&m_cRefs);
+}
+
+STDMETHODIMP_(ULONG) CTipbarAccessible::Release()
+{
+    LONG count = ::InterlockedDecrement(&m_cRefs);
+    if (count == 0)
+    {
+        delete this;
+        return 0;
+    }
+    return count;
+}
+
+STDMETHODIMP CTipbarAccessible::GetTypeInfoCount(UINT *pctinfo)
+{
+    if (!pctinfo)
+        return E_INVALIDARG;
+    *pctinfo = (m_pTypeInfo == NULL);
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::GetTypeInfo(
+    UINT iTInfo,
+    LCID lcid,
+    ITypeInfo **ppTInfo)
+{
+    if (!ppTInfo)
+        return E_INVALIDARG;
+    *ppTInfo = NULL;
+    if (iTInfo != 0)
+        return TYPE_E_ELEMENTNOTFOUND;
+    if (!m_pTypeInfo)
+        return E_NOTIMPL;
+    *ppTInfo = m_pTypeInfo;
+    m_pTypeInfo->AddRef();
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::GetIDsOfNames(
+    REFIID riid,
+    LPOLESTR *rgszNames,
+    UINT cNames,
+    LCID lcid,
+    DISPID *rgDispId)
+{
+    if (!m_pTypeInfo)
+        return E_NOTIMPL;
+    return m_pTypeInfo->GetIDsOfNames(rgszNames, cNames, rgDispId);
+}
+
+STDMETHODIMP CTipbarAccessible::Invoke(
+    DISPID dispIdMember,
+    REFIID riid,
+    LCID lcid,
+    WORD wFlags,
+    DISPPARAMS *pDispParams,
+    VARIANT *pVarResult,
+    EXCEPINFO *pExcepInfo,
+    UINT *puArgErr)
+{
+    if (!m_pTypeInfo)
+        return E_NOTIMPL;
+    return m_pTypeInfo->Invoke(this,
+                               dispIdMember,
+                               wFlags,
+                               pDispParams,
+                               pVarResult,
+                               pExcepInfo,
+                               puArgErr);
+}
+
+STDMETHODIMP CTipbarAccessible::get_accParent(IDispatch **ppdispParent)
+{
+    return m_pStdAccessible->get_accParent(ppdispParent);
+}
+
+STDMETHODIMP CTipbarAccessible::get_accChildCount(LONG *pcountChildren)
+{
+    if (!pcountChildren)
+        return E_INVALIDARG;
+    INT cItems = (INT)m_AccItems.size();
+    if (!cItems)
+        return E_FAIL;
+    *pcountChildren = cItems - 1;
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accChild(
+    VARIANT varChildID,
+    IDispatch **ppdispChild)
+{
+    if (!ppdispChild)
+        return E_INVALIDARG;
+    *ppdispChild = NULL;
+    return S_FALSE;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accName(
+    VARIANT varID,
+    BSTR *pszName)
+{
+    if (!pszName)
+        return E_INVALIDARG;
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    if (!pItem)
+        return E_INVALIDARG;
+    *pszName = pItem->GetAccName();
+    if (!*pszName)
+        return DISP_E_MEMBERNOTFOUND;
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accValue(
+    VARIANT varID,
+    BSTR *pszValue)
+{
+    if (!pszValue)
+        return E_INVALIDARG;
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    if (!pItem)
+        return E_INVALIDARG;
+    *pszValue = pItem->GetAccValue();
+    if (!*pszValue)
+        return DISP_E_MEMBERNOTFOUND;
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accDescription(
+    VARIANT varID,
+    BSTR *description)
+{
+    if (!description)
+        return E_INVALIDARG;
+    return m_pStdAccessible->get_accDescription(varID, description);
+}
+
+STDMETHODIMP CTipbarAccessible::get_accRole(
+    VARIANT varID,
+    VARIANT *role)
+{
+    if (!role)
+        return E_INVALIDARG;
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    if (!pItem)
+        return E_INVALIDARG;
+    V_VT(role) = VT_I4;
+    V_I4(role) = pItem->GetAccRole();
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accState(
+    VARIANT varID,
+    VARIANT *state)
+{
+    if (!state)
+        return E_INVALIDARG;
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    if (!pItem)
+        return E_INVALIDARG;
+    V_VT(state) = VT_I4;
+    V_I4(state) = pItem->GetAccState();
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accHelp(VARIANT varID, BSTR *help)
+{
+    return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accHelpTopic(
+    BSTR *helpfile,
+    VARIANT varID,
+    LONG *pidTopic)
+{
+    return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accKeyboardShortcut(VARIANT varID, BSTR 
*shortcut)
+{
+    return DISP_E_MEMBERNOTFOUND;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accFocus(VARIANT *pvarID)
+{
+    if (!pvarID)
+        return E_INVALIDARG;
+    V_VT(pvarID) = VT_EMPTY;
+    return S_FALSE;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accSelection(VARIANT *pvarID)
+{
+    if (!pvarID)
+        return E_INVALIDARG;
+
+    V_VT(pvarID) = VT_EMPTY;
+
+    INT cItems = (INT)m_AccItems.size();
+    if (cItems < m_cSelection)
+        return S_FALSE;
+
+    if (cItems > m_cSelection)
+    {
+        V_VT(pvarID) = VT_I4;
+        V_I4(pvarID) = m_cSelection;
+    }
+
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::get_accDefaultAction(
+    VARIANT varID,
+    BSTR *action)
+{
+    if (!action)
+        return E_INVALIDARG;
+    *action = NULL;
+
+    if (V_VT(&varID) != VT_I4)
+        return E_INVALIDARG;
+
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    if (!pItem)
+        return DISP_E_MEMBERNOTFOUND;
+    *action = pItem->GetAccDefaultAction();
+    if (!*action)
+        return S_FALSE;
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::accSelect(
+    LONG flagsSelect,
+    VARIANT varID)
+{
+    if ((flagsSelect & SELFLAG_ADDSELECTION) && (flagsSelect & 
SELFLAG_REMOVESELECTION))
+        return E_INVALIDARG;
+    if (flagsSelect & (SELFLAG_TAKEFOCUS | SELFLAG_ADDSELECTION | 
SELFLAG_EXTENDSELECTION))
+        return S_FALSE;
+    if (flagsSelect & SELFLAG_REMOVESELECTION)
+        return S_OK;
+    if (V_VT(&varID) != VT_I4)
+        return E_INVALIDARG;
+    if (flagsSelect & SELFLAG_TAKESELECTION)
+    {
+        m_cSelection = V_I4(&varID);
+        return S_OK;
+    }
+    return S_FALSE;
+}
+
+STDMETHODIMP CTipbarAccessible::accLocation(
+    LONG *left,
+    LONG *top,
+    LONG *width,
+    LONG *height,
+    VARIANT varID)
+{
+    if (!left || !top || !width || !height)
+        return E_INVALIDARG;
+
+    if (!V_I4(&varID))
+        return m_pStdAccessible->accLocation(left, top, width, height, varID);
+
+    RECT rc;
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    pItem->GetAccLocation(&rc);
+
+    *left = rc.left;
+    *top = rc.top;
+    *width = rc.right - rc.left;
+    *height = rc.bottom - rc.top;
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::accNavigate(
+    LONG dir,
+    VARIANT varStart,
+    VARIANT *pvarEnd)
+{
+    if (m_AccItems.size() <= 1)
+    {
+        V_VT(pvarEnd) = VT_EMPTY;
+        return S_OK;
+    }
+
+    switch (dir)
+    {
+        case NAVDIR_UP:
+        case NAVDIR_LEFT:
+        case NAVDIR_PREVIOUS:
+            V_VT(pvarEnd) = VT_I4;
+            V_I4(pvarEnd) = V_I4(&varStart) - 1;
+            if (V_I4(&varStart) - 1 <= 0)
+                V_I4(pvarEnd) = (INT)(m_AccItems.size() - 1);
+            return S_OK;
+
+        case NAVDIR_DOWN:
+        case NAVDIR_RIGHT:
+        case NAVDIR_NEXT:
+            V_VT(pvarEnd) = VT_I4;
+            V_I4(pvarEnd) = V_I4(&varStart) + 1;
+            if ((INT)m_AccItems.size() <= V_I4(&varStart) + 1)
+                V_I4(pvarEnd) = 1;
+            return S_OK;
+
+        case NAVDIR_FIRSTCHILD:
+            V_VT(pvarEnd) = VT_I4;
+            V_I4(pvarEnd) = 1;
+            return S_OK;
+
+        case NAVDIR_LASTCHILD:
+            V_VT(pvarEnd) = VT_I4;
+            V_I4(pvarEnd) = (INT)(m_AccItems.size() - 1);
+            return S_OK;
+
+        default:
+            break;
+    }
+
+    V_VT(pvarEnd) = VT_EMPTY;
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::accHitTest(LONG left, LONG top, VARIANT 
*pvarID)
+{
+    if (!pvarID)
+        return E_INVALIDARG;
+    POINT Point = { left, top };
+    RECT Rect;
+    ::ScreenToClient(m_hWnd, &Point);
+    ::GetClientRect(m_hWnd, &Rect);
+
+    if (!::PtInRect(&Rect, Point))
+    {
+        V_VT(pvarID) = VT_EMPTY;
+        return S_OK;
+    }
+
+    V_VT(pvarID) = VT_I4;
+    V_I4(pvarID) = 0;
+
+    for (size_t iItem = 1; iItem < m_AccItems.size(); ++iItem)
+    {
+        CTipbarAccItem *pItem = m_AccItems[iItem];
+        if (pItem)
+        {
+            pItem->GetAccLocation(&Rect);
+            if (::PtInRect(&Rect, Point))
+            {
+                V_I4(pvarID) = iItem;
+                break;
+            }
+        }
+    }
+
+    return S_OK;
+}
+
+STDMETHODIMP CTipbarAccessible::accDoDefaultAction(VARIANT varID)
+{
+    if (V_VT(&varID) != VT_I4)
+        return E_INVALIDARG;
+    CTipbarAccItem *pItem = AccItemFromID(V_I4(&varID));
+    if (!pItem)
+        return DISP_E_MEMBERNOTFOUND;
+    return pItem->DoAccDefaultAction() == 0;
+}
+
+STDMETHODIMP CTipbarAccessible::put_accName(VARIANT varID, BSTR name)
+{
+    return S_FALSE;
+}
+
+STDMETHODIMP CTipbarAccessible::put_accValue(VARIANT varID, BSTR value)
+{
+    return S_FALSE;
+}
+
 /***********************************************************************
  * CTrayIconItem
  */
@@ -509,7 +1115,7 @@ STDAPI DllUnregisterServer(VOID)
 STDAPI DllCanUnloadNow(VOID)
 {
     TRACE("()\n");
-    return gModule.DllCanUnloadNow();
+    return gModule.DllCanUnloadNow() && (g_DllRefCount == 0);
 }
 
 /***********************************************************************
diff --git a/dll/win32/msutb/precomp.h b/dll/win32/msutb/precomp.h
index d4579a7511b..7e880a30d57 100644
--- a/dll/win32/msutb/precomp.h
+++ b/dll/win32/msutb/precomp.h
@@ -14,6 +14,7 @@
 #define INITGUID
 
 #include <windows.h>
+#include <oleacc.h>
 #include <imm.h>
 #include <ddk/immdev.h>
 #include <cguid.h>

Reply via email to