[QCKLNCH] Implement the quick launch shell extension including the CISFBand
authorShriraj Sawant <sr.official@hotmail.com>
Mon, 16 Oct 2017 13:38:39 +0000 (16:38 +0300)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Mon, 16 Oct 2017 14:51:12 +0000 (17:51 +0300)
13 files changed:
dll/shellext/CMakeLists.txt
dll/shellext/qcklnch/CISFBand.cpp [new file with mode: 0644]
dll/shellext/qcklnch/CISFBand.h [new file with mode: 0644]
dll/shellext/qcklnch/CMakeLists.txt [new file with mode: 0644]
dll/shellext/qcklnch/CQuickLaunchBand.cpp [new file with mode: 0644]
dll/shellext/qcklnch/CQuickLaunchBand.h [new file with mode: 0644]
dll/shellext/qcklnch/lang/en-US.rc [new file with mode: 0644]
dll/shellext/qcklnch/precomp.h [new file with mode: 0644]
dll/shellext/qcklnch/qcklnch.cpp [new file with mode: 0644]
dll/shellext/qcklnch/qcklnch.rc [new file with mode: 0644]
dll/shellext/qcklnch/qcklnch.spec [new file with mode: 0644]
dll/shellext/qcklnch/resource.h [new file with mode: 0644]
dll/shellext/qcklnch/rgs/qcklnch.rgs [new file with mode: 0644]

index 56fabe1..2b5b3c6 100644 (file)
@@ -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 (file)
index 0000000..34192b4
--- /dev/null
@@ -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 <sr.official@hotmail.com>
+ */
+
+#include "precomp.h"
+#include <commoncontrols.h>
+
+#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<IEnumIDList> 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"<Unknown-Name>");
+         }
+         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<LPARAM>(&maxSize));                
+
+            idealSize = maxSize;
+            SendMessageW(m_hWnd, TB_GETIDEALSIZE, FALSE, reinterpret_cast<LPARAM>(&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<IContextMenu> 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<PWSTR>(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<PWSTR>(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<CISFBand>(riid, ppv);
+    }
+
diff --git a/dll/shellext/qcklnch/CISFBand.h b/dll/shellext/qcklnch/CISFBand.h
new file mode 100644 (file)
index 0000000..fc74db0
--- /dev/null
@@ -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 <sr.official@hotmail.com>
+ */
+#pragma once
+
+// COM class for cisfband
+class CISFBand :
+    public CWindow,
+    public CComCoClass<CISFBand>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,    
+    public IObjectWithSite,
+    public IDeskBand,    
+    public IPersistStream,
+    public IWinEventHandler,
+    public IOleCommandTarget,
+    public IShellFolderBand,
+    public IContextMenu
+{
+    // Band
+    DWORD m_BandID;
+    CComPtr<IUnknown> m_Site;
+
+    // Toolbar     
+    CComPtr<IShellFolder> 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 (file)
index 0000000..bcc9218
--- /dev/null
@@ -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 (file)
index 0000000..d250a3c
--- /dev/null
@@ -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 <sr.official@hotmail.com>
+ */
+
+#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<ICatRegister> 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<ICatRegister> 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<ITEMIDLIST> 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<IShellFolderBand> pISFB;
+        hr = m_punkISFB->QueryInterface(IID_PPV_ARG(IShellFolderBand, &pISFB));
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+
+        CComPtr<IShellFolder> pISF;
+        hr = SHGetDesktopFolder(&pISF);
+        if (FAILED_UNEXPECTEDLY(hr))
+            return hr;
+
+        CComHeapPtr<ITEMIDLIST> 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<IObjectWithSite> 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<IObjectWithSite> 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<IDeskBand> 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<IDeskBand> 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<IDeskBand> 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<IDeskBand> 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<IDeskBand> 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<IDeskBand> 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<IPersistStream> 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<IPersistStream> 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<IPersistStream> 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<IPersistStream> 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<IPersistStream> 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<IWinEventHandler> 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<IWinEventHandler> 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<IOleCommandTarget> 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<IOleCommandTarget> 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<IContextMenu> 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<IContextMenu> 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<IContextMenu> 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 (file)
index 0000000..c8a71dc
--- /dev/null
@@ -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 <sr.official@hotmail.com>
+ */
+#pragma once
+
+extern const GUID CLSID_QuickLaunchBand;
+
+// Component category registration
+HRESULT RegisterComCat();
+HRESULT UnregisterComCat();
+
+// COM class for quick launch
+class CQuickLaunchBand :
+    public CComCoClass<CQuickLaunchBand, &CLSID_QuickLaunchBand>,
+    public CComObjectRootEx<CComMultiThreadModelNoCS>,
+    public IObjectWithSite,
+    public IDeskBand,    
+    public IPersistStream,
+    public IWinEventHandler,
+    public IOleCommandTarget,
+    public IContextMenu
+{
+    HWND m_hWndBro;
+    CComPtr<IUnknown> 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 (file)
index 0000000..81c08eb
--- /dev/null
@@ -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 (file)
index 0000000..12b27a9
--- /dev/null
@@ -0,0 +1,41 @@
+#pragma once
+
+#define WIN32_NO_STATUS
+#include <stdarg.h>
+#include <tchar.h>
+
+#define COBJMACROS
+#define WIN32_NO_STATUS
+#define _INC_WINDOWS
+#define COM_NO_WINDOWS_H
+#define NTOS_MODE_USER
+
+#include <windef.h>
+#include <winbase.h>
+#include <winreg.h>
+#include <winuser.h>
+#include <wincon.h>
+#include <ddeml.h>
+#include <shlguid_undoc.h>
+#include <shlwapi.h>
+#include <shlguid.h>
+#include <shlobj.h>
+#include <shlobj_undoc.h>
+#include <shlwapi_undoc.h>
+#include <tchar.h>
+#include <strsafe.h>
+#include <atlbase.h>
+#include <atlcom.h>
+#include <atlwin.h>
+#include <atlstr.h>
+#include <undocshell.h>
+#include <shellutils.h>
+
+#include <shellapi.h>
+
+#include <wine/debug.h>
+#include <wine/unicode.h>
+
+#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 (file)
index 0000000..79a5a45
--- /dev/null
@@ -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 <sr.official@hotmail.com>
+ */
+
+#include "precomp.h"
+
+#include <atlwin.h>
+
+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 (file)
index 0000000..f44528e
--- /dev/null
@@ -0,0 +1,15 @@
+#include <windef.h>
+#include <winuser.h>
+#include <commctrl.h>
+#include "resource.h"
+
+LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
+
+IDR_QCKLNCH REGISTRY "rgs/qcklnch.rgs"
+
+#include <reactos/manifest_dll.rc>
+
+#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 (file)
index 0000000..069be11
--- /dev/null
@@ -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 (file)
index 0000000..b5613db
--- /dev/null
@@ -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 (file)
index 0000000..3df55ca
--- /dev/null
@@ -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