[rshell]
authorGiannis Adamopoulos <gadamopoulos@reactos.org>
Tue, 4 Feb 2014 12:11:51 +0000 (12:11 +0000)
committerGiannis Adamopoulos <gadamopoulos@reactos.org>
Tue, 4 Feb 2014 12:11:51 +0000 (12:11 +0000)
- Commit rshell.exe that allows explorer_new to run in windows 8

svn path=/branches/shell-experiments/; revision=61978

1  2 
base/shell/CMakeLists.txt
base/shell/rshell/CDesktopBrowser.cpp
base/shell/rshell/CMakeLists.txt
base/shell/rshell/CStartMenu.cpp
base/shell/rshell/misc.cpp
base/shell/rshell/precomp.h
base/shell/rshell/rshell.spec

index 1178c36,0000000..8ad4ad9
mode 100644,000000..100644
--- /dev/null
@@@ -1,5 -1,0 +1,6 @@@
 +
 +add_subdirectory(cmd)
 +add_subdirectory(explorer)
 +add_subdirectory(explorer-new)
 +add_subdirectory(filebrowser)
++add_subdirectory(rshell)
index 0000000,0000000..8bf2bdb
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,582 @@@
++/*
++ * Shell Desktop
++ *
++ * Copyright 2008 Thomas Bluemel
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
++ */
++
++#include "precomp.h"
++
++WINE_DEFAULT_DEBUG_CHANNEL(desktop);
++
++BOOL WINAPI SetShellWindowEx(HWND, HWND);
++
++#define SHDESK_TAG 0x4b534544
++
++static const WCHAR szProgmanClassName[] = {'P','r','o','g','m','a','n'};
++static const WCHAR szProgmanWindowName[] = {
++    'P','r','o','g','r','a','m',' ','M','a','n','a','g','e','r'
++};
++
++class CDesktopBrowser :
++    public CComObjectRootEx<CComMultiThreadModelNoCS>,
++    public IShellBrowser,
++    public ICommDlgBrowser,
++    public IServiceProvider
++{
++public:
++    DWORD Tag;
++private:
++    HWND hWnd;
++    HWND hWndShellView;
++    HWND hWndDesktopListView;
++    CComPtr<IShellDesktopTray>        ShellDesk;
++    CComPtr<IShellView>                DesktopView;
++    IShellBrowser *DefaultShellBrowser;
++    LPITEMIDLIST pidlDesktopDirectory;
++    LPITEMIDLIST pidlDesktop;
++public:
++    CDesktopBrowser();
++    ~CDesktopBrowser();
++    HRESULT Initialize(HWND hWndx, IShellDesktopTray *ShellDeskx);
++    HWND FindDesktopListView ();
++    BOOL CreateDeskWnd();
++    HWND DesktopGetWindowControl(IN UINT id);
++    static LRESULT CALLBACK ProgmanWindowProc(IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam);
++    static BOOL MessageLoop();
++
++    // *** IOleWindow methods ***
++    virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *lphwnd);
++    virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
++
++    // *** IShellBrowser methods ***
++    virtual HRESULT STDMETHODCALLTYPE InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths);
++    virtual HRESULT STDMETHODCALLTYPE SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject);
++    virtual HRESULT STDMETHODCALLTYPE RemoveMenusSB(HMENU hmenuShared);
++    virtual HRESULT STDMETHODCALLTYPE SetStatusTextSB(LPCOLESTR pszStatusText);
++    virtual HRESULT STDMETHODCALLTYPE EnableModelessSB(BOOL fEnable);
++    virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorSB(MSG *pmsg, WORD wID);
++    virtual HRESULT STDMETHODCALLTYPE BrowseObject(LPCITEMIDLIST pidl, UINT wFlags);
++    virtual HRESULT STDMETHODCALLTYPE GetViewStateStream(DWORD grfMode, IStream **ppStrm);
++    virtual HRESULT STDMETHODCALLTYPE GetControlWindow(UINT id, HWND *lphwnd);
++    virtual HRESULT STDMETHODCALLTYPE SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret);
++    virtual HRESULT STDMETHODCALLTYPE QueryActiveShellView(struct IShellView **ppshv);
++    virtual HRESULT STDMETHODCALLTYPE OnViewWindowActive(struct IShellView *ppshv);
++    virtual HRESULT STDMETHODCALLTYPE SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags);
++
++    // *** ICommDlgBrowser methods ***
++    virtual HRESULT STDMETHODCALLTYPE OnDefaultCommand (struct IShellView *ppshv);
++    virtual HRESULT STDMETHODCALLTYPE OnStateChange (struct IShellView *ppshv, ULONG uChange);
++    virtual HRESULT STDMETHODCALLTYPE IncludeObject (struct IShellView *ppshv, LPCITEMIDLIST pidl);
++
++    // *** IServiceProvider methods ***
++    virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
++
++BEGIN_COM_MAP(CDesktopBrowser)
++    COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
++    COM_INTERFACE_ENTRY_IID(IID_IShellBrowser, IShellBrowser)
++    COM_INTERFACE_ENTRY_IID(IID_ICommDlgBrowser, ICommDlgBrowser)
++    COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
++END_COM_MAP()
++};
++
++CDesktopBrowser::CDesktopBrowser()
++{
++    Tag = SHDESK_TAG;
++    hWnd = NULL;
++    hWndShellView = NULL;
++    hWndDesktopListView = NULL;
++    DefaultShellBrowser = NULL;
++    pidlDesktopDirectory = NULL;
++    pidlDesktop = NULL;
++}
++
++CDesktopBrowser::~CDesktopBrowser()
++{
++    if (DesktopView.p != NULL)
++    {
++        if (hWndShellView != NULL)
++            DesktopView->DestroyViewWindow();
++
++        hWndShellView = NULL;
++        hWndDesktopListView = NULL;
++    }
++
++    if (pidlDesktopDirectory != NULL)
++    {
++        ILFree(pidlDesktopDirectory);
++        pidlDesktopDirectory = NULL;
++    }
++
++    if (pidlDesktop != NULL)
++    {
++        ILFree(pidlDesktop);
++        pidlDesktop = NULL;
++    }
++}
++
++HRESULT CDesktopBrowser::Initialize(HWND hWndx, IShellDesktopTray *ShellDeskx)
++{
++    CComPtr<IShellFolder>    psfDesktopFolder;
++    CSFV                    csfv;
++    HRESULT                    hRet;
++
++    hWnd = hWndx;
++    ShellDesk = ShellDeskx;
++    ShellDesk->AddRef();
++
++    pidlDesktopDirectory = SHCloneSpecialIDList(hWnd, CSIDL_DESKTOPDIRECTORY, FALSE);
++    hRet = SHGetSpecialFolderLocation(hWnd, CSIDL_DESKTOP, &pidlDesktop);
++    if (FAILED(hRet))
++        return hRet;
++
++    hRet = SHGetDesktopFolder(&psfDesktopFolder);
++    if (FAILED(hRet))
++        return hRet;
++
++    ZeroMemory(&csfv, sizeof(csfv));
++    csfv.cbSize = sizeof(csfv);
++    csfv.pshf = psfDesktopFolder;
++    csfv.psvOuter = NULL;
++
++    hRet = SHCreateShellFolderViewEx(&csfv, &DesktopView);
++
++    return hRet;
++}
++
++static CDesktopBrowser *SHDESK_Create(HWND hWnd, LPCREATESTRUCT lpCreateStruct)
++{
++    IShellDesktopTray        *ShellDesk;
++    CComObject<CDesktopBrowser>        *pThis;
++    HRESULT                    hRet;
++
++    ShellDesk = (IShellDesktopTray *)lpCreateStruct->lpCreateParams;
++    if (ShellDesk == NULL)
++    {
++        WARN("No IShellDesk interface provided!");
++        return NULL;
++    }
++
++    pThis = new CComObject<CDesktopBrowser>;
++    if (pThis == NULL)
++        return NULL;
++    pThis->AddRef();
++
++    hRet = pThis->Initialize(hWnd, ShellDesk);
++    if (FAILED(hRet))
++    {
++        pThis->Release();
++        return NULL;
++    }
++
++    return pThis;
++}
++
++HWND CDesktopBrowser::FindDesktopListView ()
++{
++    return FindWindowExW(hWndShellView, NULL, WC_LISTVIEW, NULL);
++}
++
++BOOL CDesktopBrowser::CreateDeskWnd()
++{
++    FOLDERSETTINGS fs;
++    RECT rcClient;
++    HRESULT hRet;
++
++    if (!GetClientRect(hWnd, &rcClient))
++    {
++        return FALSE;
++    }
++
++    fs.ViewMode = FVM_ICON;
++    fs.fFlags = FWF_DESKTOP | FWF_NOCLIENTEDGE  | FWF_NOSCROLL | FWF_TRANSPARENT;
++    hRet = DesktopView->CreateViewWindow(NULL, &fs, (IShellBrowser *)this, &rcClient, &hWndShellView);
++    if (!SUCCEEDED(hRet))
++        return FALSE;
++
++    SetShellWindowEx(hWnd, FindDesktopListView());
++
++#if 1
++    /* A windows 8 specific hack */
++    ::ShowWindow(hWndShellView, SW_SHOW);
++    ::ShowWindow(FindDesktopListView(), SW_SHOW);
++#endif
++
++    return TRUE;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetWindow(HWND *phwnd)
++{
++    if (hWnd != NULL)
++    {
++        *phwnd = hWnd;
++        return S_OK;
++    }
++
++    *phwnd = NULL;
++    return E_UNEXPECTED;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::ContextSensitiveHelp(BOOL fEnterMode)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::InsertMenusSB(HMENU hmenuShared, LPOLEMENUGROUPWIDTHS lpMenuWidths)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetMenuSB(HMENU hmenuShared, HOLEMENU holemenuRes, HWND hwndActiveObject)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::RemoveMenusSB(HMENU hmenuShared)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetStatusTextSB(LPCOLESTR lpszStatusText)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::EnableModelessSB(BOOL fEnable)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::TranslateAcceleratorSB(LPMSG lpmsg, WORD wID)
++{
++    return S_FALSE;
++}
++
++typedef HRESULT (WINAPI *SH_OPEN_NEW_FRAME)(LPITEMIDLIST pidl, IUnknown *paramC, long param10, long param14);
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::BrowseObject(LPCITEMIDLIST pidl, UINT wFlags)
++{
++    /* 
++     * We should use IShellWindows interface here in order to attempt to 
++     * find an open shell window that shows the requested pidl and activate it
++     */
++
++#if 0
++    HMODULE hBrowseui = LoadLibraryW(L"browseui.dll");
++    if (hBrowseui)
++    {
++        SH_OPEN_NEW_FRAME SHOpenNewFrame = (SH_OPEN_NEW_FRAME)GetProcAddress(hBrowseui, (LPCSTR)103);
++        return SHOpenNewFrame((LPITEMIDLIST)pidl, NULL, 0, 0);
++    }
++#endif
++    return E_FAIL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetViewStateStream(DWORD grfMode, IStream **ppStrm)
++{
++    return E_NOTIMPL;
++}
++
++HWND CDesktopBrowser::DesktopGetWindowControl(IN UINT id)
++{
++    switch (id)
++    {
++        case FCW_TOOLBAR:
++        case FCW_STATUS:
++        case FCW_TREE:
++        case FCW_PROGRESS:
++            return NULL;
++
++        default:
++            return NULL;
++    }
++
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::GetControlWindow(UINT id, HWND *lphwnd)
++{
++    HWND hWnd;
++
++    hWnd = DesktopGetWindowControl(id);
++    if (hWnd != NULL)
++    {
++        *lphwnd = hWnd;
++        return S_OK;
++    }
++
++    *lphwnd = NULL;
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::SendControlMsg(UINT id, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *pret)
++{
++    HWND                        hWnd;
++
++    if (pret == NULL)
++        return E_POINTER;
++
++    hWnd = DesktopGetWindowControl(id);
++    if (hWnd != NULL)
++    {
++        *pret = SendMessageW(hWnd,
++                             uMsg,
++                             wParam,
++                             lParam);
++        return S_OK;
++    }
++
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryActiveShellView(IShellView **ppshv)
++{
++    *ppshv = DesktopView;
++    if (DesktopView != NULL)
++        DesktopView->AddRef();
++
++    return S_OK;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnViewWindowActive(IShellView *ppshv)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::SetToolbarItems(LPTBBUTTON lpButtons, UINT nButtons, UINT uFlags)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnDefaultCommand(IShellView *ppshv)
++{
++    return E_NOTIMPL;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::OnStateChange(IShellView *ppshv, ULONG uChange)
++{
++    return S_OK;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::IncludeObject(IShellView *ppshv, LPCITEMIDLIST pidl)
++{
++    return S_OK;
++}
++
++HRESULT STDMETHODCALLTYPE CDesktopBrowser::QueryService(REFGUID guidService, REFIID riid, PVOID *ppv)
++{
++    /* FIXME - handle guidService */
++    return QueryInterface(riid, ppv);
++}
++
++BOOL CDesktopBrowser::MessageLoop()
++{
++    MSG Msg;
++    BOOL bRet;
++
++    while ((bRet = GetMessageW(&Msg, NULL, 0, 0)) != 0)
++    {
++        if (bRet != -1)
++        {
++            TranslateMessage(&Msg);
++            DispatchMessageW(&Msg);
++        }
++    }
++
++    return TRUE;
++}
++
++LRESULT CALLBACK CDesktopBrowser::ProgmanWindowProc(IN HWND hwnd, IN UINT uMsg, IN WPARAM wParam, IN LPARAM lParam)
++{
++    CDesktopBrowser *pThis = NULL;
++    LRESULT Ret = FALSE;
++
++    if (uMsg != WM_NCCREATE)
++    {
++        pThis = (CDesktopBrowser*)GetWindowLongPtrW(hwnd,
++                                          0);
++        if (pThis == NULL)
++            goto DefMsgHandler;
++    }
++
++    if (pThis != NULL || uMsg == WM_NCCREATE)
++    {
++        switch (uMsg)
++        {
++            case WM_ERASEBKGND:
++                return (LRESULT)PaintDesktop((HDC)wParam);
++
++            case WM_GETISHELLBROWSER:
++                Ret = (LRESULT)((IShellBrowser *)pThis);
++                break;
++
++            case WM_SIZE:
++                if (wParam == SIZE_MINIMIZED)
++                {
++                    /* Hey, we're the desktop!!! */
++                    ShowWindow(hwnd,
++                               SW_RESTORE);
++                }
++                else
++                {
++                    RECT rcDesktop;
++
++                    rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
++                    rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
++                    rcDesktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
++                    rcDesktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
++
++                    /* FIXME: Update work area */
++                }
++                break;
++
++            case WM_SYSCOLORCHANGE:
++            case WM_SETTINGCHANGE:
++            {
++                if (uMsg == WM_SYSCOLORCHANGE || wParam == SPI_SETDESKWALLPAPER || wParam == 0)
++                {
++                    if (pThis->hWndShellView != NULL)
++                    {
++                        /* Forward the message */
++                        SendMessageW(pThis->hWndShellView,
++                                     uMsg,
++                                     wParam,
++                                     lParam);
++                    }
++                }
++                break;
++            }
++
++            case WM_CREATE:
++            {
++                pThis->ShellDesk->RegisterDesktopWindow(pThis->hWnd);
++
++                if (!pThis->CreateDeskWnd())
++                    WARN("Could not create the desktop view control!\n");
++                break;
++            }
++
++            case WM_NCCREATE:
++            {
++                LPCREATESTRUCT CreateStruct = (LPCREATESTRUCT)lParam;
++                pThis = SHDESK_Create(hwnd, CreateStruct);
++                if (pThis == NULL)
++                {
++                    WARN("Failed to create desktop structure\n");
++                    break;
++                }
++
++                SetWindowLongPtrW(hwnd,
++                                  0,
++                                  (LONG_PTR)pThis);
++                Ret = TRUE;
++                break;
++            }
++
++            case WM_NCDESTROY:
++            {
++                pThis->Release();
++                break;
++            }
++
++            default:
++DefMsgHandler:
++                Ret = DefWindowProcW(hwnd, uMsg, wParam, lParam);
++                break;
++        }
++    }
++
++    return Ret;
++}
++
++static BOOL
++RegisterProgmanWindowClass(VOID)
++{
++    WNDCLASSW wcProgman;
++
++    wcProgman.style = CS_DBLCLKS;
++    wcProgman.lpfnWndProc = CDesktopBrowser::ProgmanWindowProc;
++    wcProgman.cbClsExtra = 0;
++    wcProgman.cbWndExtra = sizeof(CDesktopBrowser *);
++    wcProgman.hInstance = shell32_hInstance;
++    wcProgman.hIcon = NULL;
++    wcProgman.hCursor = LoadCursorW(NULL, IDC_ARROW);
++    wcProgman.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1);
++    wcProgman.lpszMenuName = NULL;
++    wcProgman.lpszClassName = szProgmanClassName;
++
++    return RegisterClassW(&wcProgman) != 0;
++}
++
++
++/*************************************************************************
++ * SHCreateDesktop            [SHELL32.200]
++ *
++ */
++HANDLE WINAPI SHCreateDesktop(IShellDesktopTray *ShellDesk)
++{
++    HWND hWndDesk;
++    RECT rcDesk;
++
++    if (ShellDesk == NULL)
++    {
++        SetLastError(ERROR_INVALID_PARAMETER);
++        return NULL;
++    }
++
++    if (RegisterProgmanWindowClass() == 0)
++    {
++        WARN("Failed to register the Progman window class!\n");
++        return NULL;
++    }
++
++    rcDesk.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
++    rcDesk.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
++    rcDesk.right = rcDesk.left + GetSystemMetrics(SM_CXVIRTUALSCREEN);
++    rcDesk.bottom = rcDesk.top + GetSystemMetrics(SM_CYVIRTUALSCREEN);
++
++    if (IsRectEmpty(&rcDesk))
++    {
++        rcDesk.left = rcDesk.top = 0;
++        rcDesk.right = GetSystemMetrics(SM_CXSCREEN);
++        rcDesk.bottom = GetSystemMetrics(SM_CYSCREEN);
++    }
++
++    hWndDesk = CreateWindowExW(0, szProgmanClassName, szProgmanWindowName,
++        WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
++        rcDesk.left, rcDesk.top, rcDesk.right, rcDesk.bottom,
++        NULL, NULL, shell32_hInstance, (LPVOID)ShellDesk);
++    if (hWndDesk != NULL)
++        return (HANDLE)GetWindowLongPtrW(hWndDesk, 0);
++
++    return NULL;
++}
++
++/*************************************************************************
++ * SHCreateDesktop            [SHELL32.201]
++ *
++ */
++BOOL WINAPI SHDesktopMessageLoop(HANDLE hDesktop)
++{
++    CDesktopBrowser *Desk = (CDesktopBrowser *)hDesktop;
++
++    if (Desk == NULL || Desk->Tag != SHDESK_TAG)
++    {
++        SetLastError(ERROR_INVALID_PARAMETER);
++        return FALSE;
++    }
++
++    return Desk->MessageLoop();
++}
index 0000000,0000000..5a99577
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,31 @@@
++PROJECT(SHELL)
++
++set_cpp(WITH_RUNTIME)
++
++include_directories(${REACTOS_SOURCE_DIR}/lib/atl)
++
++spec2def(rshell.dll rshell.spec ADD_IMPORTLIB)
++
++list(APPEND SOURCE
++    CDesktopBrowser.cpp
++    CStartMenu.cpp
++    misc.cpp
++    ${CMAKE_CURRENT_BINARY_DIR}/rshell.def)
++
++add_library(rshell SHARED ${SOURCE})
++
++set_module_type(rshell win32dll UNICODE)
++
++target_link_libraries(rshell
++    atlnew
++    uuid
++    wine)
++
++add_importlibs(rshell
++    shlwapi
++    shell32
++    ole32
++    user32
++    msvcrt
++    kernel32
++    ntdll)
index 0000000,0000000..fe97909
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,318 @@@
++/*
++ * ReactOS Explorer
++ *
++ * Copyright 2014 Giannis Adamopoulos
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
++ */
++
++#include "precomp.h"
++
++/* NOTE: The following constants may *NOT* be changed because
++         they're hardcoded and need to be the exact values
++         in order to get the start menu to work! */
++#define IDM_PROGRAMS                504
++#define IDM_FAVORITES               507
++#define IDM_DOCUMENTS               501
++#define IDM_SETTINGS                508
++#define IDM_CONTROLPANEL            505
++#define IDM_SECURITY                5001
++#define IDM_NETWORKCONNECTIONS      557
++#define IDM_PRINTERSANDFAXES        510
++#define IDM_TASKBARANDSTARTMENU     413
++#define IDM_SEARCH                  520
++#define IDM_HELPANDSUPPORT          503
++#define IDM_RUN                     401
++#define IDM_SYNCHRONIZE             553
++#define IDM_LOGOFF                  402
++#define IDM_DISCONNECT              5000
++#define IDM_UNDOCKCOMPUTER          410
++#define IDM_SHUTDOWN                506
++#define IDM_LASTSTARTMENU_SEPARATOR 450
++
++/*
++ * TODO:
++ * 1. append the start menu contents from all users
++ * 2. implement the context menu for start menu entries (programs, control panel, network connetions, printers)
++ * 3. filter out programs folder from the shell folder part of the start menu
++ */
++
++class CShellMenuCallback : 
++    public CComObjectRootEx<CComMultiThreadModelNoCS>,
++    public IShellMenuCallback 
++{
++private:
++    
++    HWND m_hwndTray;
++    CComPtr<IShellMenu> m_pShellMenu;
++    CComPtr<IBandSite> m_pBandSite;
++    CComPtr<IDeskBar> m_pDeskBar;
++    CComPtr<ITrayPriv> m_pTrayPriv;
++
++    HRESULT OnInitMenu()
++    {
++        HMENU hmenu;
++        HRESULT hr;
++
++        if (m_pTrayPriv.p)
++            return S_OK;
++
++        hr = IUnknown_GetSite(m_pDeskBar, IID_PPV_ARG(ITrayPriv, &m_pTrayPriv));
++        hr = IUnknown_GetWindow(m_pTrayPriv, &m_hwndTray);
++        hr = m_pTrayPriv->AppendMenuW(&hmenu);
++        hr = m_pShellMenu->SetMenu(hmenu, NULL, SMSET_BOTTOM);
++
++        return hr;
++    }
++
++    HRESULT OnGetInfo(LPSMDATA psmd, SMINFO *psminfo)
++    {
++        int iconIndex = 0;
++                
++        switch (psmd->uId)
++        {
++        case IDM_PROGRAMS:  iconIndex = -20; break;
++        case IDM_FAVORITES: iconIndex = -173; break;
++        case IDM_DOCUMENTS: iconIndex = -21; break;
++        case IDM_SETTINGS: iconIndex = -22; break;
++        case IDM_CONTROLPANEL: iconIndex = -22; break;
++        //case IDM_SECURITY: iconIndex = -21; break;
++        case IDM_NETWORKCONNECTIONS: iconIndex = -257; break;
++        case IDM_PRINTERSANDFAXES: iconIndex = -138; break;
++        case IDM_TASKBARANDSTARTMENU: iconIndex = -40; break;
++        case IDM_SEARCH: iconIndex = -23; break;
++        case IDM_HELPANDSUPPORT: iconIndex = -24; break;
++        case IDM_RUN: iconIndex = -25; break;
++        //case IDM_SYNCHRONIZE: iconIndex = -21; break;
++        case IDM_LOGOFF: iconIndex = -45; break;
++        //case IDM_DISCONNECT: iconIndex = -21; break;
++        //case IDM_UNDOCKCOMPUTER: iconIndex = -21; break;
++        case IDM_SHUTDOWN: iconIndex = -28; break;
++        default:
++            return S_FALSE;
++        }
++
++        if (iconIndex)
++        {
++            psminfo->dwMask = SMIM_ICON;
++            psminfo->iIcon = Shell_GetCachedImageIndex(L"shell32.dll", iconIndex, FALSE); 
++        }
++        return S_OK;
++    }
++
++    HRESULT OnGetSubMenu(LPSMDATA psmd, REFIID iid, void ** pv)
++    {
++        HRESULT hr;
++        int csidl = 0;
++        IShellMenu *pShellMenu;
++        
++        switch (psmd->uId)
++        {
++        case IDM_PROGRAMS:  csidl = CSIDL_PROGRAMS; break;
++        case IDM_FAVORITES: csidl = CSIDL_FAVORITES; break;
++        case IDM_DOCUMENTS: csidl = CSIDL_RECENT; break;
++        }
++
++        hr = CoCreateInstance(CLSID_MenuBand,
++                                NULL,
++                                CLSCTX_INPROC_SERVER,
++                                IID_PPV_ARG(IShellMenu,&pShellMenu));
++
++        hr = pShellMenu->Initialize(this, 0, ANCESTORDEFAULT, SMINIT_VERTICAL);
++
++        if (csidl)
++        {
++            LPITEMIDLIST pidlStartMenu;
++            IShellFolder *psfDestop, *psfStartMenu;
++
++            hr = SHGetFolderLocation(NULL, csidl, 0, 0, &pidlStartMenu);
++            hr = SHGetDesktopFolder(&psfDestop);
++            hr = psfDestop->BindToObject(pidlStartMenu, NULL, IID_PPV_ARG(IShellFolder, &psfStartMenu));
++
++            hr = pShellMenu->SetShellFolder(psfStartMenu, NULL, NULL, 0);
++        }
++        else
++        {
++            MENUITEMINFO mii;
++            mii.cbSize = sizeof(mii);
++            mii.fMask = MIIM_SUBMENU;
++            if (GetMenuItemInfoW( psmd->hmenu, psmd->uId, FALSE, &mii))
++            {
++                hr = pShellMenu->SetMenu(mii.hSubMenu, NULL, SMSET_BOTTOM);
++            }
++        }
++        return pShellMenu->QueryInterface(iid, pv);
++    }
++
++    HRESULT OnGetContextMenu(LPSMDATA psmd, REFIID iid, void ** pv)
++    {
++        if (psmd->uId == IDM_PROGRAMS ||
++            psmd->uId == IDM_CONTROLPANEL || 
++            psmd->uId == IDM_NETWORKCONNECTIONS ||
++            psmd->uId == IDM_PRINTERSANDFAXES)
++        {
++            //UNIMPLEMENTED
++        }
++
++        return S_FALSE;
++    }
++
++    HRESULT OnGetObject(LPSMDATA psmd, REFIID iid, void ** pv)
++    {
++        if (IsEqualIID(iid , IID_IShellMenu))
++            return OnGetSubMenu(psmd, iid, pv);
++        else if (IsEqualIID( iid, IID_IContextMenu))
++            return OnGetContextMenu(psmd, iid, pv);
++
++        return S_FALSE;
++    }
++
++    HRESULT OnExec(LPSMDATA psmd)
++    {
++        if(psmd->uId == IDM_CONTROLPANEL)
++            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", NULL,NULL, 1);
++        else if(psmd->uId == IDM_NETWORKCONNECTIONS)
++            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", NULL,NULL, 1);
++        else if(psmd->uId == IDM_PRINTERSANDFAXES)
++            ShellExecuteW(NULL, L"open", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}", NULL,NULL, 1);
++        else
++            PostMessageW( m_hwndTray, WM_COMMAND, psmd->uId, 0);
++
++        return S_OK;
++    }
++
++public:
++
++    DECLARE_NOT_AGGREGATABLE(CShellMenuCallback)
++    DECLARE_PROTECT_FINAL_CONSTRUCT()
++    BEGIN_COM_MAP(CShellMenuCallback)
++        COM_INTERFACE_ENTRY_IID(IID_IShellMenuCallback, IShellMenuCallback)
++    END_COM_MAP()
++
++    void Initialize(    
++        IShellMenu* pShellMenu,
++        IBandSite* pBandSite,
++        IDeskBar* pDeskBar)
++    {
++        m_pShellMenu.Attach(pShellMenu);
++        m_pBandSite.Attach(pBandSite);
++        m_pDeskBar.Attach(pDeskBar);
++    }
++
++    ~CShellMenuCallback()
++    {
++        m_pShellMenu.Release();
++        m_pBandSite.Release();
++        m_pDeskBar.Release();
++    }
++
++    HRESULT STDMETHODCALLTYPE CallbackSM(
++        LPSMDATA psmd,
++        UINT uMsg,
++        WPARAM wParam,
++        LPARAM lParam)
++    {
++        switch (uMsg)
++        {
++        case SMC_INITMENU:
++                return OnInitMenu();
++        case SMC_GETINFO:
++                return OnGetInfo(psmd, reinterpret_cast<SMINFO*>(lParam));
++        case SMC_GETOBJECT:
++                return OnGetObject(psmd, *reinterpret_cast<IID *>(wParam), reinterpret_cast<void **>(lParam));
++        case SMC_EXEC:
++                return OnExec(psmd);
++        case SMC_SFEXEC:
++                m_pTrayPriv->Execute(psmd->psf, psmd->pidlItem);
++                break;
++        }
++
++    return S_FALSE;
++    }
++};
++
++extern "C" 
++HRESULT
++CStartMenu_Constructor(
++    REFIID riid,
++    void **ppv)
++{
++    IShellMenu* pShellMenu;
++    IBandSite* pBandSite;
++    IDeskBar* pDeskBar;
++    IShellMenuCallback* callback;
++    LPITEMIDLIST pidlStartMenu;
++
++    HRESULT hr;
++    IShellFolder *shellFolder;
++    IShellFolder *psfStartMenu;
++
++    hr = CoCreateInstance(CLSID_MenuBand,
++                          NULL,
++                          CLSCTX_INPROC_SERVER,
++                          IID_PPV_ARG(IShellMenu, &pShellMenu));
++    if (FAILED(hr))
++        return NULL;
++
++#if 1
++    hr = CoCreateInstance(CLSID_MenuBandSite,
++                          NULL,
++                          CLSCTX_INPROC_SERVER,
++                          IID_PPV_ARG(IBandSite, &pBandSite));
++#else
++    hr = CMenuSite_Constructor(IID_PPV_ARG(IBandSite, &pBandSite));
++#endif
++    if (FAILED(hr))
++        return NULL;
++
++    hr = CoCreateInstance(CLSID_MenuDeskBar,
++                          NULL,
++                          CLSCTX_INPROC_SERVER,
++                          IID_PPV_ARG(IDeskBar, &pDeskBar));
++    if (FAILED(hr))
++        return NULL;
++    
++    CComObject<CShellMenuCallback> *pCallback;
++    hr = CComObject<CShellMenuCallback>::CreateInstance(&pCallback);
++    if (FAILED(hr))
++        return FALSE;
++    pCallback->AddRef(); // CreateInstance returns object with 0 ref count */
++    pCallback->Initialize(pShellMenu, pBandSite, pDeskBar);
++    callback = pCallback;
++
++    hr = CShellMenuCallback::_CreatorClass::CreateInstance(NULL, IID_PPV_ARG(IShellMenuCallback, &callback)); 
++    if (FAILED(hr))
++        return NULL;
++
++    pShellMenu->Initialize(pCallback, -1, 0, SMINIT_TOPLEVEL | SMINIT_VERTICAL);
++    if (FAILED(hr))
++        return NULL;
++
++    hr = SHGetFolderLocation(NULL, CSIDL_STARTMENU, 0, 0, &pidlStartMenu);
++    hr = SHGetDesktopFolder(&shellFolder);
++    hr = shellFolder->BindToObject(pidlStartMenu, NULL, IID_IShellFolder, (void**)&psfStartMenu);
++
++    hr = pShellMenu->SetShellFolder(psfStartMenu, NULL, NULL, 0);
++    
++    hr =  pDeskBar->SetClient(pBandSite);
++    if (FAILED(hr))
++        return NULL;
++
++    hr =  pBandSite->AddBand(pShellMenu);
++    if (FAILED(hr))
++        return NULL;
++
++    return pDeskBar->QueryInterface(riid, ppv);
++}
index 0000000,0000000..8f9e63e
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,60 @@@
++/*
++ * ReactOS Explorer
++ *
++ * Copyright 2014 Giannis Adamopoulos
++ *
++ * This library is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU Lesser General Public
++ * License as published by the Free Software Foundation; either
++ * version 2.1 of the License, or (at your option) any later version.
++ *
++ * This library is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * Lesser General Public License for more details.
++ *
++ * You should have received a copy of the GNU Lesser General Public
++ * License along with this library; if not, write to the Free Software
++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
++ */
++
++#include "precomp.h"
++
++DWORD WINAPI WinList_Init(void)
++{
++    /* do something here (perhaps we may want to add our own implementation fo win8) */
++    return 0;
++}
++
++void *operator new (size_t, void *buf)
++{
++    return buf;
++}
++
++class CRShellModule : public CComModule
++{
++public:
++};
++
++CRShellModule                               gModule;
++CAtlWinModule                               gWinModule;
++
++STDAPI_(BOOL) DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID fImpLoad)
++{
++    if (dwReason == DLL_PROCESS_ATTACH)
++    {
++        /* HACK - the global constructors don't run, so I placement new them here */
++        new (&gModule) CRShellModule;
++        new (&gWinModule) CAtlWinModule;
++        new (&_AtlBaseModule) CAtlBaseModule;
++        new (&_AtlComModule) CAtlComModule;
++
++        gModule.Init(NULL, hInstance, NULL);
++        DisableThreadLibraryCalls (hInstance);
++    }
++    else if (dwReason == DLL_PROCESS_DETACH)
++    {
++        gModule.Term();
++    }
++    return TRUE;
++}
index 0000000,0000000..81d993f
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,55 @@@
++
++#include <stdio.h>
++#include <tchar.h>
++
++#define WIN32_NO_STATUS
++#define _INC_WINDOWS
++#define COM_NO_WINDOWS_H
++
++#define COBJMACROS
++
++#include <windef.h>
++#include <winbase.h>
++#include <winreg.h>
++#include <wingdi.h>
++#include <winnls.h>
++#include <wincon.h>
++#include <shellapi.h>
++#include <shlobj.h>
++#include <shlobj_undoc.h>
++#include <shlwapi.h>
++#include <shlguid_undoc.h>
++#include <uxtheme.h>
++#include <strsafe.h>
++
++#include <atlbase.h>
++#include <atlcom.h>
++#include <wine/debug.h>
++
++#define shell32_hInstance 0
++#define SMC_EXEC 4
++extern "C" INT WINAPI Shell_GetCachedImageIndex(LPCWSTR szPath, INT nIndex, UINT bSimulateDoc);
++extern "C" HRESULT CMenuSite_Constructor(REFIID riid, void **ppv);
++
++#define INTERFACE IExplorerHostCreator
++DECLARE_INTERFACE_(IExplorerHostCreator,IUnknown)
++{
++    /*** IUnknown methods ***/
++    STDMETHOD_(HRESULT,QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
++    STDMETHOD_(ULONG,AddRef) (THIS) PURE;
++    STDMETHOD_(ULONG,Release) (THIS) PURE;
++    /*** IExplorerHostCreator ***/
++    STDMETHOD_(HRESULT,CreateHost)(/*THIS,*/ const GUID* guid) PURE;
++    STDMETHOD_(HRESULT,RunHost)(THIS) PURE;
++};
++#undef INTERFACE
++
++#if defined(COBJMACROS)
++/*** IUnknown methods ***/
++#define IExplorerHostCreator_QueryInterface(p,a,b)             (p)->lpVtbl->QueryInterface(p,a,b)
++#define IExplorerHostCreator_AddRef(p)                         (p)->lpVtbl->AddRef(p)
++#define IExplorerHostCreator_Release(p)                        (p)->lpVtbl->Release(p)
++/*** IExplorerHostCreator methods ***/
++#define IExplorerHostCreator_CreateHost(p,a)                   (p)->lpVtbl->CreateHost(p,a)
++#define IExplorerHostCreator_RunHost(p)                          (p)->lpVtbl->RunHost(p)
++#endif
index 0000000,0000000..49da9fc
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,4 @@@
++@   stdcall CStartMenu_Constructor(ptr ptr)
++@   stdcall SHDesktopMessageLoop(ptr)
++@   stdcall SHCreateDesktop(ptr)
++@   stdcall WinList_Init()