--- /dev/null
--- /dev/null
++/*
++ * 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();
++}
--- /dev/null
--- /dev/null
++/*
++ * 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);
++}