From 69931a4a7d1a58975cfc73ddf1c225cc87fbc21a Mon Sep 17 00:00:00 2001 From: Katayama Hirofumi MZ Date: Thu, 18 Jul 2024 23:21:40 +0900 Subject: [PATCH] [SHDOCVW] Initial implementation of Favorites bar (#7146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First step to Favorites bar support. Menu: [View]→[Explorer bar] →[Favorites] JIRA issue: CORE-19686 - Add CFavBand.cpp, CFavBand.h, favband.rgs, and resource.h files. - Modify CMakeLists.txt. - Add IDS_ADD and IDS_ORGANIZE resource strings. - Implement empty Favorites bar. - The treeview is not populated yet. - The Add button is not implemented yet. --- dll/win32/shdocvw/CFavBand.cpp | 647 +++++++++++++++++++++++++++++++ dll/win32/shdocvw/CFavBand.h | 183 +++++++++ dll/win32/shdocvw/CMakeLists.txt | 19 +- dll/win32/shdocvw/favband.rgs | 13 + dll/win32/shdocvw/lang/en-US.rc | 8 + dll/win32/shdocvw/resource.h | 12 + dll/win32/shdocvw/shdocvw.h | 8 + dll/win32/shdocvw/shdocvw.rc | 14 +- dll/win32/shdocvw/shdocvw_main.c | 15 +- dll/win32/shdocvw/shlinstobj.c | 8 + 10 files changed, 919 insertions(+), 8 deletions(-) create mode 100644 dll/win32/shdocvw/CFavBand.cpp create mode 100644 dll/win32/shdocvw/CFavBand.h create mode 100644 dll/win32/shdocvw/favband.rgs create mode 100644 dll/win32/shdocvw/lang/en-US.rc create mode 100644 dll/win32/shdocvw/resource.h diff --git a/dll/win32/shdocvw/CFavBand.cpp b/dll/win32/shdocvw/CFavBand.cpp new file mode 100644 index 00000000000..66e82d578ec --- /dev/null +++ b/dll/win32/shdocvw/CFavBand.cpp @@ -0,0 +1,647 @@ +/* + * PROJECT: ReactOS Explorer + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Favorites bar + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shdocvw.h" +#include "CFavBand.h" + +#include +WINE_DEFAULT_DEBUG_CHANNEL(shdocvw); + +void *operator new(size_t size) +{ + return ::LocalAlloc(LPTR, size); +} + +void operator delete(void *ptr) +{ + ::LocalFree(ptr); +} + +void operator delete(void *ptr, size_t size) +{ + ::LocalFree(ptr); +} + +#if 1 +#undef UNIMPLEMENTED +#define UNIMPLEMENTED ERR("%s is UNIMPLEMENTED!\n", __FUNCTION__) +#endif + +CFavBand::CFavBand() + : m_fVisible(FALSE) + , m_bFocused(FALSE) + , m_dwBandID(0) + , m_hToolbarImageList(NULL) + , m_hTreeViewImageList(NULL) +{ + ::InterlockedIncrement(&SHDOCVW_refCount); + SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &m_pidlFav); +} + +CFavBand::~CFavBand() +{ + if (m_hToolbarImageList) + { + ImageList_Destroy(m_hToolbarImageList); + m_hToolbarImageList = NULL; + } + if (m_hTreeViewImageList) + { + ImageList_Destroy(m_hTreeViewImageList); + m_hTreeViewImageList = NULL; + } + ::InterlockedDecrement(&SHDOCVW_refCount); +} + +VOID CFavBand::OnFinalMessage(HWND) +{ + // The message loop is finished, now we can safely destruct! + Release(); +} + +// *** helper methods *** + +BOOL CFavBand::CreateToolbar() +{ +#define IDB_SHELL_EXPLORER_SM 216 // Borrowed from browseui.dll + HINSTANCE hinstBrowseUI = LoadLibraryExW(L"browseui.dll", NULL, LOAD_LIBRARY_AS_DATAFILE); + ATLASSERT(hinstBrowseUI); + HBITMAP hbmToolbar = NULL; + if (hinstBrowseUI) + { + hbmToolbar = LoadBitmapW(hinstBrowseUI, MAKEINTRESOURCEW(IDB_SHELL_EXPLORER_SM)); + FreeLibrary(hinstBrowseUI); + } +#undef IDB_SHELL_EXPLORER_SM + ATLASSERT(hbmToolbar); + if (!hbmToolbar) + return FALSE; + + m_hToolbarImageList = ImageList_Create(16, 16, ILC_COLOR32, 0, 8); + ATLASSERT(m_hToolbarImageList); + if (!m_hToolbarImageList) + return FALSE; + + ImageList_Add(m_hToolbarImageList, hbmToolbar, NULL); + DeleteObject(hbmToolbar); + + DWORD style = WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NODIVIDER | + TBSTYLE_WRAPABLE; + HWND hwndTB = ::CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style, 0, 0, 0, 0, m_hWnd, + (HMENU)(LONG_PTR)IDW_TOOLBAR, instance, NULL); + ATLASSERT(hwndTB); + if (!hwndTB) + return FALSE; + + m_hwndToolbar.Attach(hwndTB); + m_hwndToolbar.SendMessage(TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0); + m_hwndToolbar.SendMessage(TB_SETIMAGELIST, 0, (LPARAM)m_hToolbarImageList); + m_hwndToolbar.SendMessage(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS); + + WCHAR szzAdd[MAX_PATH], szzOrganize[MAX_PATH]; + ZeroMemory(szzAdd, sizeof(szzAdd)); + ZeroMemory(szzOrganize, sizeof(szzOrganize)); + LoadStringW(instance, IDS_ADD, szzAdd, _countof(szzAdd)); + LoadStringW(instance, IDS_ORGANIZE, szzOrganize, _countof(szzOrganize)); + + TBBUTTON tbb[2] = { { 0 } }; + INT iButton = 0; + tbb[iButton].iBitmap = 3; + tbb[iButton].idCommand = ID_ADD; + tbb[iButton].fsState = TBSTATE_ENABLED; + tbb[iButton].fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT; + tbb[iButton].iString = (INT)m_hwndToolbar.SendMessage(TB_ADDSTRING, 0, (LPARAM)szzAdd); + ++iButton; + tbb[iButton].iBitmap = 42; + tbb[iButton].idCommand = ID_ORGANIZE; + tbb[iButton].fsState = TBSTATE_ENABLED; + tbb[iButton].fsStyle = BTNS_BUTTON | BTNS_AUTOSIZE | BTNS_SHOWTEXT; + tbb[iButton].iString = (INT)m_hwndToolbar.SendMessage(TB_ADDSTRING, 0, (LPARAM)szzOrganize); + ++iButton; + ATLASSERT(iButton == _countof(tbb)); + + LRESULT ret = m_hwndToolbar.SendMessage(TB_ADDBUTTONS, iButton, (LPARAM)&tbb); + ATLASSERT(ret); + + return ret; +} + +BOOL CFavBand::CreateTreeView() +{ + m_hTreeViewImageList = ImageList_Create(16, 16, ILC_COLOR32 | ILC_MASK, 64, 0); + ATLASSERT(m_hTreeViewImageList); + if (!m_hTreeViewImageList) + return FALSE; + + DWORD style = TVS_NOHSCROLL | TVS_NONEVENHEIGHT | TVS_FULLROWSELECT | TVS_INFOTIP | + TVS_SINGLEEXPAND | TVS_TRACKSELECT | TVS_SHOWSELALWAYS | TVS_EDITLABELS | + WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_TABSTOP; + HWND hwndTV = ::CreateWindowExW(WS_EX_CLIENTEDGE, WC_TREEVIEWW, NULL, style, 0, 0, 0, 0, + m_hWnd, (HMENU)(ULONG_PTR)IDW_TREEVIEW, instance, NULL); + ATLASSERT(hwndTV); + if (!hwndTV) + return FALSE; + + m_hwndTreeView.Attach(hwndTV); + TreeView_SetImageList(m_hwndTreeView, m_hTreeViewImageList, TVSIL_NORMAL); + + return TRUE; +} + +// *** message handlers *** + +LRESULT CFavBand::OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + INITCOMMONCONTROLSEX iccx = { sizeof(iccx), ICC_TREEVIEW_CLASSES | ICC_BAR_CLASSES }; + if (!::InitCommonControlsEx(&iccx) || !CreateToolbar() || !CreateTreeView()) + return -1; + + return 0; +} + +LRESULT CFavBand::OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + m_hwndTreeView.DestroyWindow(); + m_hwndToolbar.DestroyWindow(); + return 0; +} + +LRESULT CFavBand::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled) +{ + if (!m_hwndTreeView) + return 0; + + RECT rc; + GetClientRect(&rc); + LONG cx = rc.right, cy = rc.bottom; + + RECT rcTB; + m_hwndToolbar.SendMessage(TB_AUTOSIZE, 0, 0); + m_hwndToolbar.GetWindowRect(&rcTB); + + LONG cyTB = rcTB.bottom - rcTB.top; + m_hwndTreeView.MoveWindow(0, cyTB, cx, cy - cyTB); + + return 0; +} + +LRESULT CFavBand::OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + m_bFocused = TRUE; + IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast(this), TRUE); + return 0; +} + +LRESULT CFavBand::OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + IUnknown_OnFocusChangeIS(m_pSite, reinterpret_cast(this), FALSE); + m_bFocused = FALSE; + return 0; +} + +LRESULT CFavBand::OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled) +{ + switch (LOWORD(wParam)) + { + case ID_ADD: + { + UNIMPLEMENTED; + SHELL_ErrorBox(m_hWnd, ERROR_NOT_SUPPORTED); + break; + } + case ID_ORGANIZE: + { + SHELLEXECUTEINFOW sei = { sizeof(sei), SEE_MASK_IDLIST }; + sei.hwnd = m_hWnd; + sei.nShow = SW_SHOWNORMAL; + sei.lpIDList = m_pidlFav; + ::ShellExecuteExW(&sei); + break; + } + } + return 0; +} + +// *** IOleWindow *** + +STDMETHODIMP CFavBand::GetWindow(HWND *lphwnd) +{ + if (!lphwnd) + return E_INVALIDARG; + *lphwnd = m_hWnd; + return S_OK; +} + +STDMETHODIMP CFavBand::ContextSensitiveHelp(BOOL fEnterMode) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** IDockingWindow *** + +STDMETHODIMP CFavBand::CloseDW(DWORD dwReserved) +{ + // We do nothing, we don't have anything to save yet + TRACE("CloseDW called\n"); + return S_OK; +} + +STDMETHODIMP CFavBand::ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) +{ + /* Must return E_NOTIMPL according to MSDN */ + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::ShowDW(BOOL fShow) +{ + m_fVisible = fShow; + ShowWindow(fShow ? SW_SHOW : SW_HIDE); + return S_OK; +} + +// *** IDeskBand *** + +STDMETHODIMP CFavBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi) +{ + if (!pdbi) + return E_INVALIDARG; + + m_dwBandID = dwBandID; + + if (pdbi->dwMask & DBIM_MINSIZE) + { + pdbi->ptMinSize.x = 200; + pdbi->ptMinSize.y = 30; + } + + if (pdbi->dwMask & DBIM_MAXSIZE) + pdbi->ptMaxSize.y = -1; + + if (pdbi->dwMask & DBIM_INTEGRAL) + pdbi->ptIntegral.y = 1; + + if (pdbi->dwMask & DBIM_ACTUAL) + { + pdbi->ptActual.x = 200; + pdbi->ptActual.y = 30; + } + + if (pdbi->dwMask & DBIM_TITLE) + { +#define IDS_FAVORITES 47 // Borrowed from shell32.dll + HINSTANCE hShell32 = LoadLibraryExW(L"shell32.dll", NULL, LOAD_LIBRARY_AS_DATAFILE); + if (hShell32) + { + LoadStringW(hShell32, IDS_FAVORITES, pdbi->wszTitle, _countof(pdbi->wszTitle)); + FreeLibrary(hShell32); + } +#undef IDS_FAVORITES + } + + if (pdbi->dwMask & DBIM_MODEFLAGS) + pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT; + + if (pdbi->dwMask & DBIM_BKCOLOR) + pdbi->dwMask &= ~DBIM_BKCOLOR; + + return S_OK; +} + +// *** IObjectWithSite *** + +STDMETHODIMP CFavBand::SetSite(IUnknown *pUnkSite) +{ + HRESULT hr; + + if (pUnkSite == m_pSite) + return S_OK; + + TRACE("SetSite called\n"); + + if (!pUnkSite) + { + DestroyWindow(); + m_hWnd = NULL; + } + + if (pUnkSite != m_pSite) + m_pSite = NULL; + + if (!pUnkSite) + return S_OK; + + HWND hwndParent; + hr = IUnknown_GetWindow(pUnkSite, &hwndParent); + if (!SUCCEEDED(hr)) + { + ERR("Could not get parent's window! 0x%08lX\n", hr); + return E_INVALIDARG; + } + + m_pSite = pUnkSite; + + if (m_hWnd) + { + SetParent(hwndParent); // Change its parent + } + else + { + this->Create(hwndParent, NULL, NULL, WS_CHILD | WS_VISIBLE, 0, (UINT)0, NULL); + } + + return S_OK; +} + +STDMETHODIMP CFavBand::GetSite(REFIID riid, void **ppvSite) +{ + if (!ppvSite) + return E_POINTER; + *ppvSite = m_pSite; + return S_OK; +} + +// *** IOleCommandTarget *** + +STDMETHODIMP CFavBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** IServiceProvider *** + +STDMETHODIMP CFavBand::QueryService(REFGUID guidService, REFIID riid, void **ppvObject) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** IServiceProvider *** + +STDMETHODIMP CFavBand::QueryContextMenu( + HMENU hmenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::InvokeCommand( + LPCMINVOKECOMMANDINFO lpici) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::GetCommandString( + UINT_PTR idCmd, + UINT uType, + UINT *pwReserved, + LPSTR pszName, + UINT cchMax) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** IInputObject *** + +STDMETHODIMP CFavBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg) +{ + if (fActivate) + { + //SetFocus(); + SetActiveWindow(); + } + + if (lpMsg) + { + TranslateMessage(lpMsg); + DispatchMessage(lpMsg); + } + + return S_OK; +} + +STDMETHODIMP CFavBand::HasFocusIO() +{ + return m_bFocused ? S_OK : S_FALSE; +} + +STDMETHODIMP CFavBand::TranslateAcceleratorIO(LPMSG lpMsg) +{ + if (lpMsg->hwnd == m_hWnd) + { + TranslateMessage(lpMsg); + DispatchMessage(lpMsg); + return S_OK; + } + + return S_FALSE; +} + +// *** IPersist *** + +STDMETHODIMP CFavBand::GetClassID(CLSID *pClassID) +{ + if (!pClassID) + return E_POINTER; + *pClassID = CLSID_SH_FavBand; + return S_OK; +} + + +// *** IPersistStream *** + +STDMETHODIMP CFavBand::IsDirty() +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::Load(IStream *pStm) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::Save(IStream *pStm, BOOL fClearDirty) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::GetSizeMax(ULARGE_INTEGER *pcbSize) +{ + // TODO: calculate max size + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** IWinEventHandler *** + +STDMETHODIMP CFavBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::IsWindowOwner(HWND hWnd) +{ + return (hWnd == m_hWnd) ? S_OK : S_FALSE; +} + +// *** IBandNavigate *** + +STDMETHODIMP CFavBand::Select(long paramC) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** INamespaceProxy *** + +STDMETHODIMP CFavBand::GetNavigateTarget(long paramC, long param10, long param14) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::Invoke(long paramC) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::OnSelectionChanged(long paramC) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::RefreshFlags(long paramC, long param10, long param14) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::CacheItem(long paramC) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +// *** IDispatch *** + +STDMETHODIMP CFavBand::GetTypeInfoCount(UINT *pctinfo) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::GetIDsOfNames( + REFIID riid, + LPOLESTR *rgszNames, + UINT cNames, + LCID lcid, + DISPID *rgDispId) +{ + UNIMPLEMENTED; + return E_NOTIMPL; +} + +STDMETHODIMP CFavBand::Invoke( + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS *pDispParams, + VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, + UINT *puArgErr) +{ + switch (dispIdMember) + { + case DISPID_DOWNLOADCOMPLETE: + case DISPID_NAVIGATECOMPLETE2: + // FIXME: Update current location + return S_OK; + } + return E_INVALIDARG; +} + +BEGIN_OBJECT_MAP(ObjectMap) + OBJECT_ENTRY(CLSID_SH_FavBand, CFavBand) +END_OBJECT_MAP() + +class CFavBandModule : public CComModule +{ +public: +}; + +static CFavBandModule gModule; + +EXTERN_C VOID +CFavBand_Init(HINSTANCE hInstance) +{ + gModule.Init(ObjectMap, hInstance, NULL); +} + +EXTERN_C HRESULT +CFavBand_DllCanUnloadNow(VOID) +{ + return gModule.DllCanUnloadNow(); +} + +EXTERN_C HRESULT +CFavBand_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + return gModule.DllGetClassObject(rclsid, riid, ppv); +} + +EXTERN_C HRESULT +CFavBand_DllRegisterServer(VOID) +{ + return gModule.DllRegisterServer(FALSE); +} + +EXTERN_C HRESULT +CFavBand_DllUnregisterServer(VOID) +{ + return gModule.DllUnregisterServer(FALSE); +} diff --git a/dll/win32/shdocvw/CFavBand.h b/dll/win32/shdocvw/CFavBand.h new file mode 100644 index 00000000000..05b860251c3 --- /dev/null +++ b/dll/win32/shdocvw/CFavBand.h @@ -0,0 +1,183 @@ +/* + * PROJECT: ReactOS Explorer + * LICENSE: LGPL-2.1-or-later (https://spdx.org/licenses/LGPL-2.1-or-later) + * PURPOSE: Favorites bar + * COPYRIGHT: Copyright 2024 Katayama Hirofumi MZ + */ + +#pragma once + +EXTERN_C VOID CFavBand_Init(HINSTANCE hInstance); +EXTERN_C HRESULT CFavBand_DllCanUnloadNow(VOID); +EXTERN_C HRESULT CFavBand_DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv); +EXTERN_C HRESULT CFavBand_DllRegisterServer(VOID); +EXTERN_C HRESULT CFavBand_DllUnregisterServer(VOID); + +#define FAVBANDCLASSNAME L"ReactOS Favorites Band" + +#ifdef __cplusplus +class CFavBand + : public CComCoClass + , public CComObjectRootEx + , public CWindowImpl + , public IDispatch + , public IDeskBand + , public IObjectWithSite + , public IInputObject + , public IPersistStream + , public IOleCommandTarget + , public IServiceProvider + , public IContextMenu + , public IBandNavigate + , public IWinEventHandler + , public INamespaceProxy +{ +public: + DECLARE_WND_CLASS_EX(FAVBANDCLASSNAME, 0, COLOR_3DFACE) + static LPCWSTR GetWndClassName() { return FAVBANDCLASSNAME; } + + CFavBand(); + virtual ~CFavBand(); + + // *** IOleWindow methods *** + STDMETHODIMP GetWindow(HWND *lphwnd) override; + STDMETHODIMP ContextSensitiveHelp(BOOL fEnterMode) override; + + // *** IDockingWindow methods *** + STDMETHODIMP CloseDW(DWORD dwReserved) override; + STDMETHODIMP ResizeBorderDW(const RECT *prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) override; + STDMETHODIMP ShowDW(BOOL fShow) override; + + // *** IDeskBand methods *** + STDMETHODIMP GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi) override; + + // *** IObjectWithSite methods *** + STDMETHODIMP SetSite(IUnknown *pUnkSite) override; + STDMETHODIMP GetSite(REFIID riid, void **ppvSite) override; + + // *** IOleCommandTarget methods *** + STDMETHODIMP QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) override; + STDMETHODIMP Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) override; + + // *** IServiceProvider methods *** + STDMETHODIMP QueryService(REFGUID guidService, REFIID riid, void **ppvObject) override; + + // *** IContextMenu methods *** + STDMETHODIMP QueryContextMenu( + HMENU hmenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags) override; + STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO lpici) override; + STDMETHODIMP GetCommandString( + UINT_PTR idCmd, + UINT uType, + UINT *pwReserved, + LPSTR pszName, + UINT cchMax) override; + + // *** IInputObject methods *** + STDMETHODIMP UIActivateIO(BOOL fActivate, LPMSG lpMsg) override; + STDMETHODIMP HasFocusIO() override; + STDMETHODIMP TranslateAcceleratorIO(LPMSG lpMsg) override; + + // *** IPersist methods *** + STDMETHODIMP GetClassID(CLSID *pClassID) override; + + // *** IPersistStream methods *** + STDMETHODIMP IsDirty() override; + STDMETHODIMP Load(IStream *pStm) override; + STDMETHODIMP Save(IStream *pStm, BOOL fClearDirty) override; + STDMETHODIMP GetSizeMax(ULARGE_INTEGER *pcbSize) override; + + // *** IWinEventHandler methods *** + STDMETHODIMP OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) override; + STDMETHODIMP IsWindowOwner(HWND hWnd) override; + + // *** IBandNavigate methods *** + STDMETHODIMP Select(long paramC) override; + + // *** INamespaceProxy methods *** + STDMETHODIMP GetNavigateTarget(long paramC, long param10, long param14) override; + STDMETHODIMP Invoke(long paramC) override; + STDMETHODIMP OnSelectionChanged(long paramC) override; + STDMETHODIMP RefreshFlags(long paramC, long param10, long param14) override; + STDMETHODIMP CacheItem(long paramC) override; + + // *** IDispatch methods *** + STDMETHODIMP GetTypeInfoCount(UINT *pctinfo) override; + STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo) override; + STDMETHODIMP GetIDsOfNames( + REFIID riid, + LPOLESTR *rgszNames, + UINT cNames, + LCID lcid, + DISPID *rgDispId) override; + STDMETHODIMP Invoke( + DISPID dispIdMember, + REFIID riid, + LCID lcid, + WORD wFlags, + DISPPARAMS *pDispParams, + VARIANT *pVarResult, + EXCEPINFO *pExcepInfo, + UINT *puArgErr) override; + + DECLARE_REGISTRY_RESOURCEID(IDR_FAVBAND) + DECLARE_NOT_AGGREGATABLE(CFavBand) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CFavBand) + COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch) + COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand) + COM_INTERFACE_ENTRY2_IID(IID_IDockingWindow, IDockingWindow, IDeskBand) + COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand) + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject) + COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) + COM_INTERFACE_ENTRY2_IID(IID_IPersist, IPersist, IPersistStream) + COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + COM_INTERFACE_ENTRY2_IID(IID_IUnknown, IUnknown, IContextMenu) + COM_INTERFACE_ENTRY_IID(IID_IBandNavigate, IBandNavigate) + COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) + COM_INTERFACE_ENTRY_IID(IID_INamespaceProxy, INamespaceProxy) + END_COM_MAP() + + BEGIN_MSG_MAP(CFavBand) + MESSAGE_HANDLER(WM_CREATE, OnCreate) + MESSAGE_HANDLER(WM_DESTROY, OnDestroy) + MESSAGE_HANDLER(WM_SIZE, OnSize) + MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus) + MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus) + MESSAGE_HANDLER(WM_COMMAND, OnCommand) + END_MSG_MAP() + +protected: + BOOL m_fVisible; + BOOL m_bFocused; + DWORD m_dwBandID; + CComPtr m_pSite; + CComHeapPtr m_pidlFav; + HIMAGELIST m_hToolbarImageList; + HIMAGELIST m_hTreeViewImageList; + CToolbar<> m_hwndToolbar; + CTreeView m_hwndTreeView; + + VOID OnFinalMessage(HWND) override; + + // *** helper methods *** + BOOL CreateToolbar(); + BOOL CreateTreeView(); + + // *** message handlers *** + LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); + LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled); +}; +#endif // def __cplusplus diff --git a/dll/win32/shdocvw/CMakeLists.txt b/dll/win32/shdocvw/CMakeLists.txt index 5d25b402784..6110906a268 100644 --- a/dll/win32/shdocvw/CMakeLists.txt +++ b/dll/win32/shdocvw/CMakeLists.txt @@ -1,9 +1,7 @@ add_definitions( - -D__WINESRC__ -D_SHDOCVW_) -include_directories(${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine) spec2def(shdocvw.dll shdocvw.spec ADD_IMPORTLIB) list(APPEND SOURCE @@ -19,12 +17,23 @@ add_library(shdocvw MODULE ${SOURCE} mrulist.cpp shdocvw.rc + $ ${CMAKE_CURRENT_BINARY_DIR}/shdocvw.def) -set_module_type(shdocvw win32dll) +target_include_directories(shdocvw BEFORE PRIVATE + ${REACTOS_SOURCE_DIR}/sdk/include/reactos/wine +) + +set_module_type(shdocvw win32dll UNICODE) target_link_libraries(shdocvw uuid wine) -add_delay_importlibs(shdocvw shell32 ole32 oleaut32 ieframe) -add_importlibs(shdocvw shlwapi advapi32 msvcrt kernel32 ntdll) +add_delay_importlibs(shdocvw shell32 user32 gdi32 ole32 oleaut32 ieframe) +add_importlibs(shdocvw shlwapi advapi32 msvcrt comctl32 kernel32 ntdll) add_dependencies(shdocvw stdole2) add_pch(shdocvw precomp.h SOURCE) add_cd_file(TARGET shdocvw DESTINATION reactos/system32 FOR all) + +add_library(shdocvw_sublib OBJECT CFavBand.cpp) +target_link_libraries(shdocvw_sublib PRIVATE atl_classes) +target_compile_definitions(shdocvw_sublib PRIVATE $) +target_compile_options(shdocvw_sublib PRIVATE $) +add_dependencies(shdocvw_sublib psdk) diff --git a/dll/win32/shdocvw/favband.rgs b/dll/win32/shdocvw/favband.rgs new file mode 100644 index 00000000000..839af9e4963 --- /dev/null +++ b/dll/win32/shdocvw/favband.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {EFA24E61-B078-11D0-89E4-00C04FC9E26E} = s 'Favorites Band' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + } + } +} diff --git a/dll/win32/shdocvw/lang/en-US.rc b/dll/win32/shdocvw/lang/en-US.rc new file mode 100644 index 00000000000..a5691c65715 --- /dev/null +++ b/dll/win32/shdocvw/lang/en-US.rc @@ -0,0 +1,8 @@ + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +STRINGTABLE +BEGIN + IDS_ADD "Add" + IDS_ORGANIZE "Organize" +END diff --git a/dll/win32/shdocvw/resource.h b/dll/win32/shdocvw/resource.h new file mode 100644 index 00000000000..b7c1b8f1d0e --- /dev/null +++ b/dll/win32/shdocvw/resource.h @@ -0,0 +1,12 @@ +#define IDR_SHDOCVW 1 +#define IDR_FAVBAND 2 +#define IDR_TYPELIB 1 + +#define IDW_TOOLBAR 2 +#define IDW_TREEVIEW 100 + +#define ID_ADD 100 +#define ID_ORGANIZE 101 + +#define IDS_ADD 1000 +#define IDS_ORGANIZE 1001 diff --git a/dll/win32/shdocvw/shdocvw.h b/dll/win32/shdocvw/shdocvw.h index 4569fe7e171..5119561691d 100644 --- a/dll/win32/shdocvw/shdocvw.h +++ b/dll/win32/shdocvw/shdocvw.h @@ -60,9 +60,17 @@ static inline void SHDOCVW_LockModule(void) { InterlockedIncrement( &SHDOCVW_ref static inline void SHDOCVW_UnlockModule(void) { InterlockedDecrement( &SHDOCVW_refCount ); } #ifdef __REACTOS__ +#include "resource.h" EXTERN_C HRESULT CMruLongList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3); EXTERN_C HRESULT CMruPidlList_CreateInstance(DWORD_PTR dwUnused1, void **ppv, DWORD_PTR dwUnused3); EXTERN_C HRESULT CMruClassFactory_CreateInstance(REFIID riid, void **ppv); +#define ARRAY_SIZE(array) _countof(array) +#ifdef __cplusplus +void *operator new(size_t size); +void operator delete(void *ptr); +void operator delete(void *ptr, size_t size); #endif +EXTERN_C HINSTANCE instance; +#endif // def __REACTOS__ #endif /* __WINE_SHDOCVW_H */ diff --git a/dll/win32/shdocvw/shdocvw.rc b/dll/win32/shdocvw/shdocvw.rc index b262a8d3cc6..4bbcdbd5889 100644 --- a/dll/win32/shdocvw/shdocvw.rc +++ b/dll/win32/shdocvw/shdocvw.rc @@ -17,10 +17,13 @@ */ #include "windef.h" +#include "resource.h" -1 WINE_REGISTRY "shdocvw_v1.rgs" +IDR_SHDOCVW WINE_REGISTRY "shdocvw_v1.rgs" -1 TYPELIB "shdocvw_v1.tlb" +IDR_FAVBAND REGISTRY "favband.rgs" + +IDR_TYPELIB TYPELIB "shdocvw_v1.tlb" LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL @@ -33,3 +36,10 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL #define WINE_EXTRAVALUES VALUE "OLESelfRegister","" #include "wine/wine_common_ver.rc" + +/* UTF-8 */ +#pragma code_page(65001) + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif diff --git a/dll/win32/shdocvw/shdocvw_main.c b/dll/win32/shdocvw/shdocvw_main.c index 5994e88c58a..1dd0b88c4ad 100644 --- a/dll/win32/shdocvw/shdocvw_main.c +++ b/dll/win32/shdocvw/shdocvw_main.c @@ -32,6 +32,7 @@ #include "winnls.h" #include #include /* for __wine_register_resources / __wine_unregister_resources */ +#include "CFavBand.h" #endif #include "shlwapi.h" #include "wininet.h" @@ -46,7 +47,7 @@ LONG SHDOCVW_refCount = 0; static HMODULE SHDOCVW_hshell32 = 0; static HINSTANCE ieframe_instance; #ifdef __REACTOS__ -static HINSTANCE instance; +HINSTANCE instance; #endif static HINSTANCE get_ieframe_instance(void) @@ -93,6 +94,11 @@ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv) return get_ieframe_object(rclsid, riid, ppv); #ifdef __REACTOS__ + { + HRESULT hr = CFavBand_DllGetClassObject(rclsid, riid, ppv); + if (hr != CLASS_E_CLASSNOTAVAILABLE) + return hr; + } if (IsEqualGUID(riid, &IID_IClassFactory) || IsEqualGUID(riid, &IID_IUnknown)) { if (IsEqualGUID(rclsid, &CLSID_MruLongList) || @@ -122,6 +128,7 @@ HRESULT WINAPI DllRegisterServer(void) { TRACE("\n"); #ifdef __REACTOS__ + CFavBand_DllRegisterServer(); return __wine_register_resources(instance); #else return S_OK; @@ -135,6 +142,7 @@ HRESULT WINAPI DllUnregisterServer(void) { TRACE("\n"); #ifdef __REACTOS__ + CFavBand_DllUnregisterServer(); return __wine_unregister_resources(instance); #else return S_OK; @@ -181,6 +189,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad) case DLL_PROCESS_ATTACH: #ifdef __REACTOS__ instance = hinst; + CFavBand_Init(hinst); #endif DisableThreadLibraryCalls(hinst); break; @@ -198,6 +207,10 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID fImpLoad) */ HRESULT WINAPI DllCanUnloadNow(void) { +#ifdef __REACTOS__ + if (CFavBand_DllCanUnloadNow() != S_OK) + return S_FALSE; +#endif return SHDOCVW_refCount ? S_FALSE : S_OK; } diff --git a/dll/win32/shdocvw/shlinstobj.c b/dll/win32/shdocvw/shlinstobj.c index 189c27cad58..0049ed5129b 100644 --- a/dll/win32/shdocvw/shlinstobj.c +++ b/dll/win32/shdocvw/shlinstobj.c @@ -160,7 +160,11 @@ static HRESULT WINAPI RegistryPropertyBag_IPropertyBag_Write(IPropertyBag *iface return E_NOTIMPL; } +#ifdef __REACTOS__ +static IPropertyBagVtbl RegistryPropertyBag_IPropertyBagVtbl = { +#else static const IPropertyBagVtbl RegistryPropertyBag_IPropertyBagVtbl = { +#endif RegistryPropertyBag_IPropertyBag_QueryInterface, RegistryPropertyBag_IPropertyBag_AddRef, RegistryPropertyBag_IPropertyBag_Release, @@ -305,7 +309,11 @@ static HRESULT WINAPI InstanceObjectFactory_IClassFactory_LockServer(IClassFacto return S_OK; } +#ifdef __REACTOS__ +static IClassFactoryVtbl InstanceObjectFactory_IClassFactoryVtbl = { +#else static const IClassFactoryVtbl InstanceObjectFactory_IClassFactoryVtbl = { +#endif InstanceObjectFactory_IClassFactory_QueryInterface, InstanceObjectFactory_IClassFactory_AddRef, InstanceObjectFactory_IClassFactory_Release,