diff --git a/dll/shellext/CMakeLists.txt b/dll/shellext/CMakeLists.txt index 56fabe12999..2b5b3c6c652 100644 --- a/dll/shellext/CMakeLists.txt +++ b/dll/shellext/CMakeLists.txt @@ -6,5 +6,6 @@ add_subdirectory(devcpux) add_subdirectory(fontext) add_subdirectory(netshell) add_subdirectory(ntobjshex) +add_subdirectory(qcklnch) add_subdirectory(shellbtrfs) add_subdirectory(stobject) diff --git a/dll/shellext/qcklnch/CISFBand.cpp b/dll/shellext/qcklnch/CISFBand.cpp new file mode 100644 index 00000000000..34192b45d34 --- /dev/null +++ b/dll/shellext/qcklnch/CISFBand.cpp @@ -0,0 +1,587 @@ +/* + * PROJECT: ReactOS shell extensions + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/shellext/qcklnch/CISFBand.cpp + * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) + * PROGRAMMERS: Shriraj Sawant a.k.a SR13 + */ + +#include "precomp.h" +#include + +#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) +#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) + +WINE_DEFAULT_DEBUG_CHANNEL(qcklnch); + +// ***Extras*** +/*++ +* @name _ILIsDesktop +* +* Checks whether the given PIDL is of Desktop folder or not. +* +* @param pidl +* PIDL to be checked. +* +* @return True if PIDL is of Desktop, otherwise false. +* +*--*/ +BOOL WINAPI _ILIsDesktop(LPCITEMIDLIST pidl) +{ + return (pidl == NULL || pidl->mkid.cb == 0); +} + +//***************************************************************************************** +// *** CISFBand *** + +CISFBand::CISFBand() : + m_BandID(0), + m_pidl(NULL), + m_textFlag(true), + m_iconFlag(true) +{ +} + +CISFBand::~CISFBand() +{ + CloseDW(0); +} + +// Toolbar +/*++ +* @name CreateSimpleToolbar +* +* Creates a toolbar and fills it up with buttons for enumerated objects. +* +* @param hWndParent +* Handle to the parent window, which receives the appropriate messages from child toolbar. +* +* @return The error code. +* +*--*/ +HRESULT CISFBand::CreateSimpleToolbar(HWND hWndParent) +{ + // Declare and initialize local constants. + const DWORD buttonStyles = BTNS_AUTOSIZE; + + // Create the toolbar. + m_hWnd = CreateWindowEx(0, TOOLBARCLASSNAME, NULL, + WS_CHILD | TBSTYLE_FLAT | TBSTYLE_LIST | CCS_NORESIZE | CCS_NODIVIDER, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, + hWndParent, NULL, 0, NULL); + if (m_hWnd == NULL) + return E_FAIL; + + // Set the image list. + HIMAGELIST* piml; + HRESULT hr = SHGetImageList(SHIL_SMALL, IID_IImageList, (void**)&piml); + if (FAILED_UNEXPECTEDLY(hr)) + { + DestroyWindow(); + return hr; + } + SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)piml); + + // Enumerate objects + CComPtr pEndl; + LPITEMIDLIST pidl; + STRRET stret; + hr = m_pISF->EnumObjects(0, SHCONTF_FOLDERS, &pEndl); + if (FAILED_UNEXPECTEDLY(hr)) + { + DestroyWindow(); + return hr; + } + + for (int i=0; pEndl->Next(1, &pidl, NULL) != S_FALSE; i++) + { + WCHAR sz[MAX_PATH]; + int index = SHMapPIDLToSystemImageListIndex(m_pISF, pidl, NULL); + hr = m_pISF->GetDisplayNameOf(pidl, SHGDN_NORMAL, &stret); + if (FAILED_UNEXPECTEDLY(hr)) + { + strcpyW(sz, L""); + } + else + StrRetToBuf(&stret, pidl, sz, _countof(sz)); + + TBBUTTON tb = { MAKELONG(index, 0), i, TBSTATE_ENABLED, buttonStyles,{ 0 }, (DWORD_PTR)pidl, (INT_PTR)sz }; + SendMessage(m_hWnd, TB_INSERTBUTTONW, i, (LPARAM)&tb); + } + + // Resize the toolbar, and then show it. + SendMessage(m_hWnd, TB_AUTOSIZE, 0, 0); + + return hr; +} + +/*****************************************************************************/ + +// *** IObjectWithSite *** + STDMETHODIMP CISFBand::SetSite(IUnknown *pUnkSite) + { + HRESULT hr; + HWND hwndParent; + + TRACE("CISFBand::SetSite(0x%p)\n", pUnkSite); + + hr = IUnknown_GetWindow(pUnkSite, &hwndParent); + if (FAILED(hr)) + { + TRACE("Querying site window failed: 0x%x\n", hr); + return hr; + } + m_Site = pUnkSite; + + hr = CreateSimpleToolbar(hwndParent); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + return S_OK; + } + + STDMETHODIMP CISFBand::GetSite(IN REFIID riid, OUT VOID **ppvSite) + { + TRACE("CISFBand::GetSite(0x%p,0x%p)\n", riid, ppvSite); + + HRESULT hr; + if (m_Site != NULL) + { + hr = m_Site->QueryInterface(riid, ppvSite); + if (FAILED(hr)) return hr; + } + + *ppvSite = NULL; + return E_FAIL; + } + +/*****************************************************************************/ +// *** IDeskBand *** + STDMETHODIMP CISFBand::GetWindow(OUT HWND *phwnd) + { + if (!m_hWnd) + return E_FAIL; + if (!phwnd) + return E_POINTER; + *phwnd = m_hWnd; + + return S_OK; + } + + STDMETHODIMP CISFBand::ContextSensitiveHelp(IN BOOL fEnterMode) + { + /* FIXME: Implement */ + return E_NOTIMPL; + } + + STDMETHODIMP CISFBand::ShowDW(IN BOOL bShow) + { + if (m_hWnd) + { + ShowWindow(bShow ? SW_SHOW : SW_HIDE); + return S_OK; + } + + return E_FAIL; + } + + STDMETHODIMP CISFBand::CloseDW(IN DWORD dwReserved) + { + if (m_hWnd) + { + ShowWindow(SW_HIDE); + + TBBUTTON tb; + for (int i = 0; SendMessage(m_hWnd, TB_GETBUTTON, i, (LPARAM)&tb); i++) + { + CoTaskMemFree((LPITEMIDLIST)tb.dwData); + } + + DestroyWindow(); + m_hWnd = NULL; + return S_OK; + } + + return E_FAIL; + } + + STDMETHODIMP CISFBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) + { + /* No need to implement this method */ + + return E_NOTIMPL; + } + + STDMETHODIMP CISFBand::GetBandInfo(IN DWORD dwBandID, IN DWORD dwViewMode, IN OUT DESKBANDINFO *pdbi) + { + TRACE("CTaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, m_hWnd); + + if (m_hWnd && pdbi) + { + m_BandID = dwBandID; + + RECT actualRect; + POINTL actualSize; + POINTL idealSize; + POINTL maxSize; + POINTL itemSize; + + GetWindowRect(&actualRect); + actualSize.x = actualRect.right - actualRect.left; + actualSize.y = actualRect.bottom - actualRect.top; + + // Obtain the ideal size, to be used as min and max + SendMessageW(m_hWnd, TB_AUTOSIZE, 0, 0); + SendMessageW(m_hWnd, TB_GETMAXSIZE, 0, reinterpret_cast(&maxSize)); + + idealSize = maxSize; + SendMessageW(m_hWnd, TB_GETIDEALSIZE, FALSE, reinterpret_cast(&idealSize)); + + // Obtain the button size, to be used as the integral size + DWORD size = SendMessageW(m_hWnd, TB_GETBUTTONSIZE, 0, 0); + itemSize.x = GET_X_LPARAM(size); + itemSize.y = GET_Y_LPARAM(size); + + if (pdbi->dwMask & DBIM_MINSIZE) + { + pdbi->ptMinSize.x = -1; + pdbi->ptMinSize.y = idealSize.y; + } + if (pdbi->dwMask & DBIM_MAXSIZE) + { + pdbi->ptMaxSize = maxSize; + } + if (pdbi->dwMask & DBIM_INTEGRAL) + { + pdbi->ptIntegral = itemSize; + } + if (pdbi->dwMask & DBIM_ACTUAL) + { + pdbi->ptActual = actualSize; + } + if (pdbi->dwMask & DBIM_TITLE) + wcscpy(pdbi->wszTitle, L"Quick Launch"); + if (pdbi->dwMask & DBIM_MODEFLAGS) + { + pdbi->dwModeFlags = DBIMF_NORMAL | DBIMF_VARIABLEHEIGHT | DBIMF_USECHEVRON | DBIMF_NOMARGINS | DBIMF_BKCOLOR | DBIMF_ADDTOFRONT; + } + if (pdbi->dwMask & DBIM_BKCOLOR) + pdbi->dwMask &= ~DBIM_BKCOLOR; + + return S_OK; + } + + return E_FAIL; + } + +/*****************************************************************************/ +// *** IPersistStream *** + STDMETHODIMP CISFBand::GetClassID(OUT CLSID *pClassID) + { + TRACE("CISFBand::GetClassID(0x%p)\n", pClassID); + /* We're going to return the (internal!) CLSID of the quick launch band */ + *pClassID = CLSID_QuickLaunchBand; + + return S_OK; + } + + STDMETHODIMP CISFBand::IsDirty() + { + /* The object hasn't changed since the last save! */ + + return S_FALSE; + } + + STDMETHODIMP CISFBand::Load(IN IStream *pStm) + { + TRACE("CISFBand::Load called\n"); + /* Nothing to do */ + + return S_OK; + } + + STDMETHODIMP CISFBand::Save(IN IStream *pStm, IN BOOL fClearDirty) + { + /* Nothing to do */ + + return S_OK; + } + + STDMETHODIMP CISFBand::GetSizeMax(OUT ULARGE_INTEGER *pcbSize) + { + TRACE("CISFBand::GetSizeMax called\n"); + + return S_OK; + } + +/*****************************************************************************/ +// *** IWinEventHandler *** + STDMETHODIMP CISFBand::ContainsWindow(IN HWND hWnd) + { + if (hWnd == m_hWnd || IsChild(hWnd)) + { + TRACE("CISFBand::ContainsWindow(0x%p) returns S_OK\n", hWnd); + return S_OK; + } + + return S_FALSE; + } + + STDMETHODIMP CISFBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) + { + switch (uMsg) + { + case WM_COMMAND: + { + TBBUTTON tb; + bool chk = SendMessage(m_hWnd, TB_GETBUTTON, LOWORD(wParam), (LPARAM)&tb); + if (chk) + SHInvokeDefaultCommand(m_hWnd, m_pISF, (LPITEMIDLIST)tb.dwData); + + *theResult = TRUE; + break; + } + case WM_NOTIFY: + { + switch (((LPNMHDR)lParam)->code) + { + case NM_RCLICK: + { + HRESULT hr; + POINT pt = ((LPNMMOUSE)lParam)->pt; + CComPtr picm; + HMENU fmenu = CreatePopupMenu(); + TBBUTTON tb; + + bool chk = SendMessage(m_hWnd, TB_GETBUTTON, ((LPNMMOUSE)lParam)->dwItemSpec, (LPARAM)&tb); + LPITEMIDLIST pidl = (LPITEMIDLIST)tb.dwData; + + if (chk) + { + ClientToScreen(&pt); + hr = m_pISF->GetUIObjectOf(m_hWnd, 1, &pidl, IID_NULL_PPV_ARG(IContextMenu, &picm)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + hr = picm->QueryContextMenu(fmenu, 0, 1, 0x7FFF, CMF_DEFAULTONLY); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + int id = TrackPopupMenuEx(fmenu, TPM_LEFTALIGN | TPM_BOTTOMALIGN | TPM_RETURNCMD, pt.x, pt.y, m_hWnd, 0); + if (id > 0) + { + CMINVOKECOMMANDINFOEX info = { 0 }; + info.cbSize = sizeof(info); + info.fMask = CMIC_MASK_PTINVOKE; + if (GetKeyState(VK_CONTROL) < 0) + { + info.fMask |= CMIC_MASK_CONTROL_DOWN; + } + if (GetKeyState(VK_SHIFT) < 0) + { + info.fMask |= CMIC_MASK_SHIFT_DOWN; + } + info.hwnd = m_hWnd; + info.lpVerb = MAKEINTRESOURCEA(id - 1); + info.nShow = SW_SHOWNORMAL; + info.ptInvoke = pt; + picm->InvokeCommand((LPCMINVOKECOMMANDINFO)&info); + } + } + DestroyMenu(fmenu); + + *theResult = TRUE; + break; + } + default: + *theResult = FALSE; + } + + break; + } + default: + *theResult = FALSE; + } + + return S_OK; + } + + STDMETHODIMP CISFBand::IsWindowOwner(HWND hWnd) + { + return (hWnd == m_hWnd) ? S_OK : S_FALSE; + } + +/*****************************************************************************/ +// *** IOleCommandTarget methods *** + STDMETHODIMP CISFBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) + { + UNIMPLEMENTED; + + return E_NOTIMPL; + } + + STDMETHODIMP CISFBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) + { + if (IsEqualIID(*pguidCmdGroup, IID_IBandSite)) + { + return S_OK; + } + + if (IsEqualIID(*pguidCmdGroup, IID_IDeskBand)) + { + return S_OK; + } + + UNIMPLEMENTED; + + return E_NOTIMPL; + } + +/*****************************************************************************/ +// *** IShellFolderBand *** + STDMETHODIMP CISFBand::GetBandInfoSFB(PBANDINFOSFB pbi) + { + return E_NOTIMPL; + } + + STDMETHODIMP CISFBand::InitializeSFB(IShellFolder *psf, PCIDLIST_ABSOLUTE pidl) + { + if (_ILIsDesktop(pidl)) + { + m_pISF = psf; + m_pidl = ILClone(pidl); + } + else + { + psf->BindToObject(pidl, 0, IID_PPV_ARG(IShellFolder, &m_pISF)); + m_pidl = ILClone(pidl); + } + + return S_OK; + } + + STDMETHODIMP CISFBand::SetBandInfoSFB( PBANDINFOSFB pbi) + { + return E_NOTIMPL; + } + +/*****************************************************************************/ +// *** IContextMenu *** + STDMETHODIMP CISFBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) + { + /*HRESULT hr = E_INVALIDARG; + + if (idCmd == IDM_DISPLAY) + { + switch (uFlags) + { + case GCS_HELPTEXTW: + // Only useful for pre-Vista versions of Windows that + // have a Status bar. + hr = StringCchCopyW(reinterpret_cast(pszName), + cchMax, + L"Display File Name"); + break; + + case GCS_VERBW: + // GCS_VERBW is an optional feature that enables a caller + // to discover the canonical name for the verb that is passed in + // through idCommand. + hr = StringCchCopyW(reinterpret_cast(pszName), + cchMax, + L"DisplayFileName"); + break; + } + } + return hr; */ + + return S_OK; + } + + STDMETHODIMP CISFBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici) + { + if (!HIWORD(pici->lpVerb)) + { + switch (LOWORD(pici->lpVerb)) + { + case IDM_LARGE_ICONS: + { + m_iconFlag = false; + + HIMAGELIST* piml = (HIMAGELIST*) SendMessage(m_hWnd, TB_GETIMAGELIST, 0, 0); + HRESULT hr = SHGetImageList(SHIL_LARGE, IID_IImageList, (void**)&piml); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)piml); + hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + break; + } + case IDM_SMALL_ICONS: + { + m_iconFlag = true; + + HIMAGELIST* piml = (HIMAGELIST*)SendMessage(m_hWnd, TB_GETIMAGELIST, 0, 0); + HRESULT hr = SHGetImageList(SHIL_SMALL, IID_IImageList, (void**)&piml); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + SendMessage(m_hWnd, TB_SETIMAGELIST, 0, (LPARAM)piml); + hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + break; + } + case IDM_SHOW_TEXT: + { + if (m_textFlag) + { + m_textFlag = false; + SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_MIXEDBUTTONS); + HRESULT hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + } + else + { + m_textFlag = true; + SendMessage(m_hWnd, TB_SETEXTENDEDSTYLE, 0, 0); + HRESULT hr = IUnknown_Exec(m_Site, IID_IDeskBand, DBID_BANDINFOCHANGED, 0, NULL, NULL); + if (FAILED_UNEXPECTEDLY(hr)) return hr; + } + break; + } + default: + return E_FAIL; + } + } + + return S_OK; + } + + STDMETHODIMP CISFBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) + { + HMENU qMenu = LoadMenu(_AtlBaseModule.GetResourceInstance(), MAKEINTRESOURCE(IDM_POPUPMENU)); + if(m_textFlag) + CheckMenuItem(qMenu, IDM_SHOW_TEXT, MF_CHECKED); + else + CheckMenuItem(qMenu, IDM_SHOW_TEXT, MF_UNCHECKED); + + if (m_iconFlag) + { + CheckMenuItem(qMenu, IDM_SMALL_ICONS, MF_CHECKED); + CheckMenuItem(qMenu, IDM_LARGE_ICONS, MF_UNCHECKED); + } + else + { + CheckMenuItem(qMenu, IDM_LARGE_ICONS, MF_CHECKED); + CheckMenuItem(qMenu, IDM_SMALL_ICONS, MF_UNCHECKED); + } + + UINT idMax = Shell_MergeMenus(hmenu, GetSubMenu(qMenu, 0), indexMenu, idCmdFirst, idCmdLast, MM_SUBMENUSHAVEIDS); + DestroyMenu(qMenu); + return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(idMax - idCmdFirst +1)); + } + +/*****************************************************************************/ +// C Constructor + extern "C" + HRESULT WINAPI CISFBand_CreateInstance(REFIID riid, void** ppv) + { + return ShellObjectCreator(riid, ppv); + } + diff --git a/dll/shellext/qcklnch/CISFBand.h b/dll/shellext/qcklnch/CISFBand.h new file mode 100644 index 00000000000..fc74db0b7c0 --- /dev/null +++ b/dll/shellext/qcklnch/CISFBand.h @@ -0,0 +1,196 @@ +/* + * PROJECT: ReactOS shell extensions + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/shellext/qcklnch/CISFBand.h + * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) + * PROGRAMMERS: Shriraj Sawant a.k.a SR13 + */ +#pragma once + +// COM class for cisfband +class CISFBand : + public CWindow, + public CComCoClass, + public CComObjectRootEx, + public IObjectWithSite, + public IDeskBand, + public IPersistStream, + public IWinEventHandler, + public IOleCommandTarget, + public IShellFolderBand, + public IContextMenu +{ + // Band + DWORD m_BandID; + CComPtr m_Site; + + // Toolbar + CComPtr m_pISF; + PCIDLIST_ABSOLUTE m_pidl; + + // Menu + BOOL m_textFlag; + BOOL m_iconFlag; + +public: + + CISFBand(); + virtual ~CISFBand(); + +// Personal Methods + HRESULT CreateSimpleToolbar(HWND hWndParent); + +// IObjectWithSite + + virtual STDMETHODIMP GetSite( + IN REFIID riid, + OUT void **ppvSite + ); + + virtual STDMETHODIMP SetSite( + IN IUnknown *pUnkSite + ); + +// IDeskBand + + virtual STDMETHODIMP GetWindow( + OUT HWND *phwnd + ); + + virtual STDMETHODIMP ContextSensitiveHelp( + IN BOOL fEnterMode + ); + + virtual STDMETHODIMP ShowDW( + IN BOOL bShow + ); + + virtual STDMETHODIMP CloseDW( + IN DWORD dwReserved + ); + + virtual STDMETHODIMP ResizeBorderDW( + LPCRECT prcBorder, + IUnknown *punkToolbarSite, + BOOL fReserved + ); + + virtual STDMETHODIMP GetBandInfo( + IN DWORD dwBandID, + IN DWORD dwViewMode, + IN OUT DESKBANDINFO *pdbi + ); + +// IPersistStream + + virtual STDMETHODIMP GetClassID( + OUT CLSID *pClassID + ); + + virtual STDMETHODIMP GetSizeMax( + OUT ULARGE_INTEGER *pcbSize + ); + + virtual STDMETHODIMP IsDirty(); + + virtual STDMETHODIMP Load( + IN IStream *pStm + ); + + virtual STDMETHODIMP Save( + IN IStream *pStm, + IN BOOL fClearDirty + ); + +// IWinEventHandler + + virtual STDMETHODIMP ContainsWindow( + IN HWND hWnd + ); + + virtual STDMETHODIMP OnWinEvent( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT *theResult + ); + + virtual STDMETHODIMP IsWindowOwner( + HWND hWnd + ); + +// IOleCommandTarget + + virtual STDMETHODIMP Exec( + IN const GUID *pguidCmdGroup, + IN DWORD nCmdID, + IN DWORD nCmdexecopt, + IN VARIANT *pvaIn, + IN OUT VARIANT *pvaOut + ); + + virtual STDMETHODIMP QueryStatus( + IN const GUID *pguidCmdGroup, + IN ULONG cCmds, + IN OUT OLECMD prgCmds[], + IN OUT OLECMDTEXT *pCmdText + ); + +// IShellFolderBand + virtual STDMETHODIMP GetBandInfoSFB( + PBANDINFOSFB pbi + ); + + virtual STDMETHODIMP InitializeSFB( + IShellFolder *psf, + PCIDLIST_ABSOLUTE pidl + ); + + virtual STDMETHODIMP SetBandInfoSFB( + PBANDINFOSFB pbi + ); + +// IContextMenu + virtual STDMETHODIMP GetCommandString( + UINT_PTR idCmd, + UINT uFlags, + UINT *pwReserved, + LPSTR pszName, + UINT cchMax + ); + + virtual STDMETHODIMP InvokeCommand( + LPCMINVOKECOMMANDINFO pici + ); + + virtual STDMETHODIMP QueryContextMenu( + HMENU hmenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags + ); + +//***************************************************************************************************** + + DECLARE_NOT_AGGREGATABLE(CISFBand) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CISFBand) + COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand) + COM_INTERFACE_ENTRY2_IID(IID_IDockingWindow, IDockingWindow, IDeskBand) + COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand) + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) + COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) + COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + COM_INTERFACE_ENTRY_IID(IID_IShellFolderBand, IShellFolderBand) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + END_COM_MAP() +}; + +// C Constructor +extern "C" +HRESULT WINAPI CISFBand_CreateInstance(REFIID riid, void** ppv); \ No newline at end of file diff --git a/dll/shellext/qcklnch/CMakeLists.txt b/dll/shellext/qcklnch/CMakeLists.txt new file mode 100644 index 00000000000..bcc921891d6 --- /dev/null +++ b/dll/shellext/qcklnch/CMakeLists.txt @@ -0,0 +1,43 @@ + +project(SHELL) + +set_cpp(WITH_RUNTIME) + +if(NOT MSVC) + # HACK: this should be enabled globally! + add_compile_flags_language("-std=c++11" "CXX") +endif() + +include_directories( + ${REACTOS_SOURCE_DIR}/sdk/lib/atl + ${REACTOS_SOURCE_DIR}) + +spec2def(qcklnch.dll qcklnch.spec) + +add_library(qcklnch SHARED + qcklnch.rc + qcklnch.cpp + CQuickLaunchBand.cpp + CISFBand.cpp + CQuickLaunchBand.h + CISFBand.h + ${CMAKE_CURRENT_BINARY_DIR}/qcklnch.def) + +set_module_type(qcklnch win32dll UNICODE) +target_link_libraries(qcklnch uuid wine atlnew) + +add_importlibs(qcklnch + advapi32 + winmm + ole32 + oleaut32 + shlwapi + shell32 + comctl32 + msvcrt + gdi32 + user32 + kernel32 + ntdll) + +add_cd_file(TARGET qcklnch DESTINATION reactos/system32 FOR all) diff --git a/dll/shellext/qcklnch/CQuickLaunchBand.cpp b/dll/shellext/qcklnch/CQuickLaunchBand.cpp new file mode 100644 index 00000000000..d250a3c5cae --- /dev/null +++ b/dll/shellext/qcklnch/CQuickLaunchBand.cpp @@ -0,0 +1,361 @@ +/* + * PROJECT: ReactOS shell extensions + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/shellext/qcklnch/CQuickLaunchBand.cpp + * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) + * PROGRAMMERS: Shriraj Sawant a.k.a SR13 + */ + +#include "precomp.h" + +WINE_DEFAULT_DEBUG_CHANNEL(qcklnch); + +// {260CB95D-4544-44F6-A079-575BAA60B72F} +static const GUID CLSID_QuickLaunchBand = { 0x260cb95d, 0x4544, 0x44f6, { 0xa0, 0x79, 0x57, 0x5b, 0xaa, 0x60, 0xb7, 0x2f } }; + +// Componenet Category Registration + HRESULT RegisterComCat() + { + CComPtr pcr; + HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICatRegister, &pcr)); + if (SUCCEEDED(hr)) + { + CATID catid = CATID_DeskBand; + hr = pcr->RegisterClassImplCategories(CLSID_QuickLaunchBand, 1, &catid); + } + return hr; + } + + HRESULT UnregisterComCat() + { + CComPtr pcr; + HRESULT hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(ICatRegister, &pcr)); + if (SUCCEEDED(hr)) + { + CATID catid = CATID_DeskBand; + hr = pcr->UnRegisterClassImplCategories(CLSID_QuickLaunchBand, 1, &catid); + } + return hr; + } + +// Pidl Browser +/*++ +* @name PidlBrowse +* +* Opens a folder browser dialog, +* allowing the user to select a folder for enumeration. +* +* @param hwnd +* A handle to browser dialog window. +* @param nCSIDL +* A CSIDL representing the root from which the browse folder dialog shows the files and folders. +* +* @return The PIDL to selected folder. +* +*--*/ + LPITEMIDLIST PidlBrowse(HWND hwnd, int nCSIDL) + { + CComHeapPtr pidlRoot; + + WCHAR path[MAX_PATH]; + + if (nCSIDL) + { + SHGetSpecialFolderLocation(hwnd, nCSIDL, &pidlRoot); + } + + CString biTitle((LPCSTR)IDS_BROWSEINFO_TITLE); + BROWSEINFO bi = { hwnd, pidlRoot, path, biTitle, 0, NULL, 0, 0 }; + LPITEMIDLIST pidlSelected = SHBrowseForFolder(&bi); + + return pidlSelected; + } + +// CQuickLaunchBand + + CQuickLaunchBand::CQuickLaunchBand() {} + + CQuickLaunchBand::~CQuickLaunchBand() {} + +/*****************************************************************************/ +// ATL Construct +/*++ +* @name FinalConstruct +* +* Creates an instance of CISFBand, and initializes its Shell Folder Band for enumeration. +* +* @return The error code. +* +*--*/ + HRESULT CQuickLaunchBand::FinalConstruct() + { + HRESULT hr = CISFBand_CreateInstance(IID_PPV_ARG(IUnknown, &m_punkISFB)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + CComPtr pISFB; + hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IShellFolderBand, &pISFB)); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + CComPtr pISF; + hr = SHGetDesktopFolder(&pISF); + if (FAILED_UNEXPECTEDLY(hr)) + return hr; + + CComHeapPtr pidl(PidlBrowse(m_hWndBro, CSIDL_DESKTOP)); + if (pidl == NULL) + return E_FAIL; + pISFB->InitializeSFB(pISF, pidl); + + return hr; + } + +// IObjectWithSite + STDMETHODIMP CQuickLaunchBand::SetSite(IUnknown *pUnkSite) + { + TRACE("CQuickLaunchBand::SetSite(0x%p)\n", pUnkSite); + + // Internal CISFBand Calls + CComPtr pIOWS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pIOWS)); + if (FAILED(hr)) + return hr; + + return pIOWS->SetSite(pUnkSite); + } + + STDMETHODIMP CQuickLaunchBand::GetSite(IN REFIID riid, OUT VOID **ppvSite) + { + TRACE("CQuickLaunchBand::GetSite(0x%p,0x%p)\n", riid, ppvSite); + + // Internal CISFBand Calls + CComPtr pIOWS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pIOWS)); + if (FAILED(hr)) + return hr; + + return pIOWS->GetSite(riid, ppvSite); + } + +/*****************************************************************************/ +// IDeskBand + STDMETHODIMP CQuickLaunchBand::GetWindow(OUT HWND *phwnd) + { + // Internal CISFBand Calls + CComPtr pIDB; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); + if (FAILED(hr)) + return hr; + + return pIDB->GetWindow(phwnd); + } + + STDMETHODIMP CQuickLaunchBand::ContextSensitiveHelp(IN BOOL fEnterMode) + { + // Internal CISFBand Calls + CComPtr pIDB; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); + if (FAILED(hr)) + return hr; + + return pIDB->ContextSensitiveHelp(fEnterMode); + } + + STDMETHODIMP CQuickLaunchBand::ShowDW(IN BOOL bShow) + { + // Internal CISFBand Calls + CComPtr pIDB; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); + if (FAILED(hr)) + return hr; + + return pIDB->ShowDW(bShow); + } + + STDMETHODIMP CQuickLaunchBand::CloseDW(IN DWORD dwReserved) + { + // Internal CISFBand Calls + CComPtr pIDB; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); + if (FAILED(hr)) + return hr; + + return pIDB->CloseDW(dwReserved); + } + + STDMETHODIMP CQuickLaunchBand::ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved) + { + // Internal CISFBand Calls + CComPtr pIDB; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); + if (FAILED(hr)) + return hr; + + return pIDB->ResizeBorderDW(prcBorder, punkToolbarSite, fReserved); + } + + STDMETHODIMP CQuickLaunchBand::GetBandInfo(IN DWORD dwBandID, IN DWORD dwViewMode, IN OUT DESKBANDINFO *pdbi) + { + TRACE("CQuickLaunchBand::GetBandInfo(0x%x,0x%x,0x%p)\n", dwBandID, dwViewMode, pdbi); + + // Internal CISFBand Calls + CComPtr pIDB; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IDeskBand, &pIDB)); + if (FAILED(hr)) + return hr; + + return pIDB->GetBandInfo(dwBandID, dwViewMode, pdbi); + } + +/*****************************************************************************/ +// IPersistStream + STDMETHODIMP CQuickLaunchBand::GetClassID(OUT CLSID *pClassID) + { + TRACE("CQuickLaunchBand::GetClassID(0x%p)\n", pClassID); + + // Internal CISFBand Calls + CComPtr pIPS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); + if (FAILED(hr)) + return hr; + + return pIPS->GetClassID(pClassID); + } + + STDMETHODIMP CQuickLaunchBand::IsDirty() + { + // Internal CISFBand Calls + CComPtr pIPS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); + if (FAILED(hr)) + return hr; + + return pIPS->IsDirty(); + } + + STDMETHODIMP CQuickLaunchBand::Load(IN IStream *pStm) + { + TRACE("CQuickLaunchBand::Load called\n"); + + // Internal CISFBand Calls + CComPtr pIPS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); + if (FAILED(hr)) + return hr; + + return pIPS->Load(pStm); + } + + STDMETHODIMP CQuickLaunchBand::Save(IN IStream *pStm, IN BOOL fClearDirty) + { + // Internal CISFBand Calls + CComPtr pIPS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); + if (FAILED(hr)) + return hr; + + return pIPS->Save(pStm, fClearDirty); + } + + STDMETHODIMP CQuickLaunchBand::GetSizeMax(OUT ULARGE_INTEGER *pcbSize) + { + TRACE("CQuickLaunchBand::GetSizeMax called\n"); + + // Internal CISFBand Calls + CComPtr pIPS; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IPersistStream, &pIPS)); + if (FAILED(hr)) + return hr; + + return pIPS->GetSizeMax(pcbSize); + } + + +/*****************************************************************************/ +// IWinEventHandler + STDMETHODIMP CQuickLaunchBand::ContainsWindow(IN HWND hWnd) + { + return E_NOTIMPL; + } + + STDMETHODIMP CQuickLaunchBand::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult) + { + // Internal CISFBand Calls + CComPtr pWEH; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IWinEventHandler, &pWEH)); + if (FAILED(hr)) + return hr; + + return pWEH->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult); + } + + STDMETHODIMP CQuickLaunchBand::IsWindowOwner(HWND hWnd) + { + // Internal CISFBand Calls + CComPtr pWEH; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IWinEventHandler, &pWEH)); + if (FAILED(hr)) + return hr; + + return pWEH->IsWindowOwner(hWnd); + } + +/*****************************************************************************/ +// *** IOleCommandTarget methods *** + STDMETHODIMP CQuickLaunchBand::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText) + { + // Internal CISFBand Calls + CComPtr pOCT; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOCT)); + if (FAILED(hr)) + return hr; + + return pOCT->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText); + } + + STDMETHODIMP CQuickLaunchBand::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut) + { + // Internal CISFBand Calls + CComPtr pOCT; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOCT)); + if (FAILED(hr)) + return hr; + + return pOCT->Exec(pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut); + } + +/*****************************************************************************/ +// *** IContextMenu *** + STDMETHODIMP CQuickLaunchBand::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax) + { + // Internal CISFBand Calls + CComPtr pICM; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); + if (FAILED(hr)) + return hr; + + return pICM->GetCommandString(idCmd, uFlags, pwReserved, pszName, cchMax); + } + + STDMETHODIMP CQuickLaunchBand::InvokeCommand(LPCMINVOKECOMMANDINFO pici) + { + // Internal CISFBand Calls + CComPtr pICM; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); + if (FAILED(hr)) + return hr; + + return pICM->InvokeCommand(pici); + } + + STDMETHODIMP CQuickLaunchBand::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags) + { + // Internal CISFBand Calls + CComPtr pICM; + HRESULT hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IContextMenu, &pICM)); + if (FAILED(hr)) + return hr; + + return pICM->QueryContextMenu(hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags); + } \ No newline at end of file diff --git a/dll/shellext/qcklnch/CQuickLaunchBand.h b/dll/shellext/qcklnch/CQuickLaunchBand.h new file mode 100644 index 00000000000..c8a71dc9f45 --- /dev/null +++ b/dll/shellext/qcklnch/CQuickLaunchBand.h @@ -0,0 +1,174 @@ +/* + * PROJECT: ReactOS shell extensions + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/shellext/qcklnch/CQuickLaunchBand.h + * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) + * PROGRAMMERS: Shriraj Sawant a.k.a SR13 + */ +#pragma once + +extern const GUID CLSID_QuickLaunchBand; + +// Component category registration +HRESULT RegisterComCat(); +HRESULT UnregisterComCat(); + +// COM class for quick launch +class CQuickLaunchBand : + public CComCoClass, + public CComObjectRootEx, + public IObjectWithSite, + public IDeskBand, + public IPersistStream, + public IWinEventHandler, + public IOleCommandTarget, + public IContextMenu +{ + HWND m_hWndBro; + CComPtr m_punkISFB; + + public: + + CQuickLaunchBand(); + virtual ~CQuickLaunchBand(); + +// ATL construct + + HRESULT FinalConstruct(); + +// IObjectWithSite + + virtual STDMETHODIMP GetSite( + IN REFIID riid, + OUT void **ppvSite + ); + + virtual STDMETHODIMP SetSite( + IN IUnknown *pUnkSite + ); + +// IDeskBand + + virtual STDMETHODIMP GetWindow( + OUT HWND *phwnd + ); + + virtual STDMETHODIMP ContextSensitiveHelp( + IN BOOL fEnterMode + ); + + virtual STDMETHODIMP ShowDW( + IN BOOL bShow + ); + + virtual STDMETHODIMP CloseDW( + IN DWORD dwReserved + ); + + virtual STDMETHODIMP ResizeBorderDW( + LPCRECT prcBorder, + IUnknown *punkToolbarSite, + BOOL fReserved + ); + + virtual STDMETHODIMP GetBandInfo( + IN DWORD dwBandID, + IN DWORD dwViewMode, + IN OUT DESKBANDINFO *pdbi + ); + +// IPersistStream + + virtual STDMETHODIMP GetClassID( + OUT CLSID *pClassID + ); + + virtual STDMETHODIMP GetSizeMax( + OUT ULARGE_INTEGER *pcbSize + ); + + virtual STDMETHODIMP IsDirty(); + + virtual STDMETHODIMP Load( + IN IStream *pStm + ); + + virtual STDMETHODIMP Save( + IN IStream *pStm, + IN BOOL fClearDirty + ); + +// IWinEventHandler + + virtual STDMETHODIMP ContainsWindow( + IN HWND hWnd + ); + + virtual STDMETHODIMP OnWinEvent( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam, + LRESULT *theResult + ); + + virtual STDMETHODIMP IsWindowOwner( + HWND hWnd + ); + +// IOleCommandTarget + + virtual STDMETHODIMP Exec( + IN const GUID *pguidCmdGroup, + IN DWORD nCmdID, + IN DWORD nCmdexecopt, + IN VARIANT *pvaIn, + IN OUT VARIANT *pvaOut + ); + + virtual STDMETHODIMP QueryStatus( + IN const GUID *pguidCmdGroup, + IN ULONG cCmds, + IN OUT OLECMD prgCmds[], + IN OUT OLECMDTEXT *pCmdText + ); + +// IContextMenu + virtual STDMETHODIMP GetCommandString( + UINT_PTR idCmd, + UINT uFlags, + UINT *pwReserved, + LPSTR pszName, + UINT cchMax + ); + + virtual STDMETHODIMP InvokeCommand( + LPCMINVOKECOMMANDINFO pici + ); + + virtual STDMETHODIMP QueryContextMenu( + HMENU hmenu, + UINT indexMenu, + UINT idCmdFirst, + UINT idCmdLast, + UINT uFlags + ); + +//***************************************************************************************************** + + DECLARE_REGISTRY_RESOURCEID(IDR_QCKLNCH) + DECLARE_NOT_AGGREGATABLE(CQuickLaunchBand) + DECLARE_PROTECT_FINAL_CONSTRUCT() + + BEGIN_COM_MAP(CQuickLaunchBand) + COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, IDeskBand) + COM_INTERFACE_ENTRY2_IID(IID_IDockingWindow, IDockingWindow, IDeskBand) + COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand) + COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite) + COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist) + COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream) + COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler) + COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget) + COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu) + END_COM_MAP() +}; \ No newline at end of file diff --git a/dll/shellext/qcklnch/lang/en-US.rc b/dll/shellext/qcklnch/lang/en-US.rc new file mode 100644 index 00000000000..81c08eb5d0b --- /dev/null +++ b/dll/shellext/qcklnch/lang/en-US.rc @@ -0,0 +1,19 @@ +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +IDM_POPUPMENU MENUEX DISCARDABLE +BEGIN + POPUP "" + BEGIN + POPUP "&View", IDM_VIEW_MENU + BEGIN + MENUITEM "&Large Icons", IDM_LARGE_ICONS + MENUITEM "&Small Icons", IDM_SMALL_ICONS + END + MENUITEM "&Show Text", IDM_SHOW_TEXT + END +END + +STRINGTABLE +BEGIN + IDS_BROWSEINFO_TITLE "Choose a folder" +END diff --git a/dll/shellext/qcklnch/precomp.h b/dll/shellext/qcklnch/precomp.h new file mode 100644 index 00000000000..12b27a9c150 --- /dev/null +++ b/dll/shellext/qcklnch/precomp.h @@ -0,0 +1,41 @@ +#pragma once + +#define WIN32_NO_STATUS +#include +#include + +#define COBJMACROS +#define WIN32_NO_STATUS +#define _INC_WINDOWS +#define COM_NO_WINDOWS_H +#define NTOS_MODE_USER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "resource.h" +#include "CQuickLaunchBand.h" +#include "CISFBand.h" \ No newline at end of file diff --git a/dll/shellext/qcklnch/qcklnch.cpp b/dll/shellext/qcklnch/qcklnch.cpp new file mode 100644 index 00000000000..79a5a45542f --- /dev/null +++ b/dll/shellext/qcklnch/qcklnch.cpp @@ -0,0 +1,70 @@ +/* + * PROJECT: ReactOS shell extensions + * LICENSE: GPL - See COPYING in the top level directory + * FILE: dll/shellext/qcklnch/qcklnch.cpp + * PURPOSE: Quick Launch Toolbar (Taskbar Shell Extension) + * PROGRAMMERS: Shriraj Sawant a.k.a SR13 + */ + +#include "precomp.h" + +#include + +WINE_DEFAULT_DEBUG_CHANNEL(qcklnch); + +BEGIN_OBJECT_MAP(ObjectMap) + OBJECT_ENTRY(CLSID_QuickLaunchBand, CQuickLaunchBand) +END_OBJECT_MAP() + +HINSTANCE g_hInstance; +CComModule g_Module; + +STDAPI_(BOOL) +DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + { + g_hInstance = hinstDLL; + DisableThreadLibraryCalls(g_hInstance); + + g_Module.Init(ObjectMap, g_hInstance, NULL); + } + else if (fdwReason == DLL_PROCESS_DETACH) + { + g_hInstance = NULL; + g_Module.Term(); + } + return TRUE; +} + +STDAPI +DllRegisterServer(void) +{ + HRESULT hr = g_Module.DllRegisterServer(FALSE); + if (FAILED(hr)) + return hr; + + return RegisterComCat(); +} + +STDAPI +DllUnregisterServer(void) +{ + HRESULT hr = UnregisterComCat(); + if (FAILED(hr)) + return hr; + + return g_Module.DllUnregisterServer(FALSE); +} + +STDAPI +DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) +{ + return g_Module.DllGetClassObject(rclsid, riid, ppv); +} + +STDAPI +DllCanUnloadNow(void) +{ + return g_Module.DllCanUnloadNow(); +} diff --git a/dll/shellext/qcklnch/qcklnch.rc b/dll/shellext/qcklnch/qcklnch.rc new file mode 100644 index 00000000000..f44528e0afa --- /dev/null +++ b/dll/shellext/qcklnch/qcklnch.rc @@ -0,0 +1,15 @@ +#include +#include +#include +#include "resource.h" + +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +IDR_QCKLNCH REGISTRY "rgs/qcklnch.rgs" + +#include + +#ifdef LANGUAGE_EN_US + #include "lang/en-US.rc" +#endif + diff --git a/dll/shellext/qcklnch/qcklnch.spec b/dll/shellext/qcklnch/qcklnch.spec new file mode 100644 index 00000000000..069be116271 --- /dev/null +++ b/dll/shellext/qcklnch/qcklnch.spec @@ -0,0 +1,4 @@ +@ stdcall -private DllCanUnloadNow() +@ stdcall -private DllGetClassObject(ptr ptr ptr) +@ stdcall -private DllRegisterServer() +@ stdcall -private DllUnregisterServer() \ No newline at end of file diff --git a/dll/shellext/qcklnch/resource.h b/dll/shellext/qcklnch/resource.h new file mode 100644 index 00000000000..b5613db3c29 --- /dev/null +++ b/dll/shellext/qcklnch/resource.h @@ -0,0 +1,11 @@ +#pragma once + +#define IDR_QCKLNCH 1001 + +#define IDM_POPUPMENU 2001 +#define IDM_LARGE_ICONS 1 +#define IDM_SMALL_ICONS 2 +#define IDM_SHOW_TEXT 3 +#define IDM_VIEW_MENU 4 + +#define IDS_BROWSEINFO_TITLE 101 diff --git a/dll/shellext/qcklnch/rgs/qcklnch.rgs b/dll/shellext/qcklnch/rgs/qcklnch.rgs new file mode 100644 index 00000000000..3df55ca1d30 --- /dev/null +++ b/dll/shellext/qcklnch/rgs/qcklnch.rgs @@ -0,0 +1,13 @@ +HKCR +{ + NoRemove CLSID + { + ForceRemove {260CB95D-4544-44F6-A079-575BAA60B72F} = s 'Quick Launch' + { + InprocServer32 = s '%MODULE%' + { + val ThreadingModel = s 'Apartment' + } + } + } +} \ No newline at end of file