* The Shell.. for a long time we dreamed of having a compatible, properly working rewrite, but it's easier said than done. Over the years this effort has been split into tasks, and this branch was the biggest overall. Now it's time to merge it back to trunk!

* This merge is also a chance to thank every single person involved directly and indirectly in this epic work, among them: Martin Fuchs for ReactOS explorer which we are respectfully retiring now, as it served the project so well over all these years. Thomas Bluemel (Thomas Weidenmueller aka w3seek) for his brave work on the shell, mainly his explorer_new. Andrew Hill for advancing the shell bringup with some impressive work. David Quintana, Giannis Adamopoulos and Huw Campbell for working as a solid team on making this branch a huge success, allowing the shell rewrite dream to finally become a reality. Again, thank you all!
* Merging this branch is not the end.. it's the beginning of some serious bug fixing based hopefully on the Community's continuous feedback.
* Finally, here are *some* of the highlights of this branch (simply put):

[BROWSEUI] Halfplement the address bar. Mostly implement the Favorites menu. Implement handling most hotkeys that should be handled by CShellBrowser. Fix various bugs.

[EXPLORER_NEW] Convert to C++ and use several wtl-like classes to simplify it. Fix several bugs and implement misc missing features.

[FILEBROWSER] A small exe file that opens a new file browser window in its own process. Tested to work in windows. It can be used to test our browseui.dll in windows.

[FONTS] A new marlett font.

[MSGINA] Add a proper shutdown dialog that's used when the user selects shutdown from the start menu (this is how it's done in Windows).

[RSHELL] A temporary module that hosts the implementation of the following classes needed for the shell: CMenuBand, CMenuDeskBar, CMenuSite, CMergedFolder, CStartMenu. These were implemented and tested in windows and for that reason they are still there. Should be moved in shell32 in the future.

[SHELL32] Reorganize files to isolate the ones that are not yet forked from wine. Fix various problems. Simplify the implementation of some shell folders. Implement filling in the file menu in the file browser.

[STOBJECT] A shell extension responsible for misc taskbar notification icons. So far only the sound icon is implemented. Adding this is necessary as the old explorer had the sound icon built in and deprecating it needs a proper solution for these notification icons.

[WIN32K] Fix several bugs that prevented the new start menu (that was implemented and tested in Windows) from functioning properly in ReactOS, mostly due to focus issues. Fix several shell notifications to behave more like in Windows.

* Tonight! We shall feast!
* And tomorrow the US guys shall feast again, on turkey! :p

CORE-7330

svn path=/trunk/; revision=65496
This commit is contained in:
Amine Khaldi 2014-11-26 19:49:18 +00:00
commit 5c1a8109c8
256 changed files with 34281 additions and 21720 deletions

View File

@ -2,3 +2,5 @@
add_subdirectory(cmd)
add_subdirectory(explorer)
add_subdirectory(explorer-new)
add_subdirectory(filebrowser)
add_subdirectory(rshell)

View File

@ -1,24 +1,32 @@
PROJECT(SHELL)
add_definitions(-DWIN32)
set_cpp(WITH_RUNTIME)
include_directories(${REACTOS_SOURCE_DIR}/lib/atl)
list(APPEND SOURCE
desktop.c
dragdrop.c
explorer.c
settings.c
startmnu.c
startup.c
taskband.c
taskswnd.c
tbsite.c
trayntfy.c
trayprop.c
traywnd.c
desktop.cpp
dragdrop.cpp
explorer.cpp
rshell.cpp
settings.cpp
shellservice.cpp
startctxmnu.cpp
startmnu.cpp
startmnusite.cpp
startup.cpp
taskband.cpp
taskswnd.cpp
tbsite.cpp
trayntfy.cpp
trayprop.cpp
traywnd.cpp
util.cpp
precomp.h)
add_executable(explorer_new ${SOURCE} explorer.rc)
target_link_libraries(explorer_new uuid)
set_module_type(explorer_new win32gui UNICODE)
add_importlibs(explorer_new advapi32 gdi32 user32 comctl32 ole32 oleaut32 shell32 shlwapi shdocvw version uxtheme msvcrt kernel32 ntdll)
add_pch(explorer_new precomp.h SOURCE)
add_cd_file(TARGET explorer_new DESTINATION reactos FOR all)
add_executable(explorer ${SOURCE} explorer.rc)
target_link_libraries(explorer uuid atlnew wine)
set_module_type(explorer win32gui UNICODE)
add_importlibs(explorer advapi32 gdi32 user32 comctl32 ole32 oleaut32 shell32 browseui shlwapi shdocvw version uxtheme msvcrt kernel32 ntdll)
add_pch(explorer precomp.h SOURCE)
add_cd_file(TARGET explorer DESTINATION reactos FOR all)

View File

@ -1,132 +0,0 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
typedef struct _DESKCREATEINFO
{
HANDLE hEvent;
ITrayWindow *Tray;
HANDLE hDesktop;
} DESKCREATEINFO, *PDESKCREATEINFO;
static DWORD CALLBACK
DesktopThreadProc(IN OUT LPVOID lpParameter)
{
volatile DESKCREATEINFO *DeskCreateInfo = (volatile DESKCREATEINFO *)lpParameter;
IShellDesktopTray *pSdt;
HANDLE hDesktop;
HRESULT hRet;
OleInitialize(NULL);
hRet = ITrayWindow_QueryInterface(DeskCreateInfo->Tray,
&IID_IShellDesktopTray,
(PVOID*)&pSdt);
if (!SUCCEEDED(hRet))
return 1;
hDesktop = SHCreateDesktop(pSdt);
IShellDesktopTray_Release(pSdt);
if (hDesktop == NULL)
return 1;
(void)InterlockedExchangePointer(&DeskCreateInfo->hDesktop,
hDesktop);
if (!SetEvent(DeskCreateInfo->hEvent))
{
/* Failed to notify that we initialized successfully, kill ourselves
to make the main thread wake up! */
return 1;
}
SHDesktopMessageLoop(hDesktop);
/* FIXME: Properly rundown the main thread! */
ExitProcess(0);
return 0;
}
HANDLE
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
{
HANDLE hThread;
HANDLE hEvent;
DWORD DesktopThreadId;
HANDLE hDesktop = NULL;
HANDLE Handles[2];
DWORD WaitResult;
hEvent = CreateEvent(NULL,
FALSE,
FALSE,
NULL);
if (hEvent != NULL)
{
volatile DESKCREATEINFO DeskCreateInfo;
DeskCreateInfo.hEvent = hEvent;
DeskCreateInfo.Tray = Tray;
DeskCreateInfo.hDesktop = NULL;
hThread = CreateThread(NULL,
0,
DesktopThreadProc,
(PVOID)&DeskCreateInfo,
0,
&DesktopThreadId);
if (hThread != NULL)
{
Handles[0] = hThread;
Handles[1] = hEvent;
for (;;)
{
WaitResult = MsgWaitForMultipleObjects(sizeof(Handles) / sizeof(Handles[0]),
Handles,
FALSE,
INFINITE,
QS_ALLEVENTS);
if (WaitResult == WAIT_OBJECT_0 + (sizeof(Handles) / sizeof(Handles[0])))
TrayProcessMessages(Tray);
else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
{
hDesktop = DeskCreateInfo.hDesktop;
break;
}
}
CloseHandle(hThread);
}
CloseHandle(hEvent);
}
return hDesktop;
}
VOID
DesktopDestroyShellWindow(IN HANDLE hDesktop)
{
return;
}

View File

@ -0,0 +1,144 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
HANDLE WINAPI _SHCreateDesktop(IShellDesktopTray *ShellDesk);
BOOL WINAPI _SHDesktopMessageLoop(HANDLE hDesktop);
class CDesktopThread
{
HANDLE hEvent;
HANDLE hDesktop;
CComPtr<ITrayWindow> Tray;
DWORD DesktopThreadProc()
{
CComPtr<IShellDesktopTray> pSdt;
HANDLE hDesktop;
HRESULT hRet;
OleInitialize(NULL);
hRet = Tray->QueryInterface(IID_PPV_ARG(IShellDesktopTray, &pSdt));
if (!SUCCEEDED(hRet))
return 1;
hDesktop = _SHCreateDesktop(pSdt);
if (hDesktop == NULL)
return 1;
if (!SetEvent(hEvent))
{
/* Failed to notify that we initialized successfully, kill ourselves
to make the main thread wake up! */
return 1;
}
_SHDesktopMessageLoop(hDesktop);
/* FIXME: Properly rundown the main thread! */
ExitProcess(0);
return 0;
}
static DWORD CALLBACK s_DesktopThreadProc(IN OUT LPVOID lpParameter)
{
return reinterpret_cast<CDesktopThread*>(lpParameter)->DesktopThreadProc();
}
public:
CDesktopThread() :
hEvent(NULL),
hDesktop(NULL),
Tray(NULL)
{
}
HANDLE Initialize(IN OUT ITrayWindow *pTray)
{
HANDLE hThread;
HANDLE Handles[2];
Tray = pTray;
hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (!hEvent)
return NULL;
hThread = CreateThread(NULL, 0, s_DesktopThreadProc, (PVOID)this, 0, NULL);
if (!hThread)
{
CloseHandle(hEvent);
return NULL;
}
Handles[0] = hThread;
Handles[1] = hEvent;
for (;;)
{
DWORD WaitResult = MsgWaitForMultipleObjects(_countof(Handles), Handles, FALSE, INFINITE, QS_ALLEVENTS);
if (WaitResult == WAIT_OBJECT_0 + _countof(Handles))
{
TrayProcessMessages(Tray);
}
else if (WaitResult != WAIT_FAILED && WaitResult != WAIT_OBJECT_0)
{
break;
}
}
CloseHandle(hThread);
CloseHandle(hEvent);
return hDesktop;
}
void Destroy()
{
return;
}
} * g_pDesktopWindowInstance;
HANDLE
DesktopCreateWindow(IN OUT ITrayWindow *Tray)
{
if (!g_pDesktopWindowInstance)
{
g_pDesktopWindowInstance = new CDesktopThread();
}
if (!g_pDesktopWindowInstance)
return NULL;
return g_pDesktopWindowInstance->Initialize(Tray);
}
VOID
DesktopDestroyShellWindow(IN HANDLE hDesktop)
{
if (g_pDesktopWindowInstance)
{
g_pDesktopWindowInstance->Destroy();
}
}

View File

@ -1,411 +0,0 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
static const IDropTargetVtbl IDropTargetImpl_Vtbl;
/*
* IDropTarget
*/
typedef struct
{
const IDropTargetVtbl *lpVtbl;
LONG Ref;
HWND hwndTarget;
IDropTargetHelper *DropTargetHelper;
PVOID Context;
BOOL CanDrop;
DROPTARGET_CALLBACKS Callbacks;
DWORD FormatsCount;
FORMATETC Formats[0];
} IDropTargetImpl;
static IUnknown *
IUnknown_from_impl(IDropTargetImpl *This)
{
return (IUnknown *)&This->lpVtbl;
}
static IDropTarget *
IDropTarget_from_impl(IDropTargetImpl *This)
{
return (IDropTarget *)&This->lpVtbl;
}
static IDropTargetImpl *
impl_from_IDropTarget(IDropTarget *iface)
{
return (IDropTargetImpl *)((ULONG_PTR)iface - FIELD_OFFSET(IDropTargetImpl,
lpVtbl));
}
static VOID
IDropTargetImpl_Free(IDropTargetImpl *This)
{
IDropTargetHelper_Release(This->DropTargetHelper);
HeapFree(hProcessHeap,
0,
This);
}
static ULONG STDMETHODCALLTYPE
IDropTargetImpl_Release(IN OUT IDropTarget *iface)
{
IDropTargetImpl *This = impl_from_IDropTarget(iface);
ULONG Ret;
Ret = InterlockedDecrement(&This->Ref);
if (Ret == 0)
IDropTargetImpl_Free(This);
return Ret;
}
static ULONG STDMETHODCALLTYPE
IDropTargetImpl_AddRef(IN OUT IDropTarget *iface)
{
IDropTargetImpl *This = impl_from_IDropTarget(iface);
return InterlockedIncrement(&This->Ref);
}
static HRESULT STDMETHODCALLTYPE
IDropTargetImpl_QueryInterface(IN OUT IDropTarget *iface,
IN REFIID riid,
OUT LPVOID *ppvObj)
{
IDropTargetImpl *This;
if (ppvObj == NULL)
return E_POINTER;
This = impl_from_IDropTarget(iface);
if (IsEqualIID(riid,
&IID_IUnknown))
{
*ppvObj = IUnknown_from_impl(This);
}
else if (IsEqualIID(riid,
&IID_IDropTarget))
{
*ppvObj = IDropTarget_from_impl(This);
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
IDropTargetImpl_AddRef(iface);
return S_OK;
}
IDropTarget *
CreateDropTarget(IN HWND hwndTarget,
IN DWORD nSupportedFormats,
IN const FORMATETC *Formats OPTIONAL,
IN PVOID Context OPTIONAL,
IN const DROPTARGET_CALLBACKS *Callbacks OPTIONAL)
{
IDropTargetImpl *This;
HRESULT hr;
This = HeapAlloc(hProcessHeap,
HEAP_ZERO_MEMORY,
FIELD_OFFSET(IDropTargetImpl,
Formats[nSupportedFormats]));
if (This != NULL)
{
This->lpVtbl = &IDropTargetImpl_Vtbl;
This->Ref = 1;
This->hwndTarget = hwndTarget;
This->FormatsCount = nSupportedFormats;
if (nSupportedFormats != 0)
{
CopyMemory(This->Formats,
Formats,
sizeof(Formats[0]) * nSupportedFormats);
}
This->Context = Context;
if (Callbacks != NULL)
{
CopyMemory(&This->Callbacks,
Callbacks,
sizeof(*Callbacks));
}
hr = CoCreateInstance(&CLSID_DragDropHelper,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IDropTargetHelper,
(PVOID *)&This->DropTargetHelper);
if (!SUCCEEDED(hr))
{
HeapFree(hProcessHeap,
0,
This);
return NULL;
}
return IDropTarget_from_impl(This);
}
return NULL;
}
static const FORMATETC *
IDropTargetImpl_FindSupportedFormat(IN OUT IDropTargetImpl *This,
IN IDataObject *pDataObject)
{
FORMATETC *Current, *Last;
HRESULT hr;
/* NOTE: we could use IDataObject::EnumFormatEtc(),
but this appears to be a lot easier! */
Last = This->Formats + This->FormatsCount;
for (Current = This->Formats;
Current != Last;
Current++)
{
hr = IDataObject_QueryGetData(pDataObject,
Current);
if (SUCCEEDED(hr))
return Current;
}
return NULL;
}
static HRESULT STDMETHODCALLTYPE
IDropTargetImpl_DragEnter(IN OUT IDropTarget *iface,
IN IDataObject *pDataObject,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect)
{
IDropTargetImpl *This = impl_from_IDropTarget(iface);
const FORMATETC *Format;
HRESULT hr;
if (pDataObject == NULL)
return E_INVALIDARG;
This->CanDrop = FALSE;
hr = IDropTargetHelper_DragEnter(This->DropTargetHelper,
This->hwndTarget,
pDataObject,
(POINT *)&pt,
*pdwEffect);
if (SUCCEEDED(hr))
{
Format = IDropTargetImpl_FindSupportedFormat(This,
pDataObject);
if (Format != NULL)
{
/* We found a format that we support! */
if (This->Callbacks.OnDragEnter != NULL)
{
hr = This->Callbacks.OnDragEnter(iface,
This->Context,
Format,
grfKeyState,
pt,
pdwEffect);
if (SUCCEEDED(hr))
{
if (hr == S_OK)
This->CanDrop = TRUE;
else
{
/* Special return value by the callback routine,
doesn't want to allow dragging */
*pdwEffect = DROPEFFECT_NONE;
}
hr = S_OK;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
hr = S_OK;
}
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
return hr;
}
static HRESULT STDMETHODCALLTYPE
IDropTargetImpl_DragOver(IN OUT IDropTarget *iface,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect)
{
IDropTargetImpl *This = impl_from_IDropTarget(iface);
HRESULT hr;
hr = IDropTargetHelper_DragOver(This->DropTargetHelper,
(POINT *)&pt,
*pdwEffect);
if (SUCCEEDED(hr))
{
if (This->CanDrop)
{
if (This->Callbacks.OnDragOver != NULL)
{
hr = This->Callbacks.OnDragOver(iface,
This->Context,
grfKeyState,
pt,
pdwEffect);
if (SUCCEEDED(hr))
{
if (hr != S_OK)
{
/* Special return value by the callback routine,
doesn't want to allow dropping here */
*pdwEffect = DROPEFFECT_NONE;
}
hr = S_OK;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
hr = S_OK;
}
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
return hr;
}
static HRESULT STDMETHODCALLTYPE
IDropTargetImpl_DragLeave(IN OUT IDropTarget *iface)
{
IDropTargetImpl *This = impl_from_IDropTarget(iface);
HRESULT hr;
hr = IDropTargetHelper_DragLeave(This->DropTargetHelper);
if (SUCCEEDED(hr))
{
if (This->Callbacks.OnDragLeave != NULL)
{
hr = This->Callbacks.OnDragLeave(iface,
This->Context);
}
}
return hr;
}
static HRESULT STDMETHODCALLTYPE
IDropTargetImpl_Drop(IN OUT IDropTarget *iface,
IN IDataObject *pDataObject,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect)
{
IDropTargetImpl *This = impl_from_IDropTarget(iface);
const FORMATETC *Format;
HRESULT hr;
if (pDataObject == NULL)
return E_INVALIDARG;
hr = IDropTargetHelper_Drop(This->DropTargetHelper,
pDataObject,
(POINT *)&pt,
*pdwEffect);
if (SUCCEEDED(hr) && This->CanDrop)
{
Format = IDropTargetImpl_FindSupportedFormat(This,
pDataObject);
if (Format != NULL)
{
/* We found a format that we support! */
if (This->Callbacks.OnDrop != NULL)
{
hr = This->Callbacks.OnDrop(iface,
This->Context,
Format,
grfKeyState,
pt,
pdwEffect);
if (SUCCEEDED(hr))
{
if (hr == S_OK)
This->CanDrop = TRUE;
else
{
/* Special return value by the callback routine,
doesn't want to allow dragging */
*pdwEffect = DROPEFFECT_NONE;
}
hr = S_OK;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
hr = S_OK;
}
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
return hr;
}
static const IDropTargetVtbl IDropTargetImpl_Vtbl =
{
/* IUnknown */
IDropTargetImpl_QueryInterface,
IDropTargetImpl_AddRef,
IDropTargetImpl_Release,
/* IDropTarget */
IDropTargetImpl_DragEnter,
IDropTargetImpl_DragOver,
IDropTargetImpl_DragLeave,
IDropTargetImpl_Drop
};

View File

@ -0,0 +1,314 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
class CDropTarget :
public CComCoClass<CDropTarget>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IDropTarget
{
HWND hwndTarget;
CComPtr<IDropTargetHelper> DropTargetHelper;
PVOID Context;
BOOL CanDrop;
DROPTARGET_CALLBACKS Callbacks;
DWORD FormatsCount;
FORMATETC* Formats;
const FORMATETC *
FindSupportedFormat(IN IDataObject *pDataObject)
{
FORMATETC *Current, *Last;
HRESULT hr;
/* NOTE: we could use IDataObject::EnumFormatEtc(),
but this appears to be a lot easier! */
Last = Formats + FormatsCount;
for (Current = Formats;
Current != Last;
Current++)
{
hr = pDataObject->QueryGetData(Current);
if (SUCCEEDED(hr))
return Current;
}
return NULL;
}
public:
CDropTarget() :
hwndTarget(NULL),
Context(NULL),
CanDrop(FALSE),
FormatsCount(0),
Formats(NULL)
{
ZeroMemory(&Callbacks, sizeof(Callbacks));
}
virtual ~CDropTarget() { }
HRESULT Initialize(IN HWND hwndTarget,
IN DWORD nSupportedFormats,
IN const FORMATETC *formats OPTIONAL,
IN PVOID Context OPTIONAL,
IN const DROPTARGET_CALLBACKS *Callbacks OPTIONAL)
{
this->hwndTarget = hwndTarget;
FormatsCount = nSupportedFormats;
if (nSupportedFormats != 0)
{
Formats = new FORMATETC[nSupportedFormats];
CopyMemory(Formats,
formats,
sizeof(formats[0]) * nSupportedFormats);
}
this->Context = Context;
if (Callbacks != NULL)
{
CopyMemory(&this->Callbacks,
Callbacks,
sizeof(*Callbacks));
}
HRESULT hr = CoCreateInstance(CLSID_DragDropHelper,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IDropTargetHelper, &DropTargetHelper));
return hr;
}
virtual HRESULT STDMETHODCALLTYPE DragEnter(
IN IDataObject *pDataObject,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect)
{
const FORMATETC *Format;
HRESULT hr;
if (pDataObject == NULL)
return E_INVALIDARG;
CanDrop = FALSE;
hr = DropTargetHelper->DragEnter(
hwndTarget,
pDataObject,
(POINT *) &pt,
*pdwEffect);
if (SUCCEEDED(hr))
{
Format = FindSupportedFormat(
pDataObject);
if (Format != NULL)
{
/* We found a format that we support! */
if (Callbacks.OnDragEnter != NULL)
{
hr = Callbacks.OnDragEnter(this,
Context,
Format,
grfKeyState,
pt,
pdwEffect);
if (SUCCEEDED(hr))
{
if (hr == S_OK)
CanDrop = TRUE;
else
{
/* Special return value by the callback routine,
doesn't want to allow dragging */
*pdwEffect = DROPEFFECT_NONE;
}
hr = S_OK;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
hr = S_OK;
}
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
return hr;
}
virtual HRESULT STDMETHODCALLTYPE DragOver(
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect)
{
HRESULT hr;
hr = DropTargetHelper->DragOver(
(POINT *) &pt,
*pdwEffect);
if (SUCCEEDED(hr))
{
if (CanDrop)
{
if (Callbacks.OnDragOver != NULL)
{
hr = Callbacks.OnDragOver(this,
Context,
grfKeyState,
pt,
pdwEffect);
if (SUCCEEDED(hr))
{
if (hr != S_OK)
{
/* Special return value by the callback routine,
doesn't want to allow dropping here */
*pdwEffect = DROPEFFECT_NONE;
}
hr = S_OK;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
hr = S_OK;
}
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
return hr;
}
virtual HRESULT STDMETHODCALLTYPE DragLeave()
{
HRESULT hr;
hr = DropTargetHelper->DragLeave();
if (SUCCEEDED(hr))
{
if (Callbacks.OnDragLeave != NULL)
{
hr = Callbacks.OnDragLeave(this,
Context);
}
}
return hr;
}
virtual HRESULT STDMETHODCALLTYPE Drop(
IN IDataObject *pDataObject,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect)
{
const FORMATETC *Format;
HRESULT hr;
if (pDataObject == NULL)
return E_INVALIDARG;
hr = DropTargetHelper->Drop(
pDataObject,
(POINT *) &pt,
*pdwEffect);
if (SUCCEEDED(hr) && CanDrop)
{
Format = FindSupportedFormat(pDataObject);
if (Format != NULL)
{
/* We found a format that we support! */
if (Callbacks.OnDrop != NULL)
{
hr = Callbacks.OnDrop(this,
Context,
Format,
grfKeyState,
pt,
pdwEffect);
if (SUCCEEDED(hr))
{
if (hr == S_OK)
CanDrop = TRUE;
else
{
/* Special return value by the callback routine,
doesn't want to allow dragging */
*pdwEffect = DROPEFFECT_NONE;
}
hr = S_OK;
}
else
{
*pdwEffect = DROPEFFECT_NONE;
hr = S_OK;
}
}
else
*pdwEffect = DROPEFFECT_NONE;
}
else
*pdwEffect = DROPEFFECT_NONE;
}
return hr;
}
DECLARE_NOT_AGGREGATABLE(CDropTarget)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CDropTarget)
COM_INTERFACE_ENTRY_IID(IID_IDropTarget, IDropTarget)
END_COM_MAP()
};
IDropTarget *
CreateDropTarget(IN HWND hwndTarget,
IN DWORD nSupportedFormats,
IN const FORMATETC *Formats OPTIONAL,
IN PVOID Context OPTIONAL,
IN const DROPTARGET_CALLBACKS *Callbacks OPTIONAL)
{
IDropTarget *dt;
HRESULT hr = ShellObjectCreatorInit<CDropTarget>(hwndTarget, nSupportedFormats, Formats, Context, Callbacks, IID_IDropTarget, &dt);
if (FAILED_UNEXPECTEDLY(hr))
return NULL;
return dt;
}

View File

@ -1,471 +0,0 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
#include <winver.h>
HINSTANCE hExplorerInstance;
HMODULE hUser32;
HANDLE hProcessHeap;
HKEY hkExplorer = NULL;
DRAWCAPTEMP DrawCapTemp = NULL;
typedef struct _LANGCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
} LANGCODEPAGE, *PLANGCODEPAGE;
LONG
SetWindowStyle(IN HWND hWnd,
IN LONG dwStyleMask,
IN LONG dwStyle)
{
LONG PrevStyle, Style;
ASSERT((~dwStyleMask & dwStyle) == 0);
PrevStyle = GetWindowLong(hWnd,
GWL_STYLE);
if (PrevStyle != 0 &&
(PrevStyle & dwStyleMask) != dwStyle)
{
Style = PrevStyle & ~dwStyleMask;
Style |= dwStyle;
PrevStyle = SetWindowLong(hWnd,
GWL_STYLE,
Style);
}
return PrevStyle;
}
LONG
SetWindowExStyle(IN HWND hWnd,
IN LONG dwStyleMask,
IN LONG dwStyle)
{
LONG PrevStyle, Style;
ASSERT((~dwStyleMask & dwStyle) == 0);
PrevStyle = GetWindowLong(hWnd,
GWL_EXSTYLE);
if (PrevStyle != 0 &&
(PrevStyle & dwStyleMask) != dwStyle)
{
Style = PrevStyle & ~dwStyleMask;
Style |= dwStyle;
PrevStyle = SetWindowLong(hWnd,
GWL_EXSTYLE,
Style);
}
return PrevStyle;
}
HMENU
LoadPopupMenu(IN HINSTANCE hInstance,
IN LPCTSTR lpMenuName)
{
HMENU hMenu, hSubMenu = NULL;
hMenu = LoadMenu(hInstance,
lpMenuName);
if (hMenu != NULL)
{
hSubMenu = GetSubMenu(hMenu,
0);
if (hSubMenu != NULL &&
!RemoveMenu(hMenu,
0,
MF_BYPOSITION))
{
hSubMenu = NULL;
}
DestroyMenu(hMenu);
}
return hSubMenu;
}
HMENU
FindSubMenu(IN HMENU hMenu,
IN UINT uItem,
IN BOOL fByPosition)
{
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
if (GetMenuItemInfo(hMenu,
uItem,
fByPosition,
&mii))
{
return mii.hSubMenu;
}
return NULL;
}
BOOL
GetCurrentLoggedOnUserName(OUT LPTSTR szBuffer,
IN DWORD dwBufferSize)
{
DWORD dwType;
DWORD dwSize;
/* Query the user name from the registry */
dwSize = (dwBufferSize * sizeof(TCHAR)) - 1;
if (RegQueryValueEx(hkExplorer,
TEXT("Logon User Name"),
0,
&dwType,
(LPBYTE)szBuffer,
&dwSize) == ERROR_SUCCESS &&
(dwSize / sizeof(TCHAR)) > 1 &&
szBuffer[0] != _T('\0'))
{
szBuffer[dwSize / sizeof(TCHAR)] = _T('\0');
return TRUE;
}
/* Fall back to GetUserName() */
dwSize = dwBufferSize;
if (!GetUserName(szBuffer,
&dwSize))
{
szBuffer[0] = _T('\0');
return FALSE;
}
return TRUE;
}
BOOL
FormatMenuString(IN HMENU hMenu,
IN UINT uPosition,
IN UINT uFlags,
...)
{
va_list vl;
MENUITEMINFO mii;
TCHAR szBuf[128];
TCHAR szBufFmt[128];
/* Find the menu item and read the formatting string */
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING;
mii.dwTypeData = (LPTSTR)szBufFmt;
mii.cch = sizeof(szBufFmt) / sizeof(szBufFmt[0]);
if (GetMenuItemInfo(hMenu,
uPosition,
uFlags,
&mii))
{
/* Format the string */
va_start(vl, uFlags);
_vsntprintf(szBuf,
(sizeof(szBuf) / sizeof(szBuf[0])) - 1,
szBufFmt,
vl);
va_end(vl);
szBuf[(sizeof(szBuf) / sizeof(szBuf[0])) - 1] = _T('\0');
/* Update the menu item */
mii.dwTypeData = (LPTSTR)szBuf;
if (SetMenuItemInfo(hMenu,
uPosition,
uFlags,
&mii))
{
return TRUE;
}
}
return FALSE;
}
BOOL
GetExplorerRegValueSet(IN HKEY hKey,
IN LPCTSTR lpSubKey,
IN LPCTSTR lpValue)
{
TCHAR szBuffer[MAX_PATH];
HKEY hkSubKey;
DWORD dwType, dwSize;
BOOL Ret = FALSE;
StringCbCopy(szBuffer, sizeof(szBuffer),
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"));
if (FAILED(StringCbCat(szBuffer, sizeof(szBuffer),
_T("\\"))))
return FALSE;
if (FAILED(StringCbCat(szBuffer, sizeof(szBuffer),
lpSubKey)))
return FALSE;
dwSize = sizeof(szBuffer);
if (RegOpenKeyEx(hKey,
szBuffer,
0,
KEY_QUERY_VALUE,
&hkSubKey) == ERROR_SUCCESS)
{
ZeroMemory(szBuffer,
sizeof(szBuffer));
if (RegQueryValueEx(hkSubKey,
lpValue,
0,
&dwType,
(LPBYTE)szBuffer,
&dwSize) == ERROR_SUCCESS)
{
if (dwType == REG_DWORD && dwSize == sizeof(DWORD))
Ret = *((PDWORD)szBuffer) != 0;
else if (dwSize > 0)
Ret = *((PUCHAR)szBuffer) != 0;
}
RegCloseKey(hkSubKey);
}
return Ret;
}
static BOOL
SetShellReadyEvent(IN LPCTSTR lpEventName)
{
HANDLE hEvent;
hEvent = OpenEvent(EVENT_MODIFY_STATE,
FALSE,
lpEventName);
if (hEvent != NULL)
{
SetEvent(hEvent);
CloseHandle(hEvent);
return TRUE;
}
return FALSE;
}
BOOL
GetVersionInfoString(IN TCHAR *szFileName,
IN TCHAR *szVersionInfo,
OUT TCHAR *szBuffer,
IN UINT cbBufLen)
{
LPVOID lpData = NULL;
TCHAR szSubBlock[128];
TCHAR *lpszLocalBuf = NULL;
LANGID UserLangId;
PLANGCODEPAGE lpTranslate = NULL;
DWORD dwLen;
DWORD dwHandle;
UINT cbTranslate;
UINT cbLen;
BOOL bRet = FALSE;
unsigned int i;
dwLen = GetFileVersionInfoSize(szFileName, &dwHandle);
if (dwLen > 0)
{
lpData = HeapAlloc(hProcessHeap, 0, dwLen);
if (lpData != NULL)
{
if (GetFileVersionInfo(szFileName,
0,
dwLen,
lpData) != 0)
{
UserLangId = GetUserDefaultLangID();
VerQueryValue(lpData,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID *)&lpTranslate,
&cbTranslate);
for (i = 0; i < cbTranslate / sizeof(LANGCODEPAGE); i++)
{
/* If the bottom eight bits of the language id's
match, use this version information (since this
means that the version information and the users
default language are the same). */
if ((lpTranslate[i].wLanguage & 0xFF) ==
(UserLangId & 0xFF))
{
wnsprintf(szSubBlock,
sizeof(szSubBlock) / sizeof(szSubBlock[0]),
TEXT("\\StringFileInfo\\%04X%04X\\%s"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage,
szVersionInfo);
if (VerQueryValue(lpData,
szSubBlock,
(LPVOID *)&lpszLocalBuf,
&cbLen) != 0)
{
_tcsncpy(szBuffer, lpszLocalBuf, cbBufLen / sizeof(*szBuffer));
bRet = TRUE;
break;
}
}
}
}
HeapFree(hProcessHeap, 0, lpData);
lpData = NULL;
}
}
return bRet;
}
static VOID
HideMinimizedWindows(IN BOOL bHide)
{
MINIMIZEDMETRICS mm;
mm.cbSize = sizeof(mm);
if (!SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
{
DbgPrint("SystemParametersInfo failed with %lu\n", GetLastError());
return;
}
if (bHide)
mm.iArrange |= ARW_HIDE;
else
mm.iArrange &= ~ARW_HIDE;
if (!SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
DbgPrint("SystemParametersInfo failed with %lu\n", GetLastError());
}
INT WINAPI
_tWinMain(IN HINSTANCE hInstance,
IN HINSTANCE hPrevInstance,
IN LPTSTR lpCmdLine,
IN INT nCmdShow)
{
ITrayWindow *Tray = NULL;
HANDLE hShellDesktop = NULL;
BOOL CreateShellDesktop = FALSE;
if (RegOpenKey(HKEY_CURRENT_USER,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
&hkExplorer) != ERROR_SUCCESS)
{
TCHAR Message[256];
LoadString(hInstance, IDS_STARTUP_ERROR, Message, 256);
MessageBox(NULL, Message, NULL, MB_ICONERROR);
return 1;
}
hExplorerInstance = hInstance;
hProcessHeap = GetProcessHeap();
LoadAdvancedSettings();
hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
if (hUser32 != NULL)
{
DrawCapTemp = (DRAWCAPTEMP)GetProcAddress(hUser32,
PROC_NAME_DRAWCAPTIONTEMP);
}
InitCommonControls();
OleInitialize(NULL);
ProcessStartupItems();
if (GetShellWindow() == NULL)
CreateShellDesktop = TRUE;
/* FIXME - initialize SSO Thread */
if (CreateShellDesktop)
{
/* Initialize shell dde support */
ShellDDEInit(TRUE);
/* Initialize shell icons */
FileIconInit(TRUE);
/* Initialize CLSID_ShellWindows class */
WinList_Init();
if (RegisterTrayWindowClass() && RegisterTaskSwitchWndClass())
{
Tray = CreateTrayWindow();
/* This not only hides the minimized window captions in the bottom
left screen corner, but is also needed in order to receive
HSHELL_* notification messages (which are required for taskbar
buttons to work right) */
HideMinimizedWindows(TRUE);
if (Tray != NULL)
hShellDesktop = DesktopCreateWindow(Tray);
}
/* WinXP: Notify msgina to hide the welcome screen */
if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
}
else
{
/* A shell is already loaded. Parse the command line arguments
and unless we need to do something specific simply display
the desktop in a separate explorer window */
/* FIXME */
}
if (Tray != NULL)
{
RegisterHotKey(NULL, IDHK_RUN, MOD_WIN, 'R');
TrayMessageLoop(Tray);
HideMinimizedWindows(FALSE);
ITrayWindow_Release(Tray);
UnregisterTrayWindowClass();
}
if (hShellDesktop != NULL)
DesktopDestroyShellWindow(hShellDesktop);
/* FIXME - shutdown SSO Thread */
OleUninitialize();
RegCloseKey(hkExplorer);
hkExplorer = NULL;
return 0;
}

View File

@ -0,0 +1,239 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
#include <shlwapi_undoc.h>
DWORD WINAPI _WinList_Init(void);
void WINAPI _ShellDDEInit(BOOL bInit);
HINSTANCE hExplorerInstance;
HMODULE hUser32;
HANDLE hProcessHeap;
HKEY hkExplorer = NULL;
DRAWCAPTEMP DrawCapTemp = NULL;
class CExplorerModule : public CComModule
{
public:
};
BEGIN_OBJECT_MAP(ObjectMap)
END_OBJECT_MAP()
CExplorerModule gModule;
CAtlWinModule gWinModule;
void *operator new (size_t, void *buf)
{
return buf;
}
static VOID InitializeAtlModule(HINSTANCE hInstance, BOOL bInitialize)
{
if (bInitialize)
{
/* HACK - the global constructors don't run, so I placement new them here */
new (&gModule) CExplorerModule;
new (&gWinModule) CAtlWinModule;
new (&_AtlBaseModule) CAtlBaseModule;
new (&_AtlComModule) CAtlComModule;
gModule.Init(ObjectMap, hInstance, NULL);
}
else
{
gModule.Term();
}
}
#if !WIN7_COMPAT_MODE
static BOOL
SetShellReadyEvent(IN LPCTSTR lpEventName)
{
HANDLE hEvent;
hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, lpEventName);
if (hEvent != NULL)
{
SetEvent(hEvent);
CloseHandle(hEvent);
return TRUE;
}
return FALSE;
}
static VOID
HideMinimizedWindows(IN BOOL bHide)
{
MINIMIZEDMETRICS mm;
mm.cbSize = sizeof(mm);
if (!SystemParametersInfo(SPI_GETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
{
ERR("SystemParametersInfo failed with %lu\n", GetLastError());
return;
}
if (bHide)
mm.iArrange |= ARW_HIDE;
else
mm.iArrange &= ~ARW_HIDE;
if (!SystemParametersInfo(SPI_SETMINIMIZEDMETRICS, sizeof(mm), &mm, 0))
ERR("SystemParametersInfo failed with %lu\n", GetLastError());
}
static INT
StartWithCommandLine(IN HINSTANCE hInstance)
{
BOOL b = FALSE;
EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 };
if (SHExplorerParseCmdLine(&parseResults))
b = SHCreateFromDesktop(&parseResults);
if (parseResults.strPath)
SHFree(parseResults.strPath);
if (parseResults.pidlPath)
ILFree(parseResults.pidlPath);
if (parseResults.pidlRoot)
ILFree(parseResults.pidlRoot);
return b;
}
#endif
static INT
StartWithDesktop(IN HINSTANCE hInstance)
{
InitializeAtlModule(hInstance, TRUE);
if (RegOpenKey(HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer",
&hkExplorer) != ERROR_SUCCESS)
{
WCHAR Message[256];
LoadString(hInstance, IDS_STARTUP_ERROR, Message, 256);
MessageBox(NULL, Message, NULL, MB_ICONERROR);
return 1;
}
hExplorerInstance = hInstance;
hProcessHeap = GetProcessHeap();
LoadAdvancedSettings();
hUser32 = GetModuleHandle(TEXT("USER32.DLL"));
if (hUser32 != NULL)
{
DrawCapTemp = (DRAWCAPTEMP) GetProcAddress(hUser32, PROC_NAME_DRAWCAPTIONTEMP);
}
InitCommonControls();
OleInitialize(NULL);
#if !WIN7_COMPAT_MODE
ProcessStartupItems();
/* Initialize shell dde support */
_ShellDDEInit(TRUE);
#endif
/* Initialize shell icons */
FileIconInit(TRUE);
/* Initialize CLSID_ShellWindows class */
_WinList_Init();
CComPtr<ITrayWindow> Tray;
CreateTrayWindow(&Tray);
#if !WIN7_COMPAT_MODE
/* This not only hides the minimized window captions in the bottom
left screen corner, but is also needed in order to receive
HSHELL_* notification messages (which are required for taskbar
buttons to work right) */
HideMinimizedWindows(TRUE);
HANDLE hShellDesktop = NULL;
if (Tray != NULL)
hShellDesktop = DesktopCreateWindow(Tray);
/* WinXP: Notify msgina to hide the welcome screen */
if (!SetShellReadyEvent(TEXT("msgina: ShellReadyEvent")))
SetShellReadyEvent(TEXT("Global\\msgina: ShellReadyEvent"));
#endif
if (Tray != NULL)
{
#if !WIN7_COMPAT_MODE
RegisterHotKey(NULL, IDHK_RUN, MOD_WIN, 'R');
#endif
TrayMessageLoop(Tray);
#if !WIN7_COMPAT_MODE
HideMinimizedWindows(FALSE);
#endif
}
#if !WIN7_COMPAT_MODE
if (hShellDesktop != NULL)
DesktopDestroyShellWindow(hShellDesktop);
#endif
OleUninitialize();
RegCloseKey(hkExplorer);
hkExplorer = NULL;
InitializeAtlModule(hInstance, FALSE);
return 0;
}
INT WINAPI
_tWinMain(IN HINSTANCE hInstance,
IN HINSTANCE hPrevInstance,
IN LPTSTR lpCmdLine,
IN INT nCmdShow)
{
#if !WIN7_COMPAT_MODE
BOOL CreateShellDesktop = FALSE;
TRACE("Explorer starting... Commandline: %S\n", lpCmdLine);
/*
* Set our shutdown parameters: we want to shutdown the very last,
* but before any TaskMgr instance (which has a shutdown level of 1).
*/
SetProcessShutdownParameters(2, 0);
if (GetShellWindow() == NULL)
CreateShellDesktop = TRUE;
if (!CreateShellDesktop)
{
return StartWithCommandLine(hInstance);
}
#endif
return StartWithDesktop(hInstance);
}

View File

@ -1,6 +1,8 @@
#ifndef _EXPLORER_PRECOMP__H_
#define _EXPLORER_PRECOMP__H_
#define WIN7_COMPAT_MODE 0
#include <stdio.h>
#include <tchar.h>
@ -16,6 +18,9 @@
#include <wingdi.h>
#include <winnls.h>
#include <wincon.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlwin.h>
#include <shellapi.h>
#include <shlobj.h>
#include <shlobj_undoc.h>
@ -23,68 +28,39 @@
#include <shlguid_undoc.h>
#include <uxtheme.h>
#include <strsafe.h>
#include <undocuser.h>
#include <undocshell.h>
#include <rosctrls.h>
#include "tmschema.h"
#include "resource.h"
#include "comcsup.h"
#include <wine/debug.h>
WINE_DEFAULT_DEBUG_CHANNEL(explorernew);
/* dynamic imports due to lack of support in msvc linker libs */
typedef INT (APIENTRY *REGSHELLHOOK)(HWND, DWORD);
typedef INT(APIENTRY *REGSHELLHOOK)(HWND, DWORD);
#ifdef UNICODE
#define PROC_NAME_DRAWCAPTIONTEMP "DrawCaptionTempW"
typedef BOOL (APIENTRY *DRAWCAPTEMP)(HWND, HDC, const RECT*, HFONT, HICON, LPCWSTR, UINT);
typedef BOOL(APIENTRY *DRAWCAPTEMP)(HWND, HDC, const RECT*, HFONT, HICON, LPCWSTR, UINT);
#else
#define PROC_NAME_DRAWCAPTIONTEMP "DrawCaptionTempA"
typedef BOOL (APIENTRY *DRAWCAPTEMP)(HWND, HDC, const RECT*, HFONT, HICON, LPCSTR, UINT);
#endif
typedef HRESULT (APIENTRY *SHINVDEFCMD)(HWND, IShellFolder*, LPCITEMIDLIST);
typedef HRESULT(APIENTRY *SHINVDEFCMD)(HWND, IShellFolder*, LPCITEMIDLIST);
typedef void (APIENTRY *RUNFILEDLG)(HWND, HICON, LPCWSTR, LPCWSTR, LPCWSTR, UINT);
typedef void (APIENTRY *EXITWINDLG)(HWND);
typedef HRESULT (APIENTRY *SHWINHELP)(HWND, LPWSTR, UINT, DWORD);
typedef HRESULT(APIENTRY *SHWINHELP)(HWND, LPWSTR, UINT, DWORD);
/* Constants for RunFileDlg */
#define RFF_CALCDIRECTORY 0x04 /* Calculates the working directory from the file name. */
static __inline ULONG
Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...)
{
char szMsg[512];
char *szMsgStart;
const char *fname;
va_list vl;
ULONG uRet;
fname = strrchr(filename, '\\');
if (fname == NULL)
{
fname = strrchr(filename, '/');
if (fname != NULL)
fname++;
}
else
fname++;
if (fname == NULL)
fname = filename;
szMsgStart = szMsg + sprintf(szMsg, "%s:%d: ", fname, line);
va_start(vl, lpFormat);
uRet = (ULONG)vsprintf(szMsgStart, lpFormat, vl);
va_end(vl);
OutputDebugStringA(szMsg);
return uRet;
}
#define ASSERT(cond) \
do if (!(cond)) { \
Win32DbgPrint(__FILE__, __LINE__, "ASSERTION %s FAILED!\n", #cond); \
} while (0)
#define DbgPrint(fmt, ...) \
Win32DbgPrint(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
} while (0)
extern HINSTANCE hExplorerInstance;
extern HMODULE hUser32;
@ -98,33 +74,33 @@ extern DRAWCAPTEMP DrawCapTemp;
typedef struct _DROPTARGET_CALLBACKS
{
HRESULT (*OnDragEnter)(IN IDropTarget *pDropTarget,
IN PVOID Context,
IN const FORMATETC *Format,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect);
HRESULT (*OnDragOver)(IN IDropTarget *pDropTarget,
HRESULT(*OnDragEnter)(IN IDropTarget *pDropTarget,
IN PVOID Context,
IN const FORMATETC *Format,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect);
HRESULT (*OnDragLeave)(IN IDropTarget *pDropTarget,
IN PVOID Context);
HRESULT (*OnDrop)(IN IDropTarget *pDropTarget,
IN PVOID Context,
IN const FORMATETC *Format,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect);
HRESULT(*OnDragOver)(IN IDropTarget *pDropTarget,
IN PVOID Context,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect);
HRESULT(*OnDragLeave)(IN IDropTarget *pDropTarget,
IN PVOID Context);
HRESULT(*OnDrop)(IN IDropTarget *pDropTarget,
IN PVOID Context,
IN const FORMATETC *Format,
IN DWORD grfKeyState,
IN POINTL pt,
IN OUT DWORD *pdwEffect);
} DROPTARGET_CALLBACKS, *PDROPTARGET_CALLBACKS;
IDropTarget *
CreateDropTarget(IN HWND hwndTarget,
IN DWORD nSupportedFormats,
IN const FORMATETC *Formats OPTIONAL,
IN PVOID Context OPTIONAL,
IN const DROPTARGET_CALLBACKS *Callbacks OPTIONAL);
IN DWORD nSupportedFormats,
IN const FORMATETC *Formats OPTIONAL,
IN PVOID Context OPTIONAL,
IN const DROPTARGET_CALLBACKS *Callbacks OPTIONAL);
/*
* explorer.c
@ -134,37 +110,44 @@ CreateDropTarget(IN HWND hwndTarget,
LONG
SetWindowStyle(IN HWND hWnd,
IN LONG dwStyleMask,
IN LONG dwStyle);
IN LONG dwStyleMask,
IN LONG dwStyle);
LONG
SetWindowExStyle(IN HWND hWnd,
IN LONG dwStyleMask,
IN LONG dwStyle);
IN LONG dwStyleMask,
IN LONG dwStyle);
HMENU
LoadPopupMenu(IN HINSTANCE hInstance,
IN LPCTSTR lpMenuName);
IN LPCTSTR lpMenuName);
HMENU
FindSubMenu(IN HMENU hMenu,
IN UINT uItem,
IN BOOL fByPosition);
IN UINT uItem,
IN BOOL fByPosition);
BOOL
GetCurrentLoggedOnUserName(OUT LPTSTR szBuffer,
IN DWORD dwBufferSize);
IN DWORD dwBufferSize);
BOOL
FormatMenuString(IN HMENU hMenu,
IN UINT uPosition,
IN UINT uFlags,
...);
IN UINT uPosition,
IN UINT uFlags,
...);
BOOL
GetExplorerRegValueSet(IN HKEY hKey,
IN LPCTSTR lpSubKey,
IN LPCTSTR lpValue);
IN LPCTSTR lpSubKey,
IN LPCTSTR lpValue);
/*
* rshell.c
*/
HRESULT WINAPI
_CStartMenu_Constructor(REFIID riid, void **ppv);
/*
* traywnd.c
@ -172,39 +155,25 @@ GetExplorerRegValueSet(IN HKEY hKey,
#define TWM_OPENSTARTMENU (WM_USER + 260)
typedef HMENU (*PCREATECTXMENU)(IN HWND hWndOwner,
IN PVOID *ppcmContext,
IN PVOID Context OPTIONAL);
typedef VOID (*PCTXMENUCOMMAND)(IN HWND hWndOwner,
IN UINT uiCmdId,
IN PVOID pcmContext OPTIONAL,
IN PVOID Context OPTIONAL);
typedef struct _TRAYWINDOW_CTXMENU
{
PCREATECTXMENU CreateCtxMenu;
PCTXMENUCOMMAND CtxMenuCommand;
} TRAYWINDOW_CTXMENU, *PTRAYWINDOW_CTXMENU;
extern const GUID IID_IShellDesktopTray;
#define INTERFACE ITrayWindow
DECLARE_INTERFACE_(ITrayWindow,IUnknown)
DECLARE_INTERFACE_(ITrayWindow, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT,QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
STDMETHOD_(HRESULT, QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
/*** ITrayWindow methods ***/
STDMETHOD_(HRESULT,Open) (THIS) PURE;
STDMETHOD_(HRESULT,Close) (THIS) PURE;
STDMETHOD_(HWND,GetHWND) (THIS) PURE;
STDMETHOD_(BOOL,IsSpecialHWND) (THIS_ HWND hWnd) PURE;
STDMETHOD_(BOOL,IsHorizontal) (THIS) PURE;
STDMETHOD_(HFONT,GetCaptionFonts) (THIS_ HFONT *phBoldCaption) PURE;
STDMETHOD_(HWND,DisplayProperties) (THIS) PURE;
STDMETHOD_(BOOL,ExecContextMenuCmd) (THIS_ UINT uiCmd) PURE;
STDMETHOD_(BOOL,Lock) (THIS_ BOOL bLock) PURE;
STDMETHOD_(HRESULT, Open) (THIS) PURE;
STDMETHOD_(HRESULT, Close) (THIS) PURE;
STDMETHOD_(HWND, GetHWND) (THIS) PURE;
STDMETHOD_(BOOL, IsSpecialHWND) (THIS_ HWND hWnd) PURE;
STDMETHOD_(BOOL, IsHorizontal) (THIS) PURE;
STDMETHOD_(HFONT, GetCaptionFonts) (THIS_ HFONT *phBoldCaption) PURE;
STDMETHOD_(HWND, DisplayProperties) (THIS) PURE;
STDMETHOD_(BOOL, ExecContextMenuCmd) (THIS_ UINT uiCmd) PURE;
STDMETHOD_(BOOL, Lock) (THIS_ BOOL bLock) PURE;
};
#undef INTERFACE
@ -231,8 +200,7 @@ RegisterTrayWindowClass(VOID);
VOID
UnregisterTrayWindowClass(VOID);
ITrayWindow *
CreateTrayWindow(VOID);
HRESULT CreateTrayWindow(ITrayWindow ** ppTray);
VOID
TrayProcessMessages(IN OUT ITrayWindow *Tray);
@ -245,23 +213,24 @@ TrayMessageLoop(IN OUT ITrayWindow *Tray);
*/
/* Structure to hold non-default options*/
typedef struct _ADVANCED_SETTINGS {
typedef struct _ADVANCED_SETTINGS
{
BOOL bShowSeconds;
} ADVANCED_SETTINGS, *PADVANCED_SETTINGS;
extern ADVANCED_SETTINGS AdvancedSettings;
extern const TCHAR szAdvancedSettingsKey[];
extern const TCHAR szAdvancedSettingsKey [];
VOID
LoadAdvancedSettings(VOID);
BOOL
SaveSettingDword(IN PCTSTR pszKeyName,
IN PCTSTR pszValueName,
IN DWORD dwValue);
IN PCTSTR pszValueName,
IN DWORD dwValue);
/*
* startup.c
* startup.cpp
*/
int
@ -275,7 +244,7 @@ VOID
DisplayTrayProperties(IN HWND hwndOwner);
/*
* desktop.c
* desktop.cpp
*/
HANDLE
DesktopCreateWindow(IN OUT ITrayWindow *Tray);
@ -284,21 +253,21 @@ VOID
DesktopDestroyShellWindow(IN HANDLE hDesktop);
/*
* taskband.c
* taskband.cpp
*/
/* Internal Task Band CLSID */
extern const GUID CLSID_ITaskBand;
#define INTERFACE ITaskBand
DECLARE_INTERFACE_(ITaskBand,IUnknown)
DECLARE_INTERFACE_(ITaskBand, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT,QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
STDMETHOD_(HRESULT, QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
/*** ITaskBand methods ***/
STDMETHOD_(HRESULT,GetRebarBandID)(THIS_ DWORD *pdwBandID) PURE;
STDMETHOD_(HRESULT, GetRebarBandID)(THIS_ DWORD *pdwBandID) PURE;
};
#undef INTERFACE
@ -315,24 +284,24 @@ ITaskBand *
CreateTaskBand(IN OUT ITrayWindow *Tray);
/*
* tbsite.c
* tbsite.cpp
*/
#define INTERFACE ITrayBandSite
DECLARE_INTERFACE_(ITrayBandSite,IUnknown)
DECLARE_INTERFACE_(ITrayBandSite, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT,QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
STDMETHOD_(HRESULT, QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
/*** IBandSiteStreamCallback ***/
STDMETHOD_(HRESULT,OnLoad)(THIS_ IStream *pStm, REFIID riid, PVOID *pvObj) PURE;
STDMETHOD_(HRESULT,OnSave)(THIS_ IUnknown *pUnk, IStream *pStm) PURE;
STDMETHOD_(HRESULT, OnLoad)(THIS_ IStream *pStm, REFIID riid, PVOID *pvObj) PURE;
STDMETHOD_(HRESULT, OnSave)(THIS_ IUnknown *pUnk, IStream *pStm) PURE;
/*** ITrayBandSite methods ***/
STDMETHOD_(HRESULT,IsTaskBand) (THIS_ IUnknown *punk) PURE;
STDMETHOD_(HRESULT,ProcessMessage) (THIS_ HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) PURE;
STDMETHOD_(HRESULT,AddContextMenus) (THIS_ HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags, IContextMenu **ppcm) PURE;
STDMETHOD_(HRESULT,Lock) (THIS_ BOOL bLock) PURE;
STDMETHOD_(HRESULT, IsTaskBand) (THIS_ IUnknown *punk) PURE;
STDMETHOD_(HRESULT, ProcessMessage) (THIS_ HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *plResult) PURE;
STDMETHOD_(HRESULT, AddContextMenus) (THIS_ HMENU hmenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags, IContextMenu **ppcm) PURE;
STDMETHOD_(HRESULT, Lock) (THIS_ BOOL bLock) PURE;
};
#undef INTERFACE
@ -353,22 +322,22 @@ DECLARE_INTERFACE_(ITrayBandSite,IUnknown)
ITrayBandSite *
CreateTrayBandSite(IN OUT ITrayWindow *Tray,
OUT HWND *phWndRebar,
OUT HWND *phWndTaskSwitch);
OUT HWND *phWndRebar,
OUT HWND *phWndTaskSwitch);
/*
* startmnu.c
* startmnu.cpp
*/
extern const TRAYWINDOW_CTXMENU StartMenuBtnCtxMenu;
HRESULT StartMenuBtnCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu);
#define INTERFACE IStartMenuSite
DECLARE_INTERFACE_(IStartMenuSite,IUnknown)
DECLARE_INTERFACE_(IStartMenuSite, IUnknown)
{
/*** IUnknown methods ***/
STDMETHOD_(HRESULT,QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG,AddRef) (THIS) PURE;
STDMETHOD_(ULONG,Release) (THIS) PURE;
STDMETHOD_(HRESULT, QueryInterface) (THIS_ REFIID riid, void** ppvObject) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
/*** IStartMenuSite ***/
};
#undef INTERFACE
@ -383,14 +352,21 @@ DECLARE_INTERFACE_(IStartMenuSite,IUnknown)
IMenuPopup*
CreateStartMenu(IN ITrayWindow *Tray,
OUT IMenuBand **ppMenuBand,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons);
OUT IMenuBand **ppMenuBand,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons);
HRESULT
UpdateStartMenu(IN OUT IMenuPopup *pMenuPopup,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons);
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons);
/*
* startmnusite.cpp
*/
HRESULT
CreateStartMenuSite(IN OUT ITrayWindow *Tray, const IID & riid, PVOID * ppv);
/*
* trayntfy.c
@ -417,16 +393,14 @@ UnregisterTrayNotifyWndClass(VOID);
HWND
CreateTrayNotifyWnd(IN OUT ITrayWindow *TrayWindow,
IN BOOL bHideClock);
IN BOOL bHideClock);
VOID
TrayNotify_NotifyMsg(IN HWND hwnd,
IN WPARAM wParam,
IN LPARAM lParam);
TrayNotify_NotifyMsg(IN WPARAM wParam,
IN LPARAM lParam);
BOOL
TrayNotify_GetClockRect(IN HWND hwnd,
OUT PRECT rcClock);
TrayNotify_GetClockRect(OUT PRECT rcClock);
/*
* taskswnd.c
@ -443,6 +417,12 @@ UnregisterTaskSwitchWndClass(VOID);
HWND
CreateTaskSwitchWnd(IN HWND hWndParent,
IN OUT ITrayWindow *Tray);
IN OUT ITrayWindow *Tray);
HRESULT
Tray_OnStartMenuDismissed();
HRESULT
IsSameObject(IN IUnknown *punk1, IN IUnknown *punk2);
#endif /* _EXPLORER_PRECOMP__H_ */

View File

@ -0,0 +1,184 @@
/*
* 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"
static HINSTANCE hRShell = NULL;
typedef HRESULT(WINAPI * PSTARTMENU_CONSTRUCTOR)(REFIID riid, void **ppv);
HRESULT WINAPI _CStartMenu_Constructor(REFIID riid, void **ppv)
{
if (!hRShell)
{
hRShell = LoadLibraryW(L"rshell.dll");
}
if (hRShell)
{
PSTARTMENU_CONSTRUCTOR func = (PSTARTMENU_CONSTRUCTOR)GetProcAddress(hRShell, "CStartMenu_Constructor");
if(func)
{
return func(riid, ppv);
}
}
return CoCreateInstance(CLSID_StartMenu,
NULL,
CLSCTX_INPROC_SERVER,
riid,
ppv);
}
typedef HANDLE(WINAPI * PSHCREATEDESKTOP)(IShellDesktopTray *ShellDesk);
HANDLE WINAPI _SHCreateDesktop(IShellDesktopTray *ShellDesk)
{
HINSTANCE hFallback;
if (!hRShell)
{
hRShell = LoadLibraryW(L"rshell.dll");
}
if (hRShell)
{
PSHCREATEDESKTOP func = (PSHCREATEDESKTOP)GetProcAddress(hRShell, "SHCreateDesktop");
if (func)
{
return func(ShellDesk);
}
}
hFallback = GetModuleHandleW(L"shell32.dll");
if (hFallback)
{
PSHCREATEDESKTOP func = (PSHCREATEDESKTOP) GetProcAddress(hFallback, (LPCSTR) 200);
if (func)
{
return func(ShellDesk);
}
}
return 0;
}
typedef BOOL(WINAPI *PSHDESKTOPMESSAGELOOP)(HANDLE hDesktop);
BOOL WINAPI _SHDesktopMessageLoop(HANDLE hDesktop)
{
HINSTANCE hFallback;
if (!hRShell)
{
hRShell = LoadLibraryW(L"rshell.dll");
}
if (hRShell)
{
PSHDESKTOPMESSAGELOOP func = (PSHDESKTOPMESSAGELOOP)GetProcAddress(hRShell, "SHDesktopMessageLoop");
if (func)
{
return func(hDesktop);
}
}
hFallback = GetModuleHandleW(L"shell32.dll");
if (hFallback)
{
PSHDESKTOPMESSAGELOOP func = (PSHDESKTOPMESSAGELOOP) GetProcAddress(hFallback, (LPCSTR) 201);
if (func)
{
return func(hDesktop);
}
}
return FALSE;
}
typedef DWORD(WINAPI* PWINLIST_INIT)(void);
DWORD WINAPI _WinList_Init(void)
{
HINSTANCE hFallback;
if (!hRShell)
{
hRShell = LoadLibraryW(L"rshell.dll");
}
if (hRShell)
{
PWINLIST_INIT func = (PWINLIST_INIT)GetProcAddress(hRShell, "WinList_Init");
if (func)
{
return func();
}
}
hFallback = GetModuleHandleW(L"shdocvw.dll");
if (hFallback)
{
PWINLIST_INIT func = (PWINLIST_INIT) GetProcAddress(hFallback, (LPCSTR) 110);
if (func)
{
return func();
}
}
return 0;
}
typedef void (WINAPI *PSHELLDDEINIT)(BOOL bInit);
void WINAPI _ShellDDEInit(BOOL bInit)
{
HINSTANCE hFallback;
if (!hRShell)
{
hRShell = LoadLibraryW(L"rshell.dll");
}
if (hRShell)
{
PSHELLDDEINIT func = (PSHELLDDEINIT)GetProcAddress(hRShell, "ShellDDEInit");
if (func)
{
func(bInit);
return;
}
}
hFallback = GetModuleHandleW(L"shell32.dll");
if (hFallback)
{
PSHELLDDEINIT func = (PSHELLDDEINIT) GetProcAddress(hFallback, (LPCSTR) 188);
if (func)
{
func(bInit);
return;
}
}
}

View File

@ -21,8 +21,7 @@
#include "precomp.h"
ADVANCED_SETTINGS AdvancedSettings;
const TCHAR szAdvancedSettingsKey[] = TEXT("Software\\ReactOS\\Features\\Explorer");
const WCHAR szAdvancedSettingsKey[] = TEXT("Software\\ReactOS\\Features\\Explorer");
VOID
LoadAdvancedSettings(VOID)

View File

@ -0,0 +1,143 @@
/*
* ReactOS Explorer
*
* Copyright 2014 - David Quintana
*
* 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"
extern HRESULT InitShellServices(HDPA * phdpa);
extern HRESULT ShutdownShellServices(HDPA hdpa);
static int CALLBACK InitializeAllCallback(void* pItem, void* pData)
{
IOleCommandTarget * pOct = reinterpret_cast<IOleCommandTarget *>(pItem);
HRESULT * phr = reinterpret_cast<HRESULT *>(pData);
TRACE("Initializing SSO %p\n", pOct);
*phr = pOct->Exec(&CGID_ShellServiceObject, OLECMDID_NEW, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
return SUCCEEDED(*phr);
}
static int CALLBACK ShutdownAllCallback(void* pItem, void* pData)
{
IOleCommandTarget * pOct = reinterpret_cast<IOleCommandTarget *>(pItem);
TRACE("Shutting down SSO %p\n", pOct);
pOct->Exec(&CGID_ShellServiceObject, OLECMDID_SAVE, OLECMDEXECOPT_DODEFAULT, NULL, NULL);
return TRUE;
}
static int CALLBACK DeleteAllEnumCallback(void* pItem, void* pData)
{
IOleCommandTarget * pOct = reinterpret_cast<IOleCommandTarget *>(pItem);
TRACE("Releasing SSO %p\n", pOct);
pOct->Release();
return TRUE;
}
HRESULT InitShellServices(HDPA * phdpa)
{
IOleCommandTarget * pOct;
HKEY hkey;
CLSID clsid;
WCHAR name[MAX_PATH];
WCHAR value[MAX_PATH];
DWORD type;
LONG ret;
HDPA hdpa;
HRESULT hr = S_OK;
int count = 0;
*phdpa = NULL;
TRACE("Enumerating Shell Service Ojbect GUIDs...\n");
if (RegOpenKey(HKEY_LOCAL_MACHINE,
L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ShellServiceObjectDelayLoad",
&hkey))
{
ERR("RegOpenKey failed.\n");
return HRESULT_FROM_WIN32(GetLastError());
}
hdpa = DPA_Create(5);
/* Enumerate */
do
{
DWORD name_len = MAX_PATH;
DWORD value_len = sizeof(value); /* byte count! */
ret = RegEnumValueW(hkey, count, name, &name_len, 0, &type, (LPBYTE) &value, &value_len);
if (ret)
break;
if (type != REG_SZ)
{
WARN("Value type was not REG_SZ.\n");
continue;
}
hr = CLSIDFromString(value, &clsid);
if (FAILED_UNEXPECTEDLY(hr))
{
ERR("CLSIDFromString failed %08x.\n", hr);
goto cleanup;
}
hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IOleCommandTarget, &pOct));
if (FAILED_UNEXPECTEDLY(hr))
{
ERR("CoCreateInstance failed %08x.\n", hr);
goto cleanup;
}
DPA_AppendPtr(hdpa, pOct);
count++;
}
while (1);
if (ret != ERROR_NO_MORE_ITEMS)
{
ERR("RegEnumValueW failed %08x.\n", ret);
hr = HRESULT_FROM_WIN32(GetLastError());
goto cleanup;
}
RegCloseKey(hkey);
/* Initialize */
DPA_EnumCallback(hdpa, InitializeAllCallback, &hr);
if (FAILED_UNEXPECTEDLY(hr))
goto cleanup;
*phdpa = hdpa;
return count > 0 ? S_OK : S_FALSE;
cleanup:
*phdpa = NULL;
ShutdownShellServices(hdpa);
return hr;
}
HRESULT ShutdownShellServices(HDPA hdpa)
{
DPA_EnumCallback(hdpa, ShutdownAllCallback, NULL);
DPA_EnumCallback(hdpa, DeleteAllEnumCallback, NULL);
DPA_Destroy(hdpa);
return S_OK;
}

View File

@ -0,0 +1,245 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
/*
* Start menu button context menu
*/
class CStartMenuBtnCtxMenu :
public CComCoClass<CStartMenuBtnCtxMenu>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IContextMenu
{
HWND hWndOwner;
CComPtr<ITrayWindow> TrayWnd;
CComPtr<IContextMenu> pcm;
CComPtr<IShellFolder> psf;
LPITEMIDLIST pidl;
HRESULT CreateContextMenuFromShellFolderPidl(HMENU hPopup)
{
CComPtr<IContextMenu> pcm;
HRESULT hRet;
hRet = psf->GetUIObjectOf(hWndOwner, 1, (LPCITEMIDLIST *) &pidl, IID_NULL_PPV_ARG(IContextMenu, &pcm));
if (SUCCEEDED(hRet))
{
if (hPopup != NULL)
{
hRet = pcm->QueryContextMenu(
hPopup,
0,
ID_SHELL_CMD_FIRST,
ID_SHELL_CMD_LAST,
CMF_VERBSONLY);
if (SUCCEEDED(hRet))
{
return hRet;
}
DestroyMenu(hPopup);
}
}
return E_FAIL;
}
VOID AddStartContextMenuItems(IN HMENU hPopup)
{
WCHAR szBuf[MAX_PATH];
HRESULT hRet;
/* Add the "Open All Users" menu item */
if (LoadString(hExplorerInstance,
IDS_PROPERTIES,
szBuf,
sizeof(szBuf) / sizeof(szBuf[0])))
{
AppendMenu(hPopup,
MF_STRING,
ID_SHELL_CMD_PROPERTIES,
szBuf);
}
if (!SHRestricted(REST_NOCOMMONGROUPS))
{
/* Check if we should add menu items for the common start menu */
hRet = SHGetFolderPath(hWndOwner,
CSIDL_COMMON_STARTMENU,
NULL,
SHGFP_TYPE_CURRENT,
szBuf);
if (SUCCEEDED(hRet) && hRet != S_FALSE)
{
/* The directory exists, but only show the items if the
user can actually make any changes to the common start
menu. This is most likely only the case if the user
has administrative rights! */
if (IsUserAnAdmin())
{
AppendMenu(hPopup,
MF_SEPARATOR,
0,
NULL);
/* Add the "Open All Users" menu item */
if (LoadString(hExplorerInstance,
IDS_OPEN_ALL_USERS,
szBuf,
sizeof(szBuf) / sizeof(szBuf[0])))
{
AppendMenu(hPopup,
MF_STRING,
ID_SHELL_CMD_OPEN_ALL_USERS,
szBuf);
}
/* Add the "Explore All Users" menu item */
if (LoadString(hExplorerInstance,
IDS_EXPLORE_ALL_USERS,
szBuf,
sizeof(szBuf) / sizeof(szBuf[0])))
{
AppendMenu(hPopup,
MF_STRING,
ID_SHELL_CMD_EXPLORE_ALL_USERS,
szBuf);
}
}
}
}
}
public:
HRESULT Initialize(ITrayWindow * pTrayWnd, IN HWND hWndOwner)
{
this->TrayWnd = pTrayWnd;
this->hWndOwner = hWndOwner;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE
QueryContextMenu(HMENU hPopup,
UINT indexMenu,
UINT idCmdFirst,
UINT idCmdLast,
UINT uFlags)
{
LPITEMIDLIST pidlStart;
CComPtr<IShellFolder> psfDesktop;
HRESULT hRet;
psfDesktop = NULL;
pcm = NULL;
pidlStart = SHCloneSpecialIDList(hWndOwner, CSIDL_STARTMENU, TRUE);
if (pidlStart != NULL)
{
pidl = ILClone(ILFindLastID(pidlStart));
ILRemoveLastID(pidlStart);
if (pidl != NULL)
{
hRet = SHGetDesktopFolder(&psfDesktop);
if (SUCCEEDED(hRet))
{
hRet = psfDesktop->BindToObject(pidlStart, NULL, IID_PPV_ARG(IShellFolder, &psf));
if (SUCCEEDED(hRet))
{
CreateContextMenuFromShellFolderPidl(hPopup);
AddStartContextMenuItems(hPopup);
}
}
}
ILFree(pidlStart);
}
return NULL;
}
virtual HRESULT STDMETHODCALLTYPE
InvokeCommand(LPCMINVOKECOMMANDINFO lpici)
{
UINT uiCmdId = (UINT)lpici->lpVerb;
if (uiCmdId != 0)
{
if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId <= ID_SHELL_CMD_LAST))
{
CMINVOKECOMMANDINFO cmici = { 0 };
CHAR szDir[MAX_PATH];
/* Setup and invoke the shell command */
cmici.cbSize = sizeof(cmici);
cmici.hwnd = hWndOwner;
cmici.lpVerb = MAKEINTRESOURCEA(uiCmdId - ID_SHELL_CMD_FIRST);
cmici.nShow = SW_NORMAL;
/* FIXME: Support Unicode!!! */
if (SHGetPathFromIDListA(pidl, szDir))
{
cmici.lpDirectory = szDir;
}
pcm->InvokeCommand(&cmici);
}
else
{
TrayWnd->ExecContextMenuCmd(uiCmdId);
}
}
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE
GetCommandString(UINT_PTR idCmd,
UINT uType,
UINT *pwReserved,
LPSTR pszName,
UINT cchMax)
{
return E_NOTIMPL;
}
CStartMenuBtnCtxMenu()
{
}
virtual ~CStartMenuBtnCtxMenu()
{
if (pidl)
ILFree(pidl);
}
BEGIN_COM_MAP(CStartMenuBtnCtxMenu)
COM_INTERFACE_ENTRY_IID(IID_IContextMenu, IContextMenu)
END_COM_MAP()
};
HRESULT StartMenuBtnCtxMenuCreator(ITrayWindow * TrayWnd, IN HWND hWndOwner, IContextMenu ** ppCtxMenu)
{
CStartMenuBtnCtxMenu * mnu = new CComObject<CStartMenuBtnCtxMenu>();
mnu->Initialize(TrayWnd, hWndOwner);
*ppCtxMenu = mnu;
return S_OK;
}

View File

@ -1,950 +0,0 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
/*
* Start menu button context menu
*/
typedef struct _STARTMNU_CTMENU_CTX
{
IContextMenu *pcm;
LPITEMIDLIST pidl;
} STARTMNU_CTMENU_CTX, *PSTARTMNU_CTMENU_CTX;
static HMENU
CreateStartContextMenu(IN HWND hWndOwner,
IN PVOID *ppcmContext,
IN PVOID Context OPTIONAL);
static VOID
OnStartContextMenuCommand(IN HWND hWndOwner,
IN UINT uiCmdId,
IN PVOID pcmContext OPTIONAL,
IN PVOID Context OPTIONAL);
const TRAYWINDOW_CTXMENU StartMenuBtnCtxMenu = {
CreateStartContextMenu,
OnStartContextMenuCommand
};
static HMENU
CreateContextMenuFromShellFolderPidl(IN HWND hWndOwner,
IN OUT IShellFolder *psf,
IN OUT LPITEMIDLIST pidl,
OUT IContextMenu **ppcm)
{
IContextMenu *pcm;
HRESULT hRet;
HMENU hPopup;
hRet = IShellFolder_GetUIObjectOf(psf,
hWndOwner,
1,
(LPCITEMIDLIST *)&pidl,
&IID_IContextMenu,
NULL,
(PVOID *)&pcm);
if (SUCCEEDED(hRet))
{
hPopup = CreatePopupMenu();
if (hPopup != NULL)
{
hRet = IContextMenu_QueryContextMenu(pcm,
hPopup,
0,
ID_SHELL_CMD_FIRST,
ID_SHELL_CMD_LAST,
CMF_VERBSONLY);
if (SUCCEEDED(hRet))
{
*ppcm = pcm;
return hPopup;
}
DestroyMenu(hPopup);
}
IContextMenu_Release(pcm);
}
return NULL;
}
static VOID
OnStartContextMenuCommand(IN HWND hWndOwner,
IN UINT uiCmdId,
IN PVOID pcmContext OPTIONAL,
IN PVOID Context OPTIONAL)
{
PSTARTMNU_CTMENU_CTX psmcmc = pcmContext;
if (uiCmdId != 0)
{
if ((uiCmdId >= ID_SHELL_CMD_FIRST) && (uiCmdId <= ID_SHELL_CMD_LAST))
{
CMINVOKECOMMANDINFO cmici = {0};
CHAR szDir[MAX_PATH];
/* Setup and invoke the shell command */
cmici.cbSize = sizeof(cmici);
cmici.hwnd = hWndOwner;
cmici.lpVerb = (LPCSTR)MAKEINTRESOURCE(uiCmdId - ID_SHELL_CMD_FIRST);
cmici.nShow = SW_NORMAL;
/* FIXME: Support Unicode!!! */
if (SHGetPathFromIDListA(psmcmc->pidl,
szDir))
{
cmici.lpDirectory = szDir;
}
IContextMenu_InvokeCommand(psmcmc->pcm,
&cmici);
}
else
{
ITrayWindow_ExecContextMenuCmd((ITrayWindow *)Context,
uiCmdId);
}
}
IContextMenu_Release(psmcmc->pcm);
HeapFree(hProcessHeap,
0,
psmcmc);
}
static VOID
AddStartContextMenuItems(IN HWND hWndOwner,
IN HMENU hPopup)
{
TCHAR szBuf[MAX_PATH];
HRESULT hRet;
/* Add the "Open All Users" menu item */
if (LoadString(hExplorerInstance,
IDS_PROPERTIES,
szBuf,
sizeof(szBuf) / sizeof(szBuf[0])))
{
AppendMenu(hPopup,
MF_STRING,
ID_SHELL_CMD_PROPERTIES,
szBuf);
}
if (!SHRestricted(REST_NOCOMMONGROUPS))
{
/* Check if we should add menu items for the common start menu */
hRet = SHGetFolderPath(hWndOwner,
CSIDL_COMMON_STARTMENU,
NULL,
SHGFP_TYPE_CURRENT,
szBuf);
if (SUCCEEDED(hRet) && hRet != S_FALSE)
{
/* The directory exists, but only show the items if the
user can actually make any changes to the common start
menu. This is most likely only the case if the user
has administrative rights! */
if (IsUserAnAdmin())
{
AppendMenu(hPopup,
MF_SEPARATOR,
0,
NULL);
/* Add the "Open All Users" menu item */
if (LoadString(hExplorerInstance,
IDS_OPEN_ALL_USERS,
szBuf,
sizeof(szBuf) / sizeof(szBuf[0])))
{
AppendMenu(hPopup,
MF_STRING,
ID_SHELL_CMD_OPEN_ALL_USERS,
szBuf);
}
/* Add the "Explore All Users" menu item */
if (LoadString(hExplorerInstance,
IDS_EXPLORE_ALL_USERS,
szBuf,
sizeof(szBuf) / sizeof(szBuf[0])))
{
AppendMenu(hPopup,
MF_STRING,
ID_SHELL_CMD_EXPLORE_ALL_USERS,
szBuf);
}
}
}
}
}
static HMENU
CreateStartContextMenu(IN HWND hWndOwner,
IN PVOID *ppcmContext,
IN PVOID Context OPTIONAL)
{
LPITEMIDLIST pidlStart, pidlLast;
IShellFolder *psfStart, *psfDesktop;
IContextMenu *pcm;
HRESULT hRet;
HMENU hPopup;
pidlStart = SHCloneSpecialIDList(hWndOwner,
CSIDL_STARTMENU,
TRUE);
if (pidlStart != NULL)
{
pidlLast = ILClone(ILFindLastID(pidlStart));
ILRemoveLastID(pidlStart);
if (pidlLast != NULL)
{
hRet = SHGetDesktopFolder(&psfDesktop);
if (SUCCEEDED(hRet))
{
hRet = IShellFolder_BindToObject(psfDesktop,
pidlStart,
NULL,
&IID_IShellFolder,
(PVOID*)&psfStart);
if (SUCCEEDED(hRet))
{
hPopup = CreateContextMenuFromShellFolderPidl(hWndOwner,
psfStart,
pidlLast,
&pcm);
if (hPopup != NULL)
{
PSTARTMNU_CTMENU_CTX psmcmc;
psmcmc = HeapAlloc(hProcessHeap,
0,
sizeof(*psmcmc));
if (psmcmc != NULL)
{
psmcmc->pcm = pcm;
psmcmc->pidl = pidlLast;
AddStartContextMenuItems(hWndOwner,
hPopup);
*ppcmContext = psmcmc;
return hPopup;
}
else
{
IContextMenu_Release(pcm);
DestroyMenu(hPopup);
hPopup = NULL;
}
}
IShellFolder_Release(psfStart);
}
IShellFolder_Release(psfDesktop);
}
ILFree(pidlLast);
}
ILFree(pidlStart);
}
return NULL;
}
/*****************************************************************************
** IStartMenuSite ***********************************************************
*****************************************************************************/
static const IStartMenuSiteVtbl IStartMenuSiteImpl_Vtbl;
static const IServiceProviderVtbl IServiceProviderImpl_Vtbl;
static const ITrayPrivVtbl ITrayPrivImpl_Vtbl;
static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl;
typedef struct
{
const IStartMenuSiteVtbl *lpVtbl;
const IServiceProviderVtbl *lpServiceProviderVtbl;
const ITrayPrivVtbl *lpStartMenuCallbackVtbl;
const IOleCommandTargetVtbl *lpOleCommandTargetVtbl;
LONG Ref;
ITrayWindow *Tray;
} IStartMenuSiteImpl;
static IUnknown *
IUnknown_from_IStartMenuSiteImpl(IStartMenuSiteImpl *This)
{
return (IUnknown *)&This->lpVtbl;
}
IMPL_CASTS(IStartMenuSite, IStartMenuSite, lpVtbl)
IMPL_CASTS(IServiceProvider, IStartMenuSite, lpServiceProviderVtbl)
IMPL_CASTS(ITrayPriv, IStartMenuSite, lpStartMenuCallbackVtbl)
IMPL_CASTS(IOleCommandTarget, IStartMenuSite, lpOleCommandTargetVtbl)
/*******************************************************************/
static ULONG STDMETHODCALLTYPE
IStartMenuSiteImpl_AddRef(IN OUT IStartMenuSite *iface)
{
IStartMenuSiteImpl *This = IStartMenuSiteImpl_from_IStartMenuSite(iface);
return InterlockedIncrement(&This->Ref);
}
static VOID
IStartMenuSiteImpl_Free(IN OUT IStartMenuSiteImpl *This)
{
HeapFree(hProcessHeap,
0,
This);
}
static ULONG STDMETHODCALLTYPE
IStartMenuSiteImpl_Release(IN OUT IStartMenuSite *iface)
{
IStartMenuSiteImpl *This = IStartMenuSiteImpl_from_IStartMenuSite(iface);
ULONG Ret;
Ret = InterlockedDecrement(&This->Ref);
if (Ret == 0)
IStartMenuSiteImpl_Free(This);
return Ret;
}
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_QueryInterface(IN OUT IStartMenuSite *iface,
IN REFIID riid,
OUT LPVOID *ppvObj)
{
IStartMenuSiteImpl *This;
if (ppvObj == NULL)
return E_POINTER;
This = IStartMenuSiteImpl_from_IStartMenuSite(iface);
if (IsEqualIID(riid,
&IID_IUnknown))
{
*ppvObj = IUnknown_from_IStartMenuSiteImpl(This);
}
else if (IsEqualIID(riid,
&IID_IServiceProvider))
{
*ppvObj = IServiceProvider_from_IStartMenuSiteImpl(This);
}
else if (IsEqualIID(riid,
&IID_ITrayPriv) ||
IsEqualIID(riid,
&IID_IOleWindow))
{
*ppvObj = ITrayPriv_from_IStartMenuSiteImpl(This);
}
else if (IsEqualIID(riid,
&IID_IOleCommandTarget))
{
*ppvObj = IOleCommandTarget_from_IStartMenuSiteImpl(This);
}
else
{
DbgPrint("IStartMenuSite::QueryInterface queried unsupported interface: "
"{0x%8x,0x%4x,0x%4x,{0x%2x,0x%2x,0x%2x,0x%2x,0x%2x,0x%2x,0x%2x,0x%2x}}\n",
riid->Data1, riid->Data2, riid->Data3, riid->Data4[0], riid->Data4[1],
riid->Data4[2], riid->Data4[3], riid->Data4[4], riid->Data4[5],
riid->Data4[6], riid->Data4[7]);
*ppvObj = NULL;
return E_NOINTERFACE;
}
IStartMenuSiteImpl_AddRef(iface);
return S_OK;
}
static const IStartMenuSiteVtbl IStartMenuSiteImpl_Vtbl =
{
/*** IUnknown methods ***/
IStartMenuSiteImpl_QueryInterface,
IStartMenuSiteImpl_AddRef,
IStartMenuSiteImpl_Release,
/*** IStartMenuSite methods ***/
};
/*******************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IServiceProvider, IStartMenuSite)
METHOD_IUNKNOWN_INHERITED_RELEASE(IServiceProvider, IStartMenuSite)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IServiceProvider, IStartMenuSite)
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_QueryService(IN OUT IServiceProvider *iface,
IN REFGUID guidService,
IN REFIID riid,
OUT PVOID *ppvObject)
{
IStartMenuSiteImpl *This = IStartMenuSiteImpl_from_IServiceProvider(iface);
if (IsEqualGUID(guidService,
&SID_SMenuPopup))
{
return IStartMenuSiteImpl_QueryInterface(IStartMenuSite_from_IStartMenuSiteImpl(This),
riid,
ppvObject);
}
return E_NOINTERFACE;
}
static const IServiceProviderVtbl IServiceProviderImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IServiceProvider, IStartMenuSite),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IServiceProvider, IStartMenuSite),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IServiceProvider, IStartMenuSite),
/*** IServiceProvider methods ***/
IStartMenuSiteImpl_QueryService
};
/*******************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(ITrayPriv, IStartMenuSite)
METHOD_IUNKNOWN_INHERITED_RELEASE(ITrayPriv, IStartMenuSite)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(ITrayPriv, IStartMenuSite)
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_GetWindow(IN OUT ITrayPriv *iface,
OUT HWND *phwnd)
{
IStartMenuSiteImpl *This = IStartMenuSiteImpl_from_ITrayPriv(iface);
DbgPrint("ITrayPriv::GetWindow\n");
*phwnd = ITrayWindow_GetHWND(This->Tray);
if (*phwnd != NULL)
return S_OK;
return E_FAIL;
}
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_ContextSensitiveHelp(IN OUT ITrayPriv *iface,
IN BOOL fEnterMode)
{
DbgPrint("ITrayPriv::ContextSensitiveHelp\n");
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_Execute(IN OUT ITrayPriv *iface,
IN IShellFolder *pShellFolder,
IN LPCITEMIDLIST pidl)
{
HMODULE hShlwapi;
HRESULT ret = S_FALSE;
IStartMenuSiteImpl *This = IStartMenuSiteImpl_from_ITrayPriv(iface);
DbgPrint("ITrayPriv::Execute\n");
hShlwapi = GetModuleHandle(TEXT("SHLWAPI.DLL"));
if (hShlwapi != NULL)
{
SHINVDEFCMD SHInvokeDefCmd;
/* SHInvokeDefaultCommand */
SHInvokeDefCmd = (SHINVDEFCMD)GetProcAddress(hShlwapi,
(LPCSTR)((LONG)279));
if (SHInvokeDefCmd != NULL)
{
ret = SHInvokeDefCmd(ITrayWindow_GetHWND(This->Tray),
pShellFolder,
pidl);
}
}
return ret;
}
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_Unknown(IN OUT ITrayPriv *iface,
IN PVOID Unknown1,
IN PVOID Unknown2,
IN PVOID Unknown3,
IN PVOID Unknown4)
{
DbgPrint("ITrayPriv::Unknown(0x%p,0x%p,0x%p,0x%p)\n", Unknown1, Unknown2, Unknown3, Unknown4);
return E_NOTIMPL;
}
static BOOL
ShowUndockMenuItem(VOID)
{
DbgPrint("ShowUndockMenuItem() not implemented!\n");
/* FIXME: How do we detect this?! */
return FALSE;
}
static BOOL
ShowSynchronizeMenuItem(VOID)
{
DbgPrint("ShowSynchronizeMenuItem() not implemented!\n");
/* FIXME: How do we detect this?! */
return FALSE;
}
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_AppendMenu(IN OUT ITrayPriv *iface,
OUT HMENU* phMenu)
{
HMENU hMenu, hSettingsMenu;
DWORD dwLogoff;
BOOL bWantLogoff;
UINT uLastItemsCount = 5; /* 5 menu items below the last separator */
TCHAR szUser[128];
DbgPrint("ITrayPriv::AppendMenu\n");
hMenu = LoadPopupMenu(hExplorerInstance,
MAKEINTRESOURCE(IDM_STARTMENU));
*phMenu = hMenu;
if (hMenu == NULL)
return E_FAIL;
/* Remove menu items that don't apply */
dwLogoff = SHRestricted(REST_STARTMENULOGOFF);
bWantLogoff = (dwLogoff == 2 ||
SHRestricted(REST_FORCESTARTMENULOGOFF) ||
GetExplorerRegValueSet(HKEY_CURRENT_USER,
TEXT("Advanced"),
TEXT("StartMenuLogoff")));
/* FIXME: Favorites */
/* Documents */
if (SHRestricted(REST_NORECENTDOCSMENU))
{
DeleteMenu(hMenu,
IDM_DOCUMENTS,
MF_BYCOMMAND);
}
/* Settings */
hSettingsMenu = FindSubMenu(hMenu,
IDM_SETTINGS,
FALSE);
if (hSettingsMenu != NULL)
{
if (SHRestricted(REST_NOSETFOLDERS))
{
/* Control Panel */
if (SHRestricted(REST_NOCONTROLPANEL))
{
DeleteMenu(hSettingsMenu,
IDM_CONTROLPANEL,
MF_BYCOMMAND);
/* Delete the separator below it */
DeleteMenu(hSettingsMenu,
0,
MF_BYPOSITION);
}
/* Network Connections */
if (SHRestricted(REST_NONETWORKCONNECTIONS))
{
DeleteMenu(hSettingsMenu,
IDM_NETWORKCONNECTIONS,
MF_BYCOMMAND);
}
/* Printers and Faxes */
DeleteMenu(hSettingsMenu,
IDM_PRINTERSANDFAXES,
MF_BYCOMMAND);
}
/* Security */
if (GetSystemMetrics(SM_REMOTECONTROL) == 0 ||
SHRestricted(REST_NOSECURITY))
{
DeleteMenu(hSettingsMenu,
IDM_SECURITY,
MF_BYCOMMAND);
}
if (GetMenuItemCount(hSettingsMenu) == 0)
{
DeleteMenu(hMenu,
IDM_SETTINGS,
MF_BYCOMMAND);
}
}
/* Search */
if (SHRestricted(REST_NOFIND))
{
DeleteMenu(hMenu,
IDM_SEARCH,
MF_BYCOMMAND);
}
/* FIXME: Help */
/* Run */
if (SHRestricted(REST_NORUN))
{
DeleteMenu(hMenu,
IDM_RUN,
MF_BYCOMMAND);
}
/* Synchronize */
if (!ShowSynchronizeMenuItem())
{
DeleteMenu(hMenu,
IDM_SYNCHRONIZE,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Log off */
if (dwLogoff != 1 && bWantLogoff)
{
/* FIXME: We need a more sophisticated way to determine whether to show
or hide it, it might be hidden in too many cases!!! */
/* Update Log Off menu item */
if (!GetCurrentLoggedOnUserName(szUser,
sizeof(szUser) / sizeof(szUser[0])))
{
szUser[0] = _T('\0');
}
if (!FormatMenuString(hMenu,
IDM_LOGOFF,
MF_BYCOMMAND,
szUser))
{
/* We couldn't update the menu item, delete it... */
DeleteMenu(hMenu,
IDM_LOGOFF,
MF_BYCOMMAND);
}
}
else
{
DeleteMenu(hMenu,
IDM_LOGOFF,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Disconnect */
if (GetSystemMetrics(SM_REMOTECONTROL) == 0)
{
DeleteMenu(hMenu,
IDM_DISCONNECT,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Undock computer */
if (!ShowUndockMenuItem())
{
DeleteMenu(hMenu,
IDM_UNDOCKCOMPUTER,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Shut down */
if (SHRestricted(REST_NOCLOSE))
{
DeleteMenu(hMenu,
IDM_SHUTDOWN,
MF_BYCOMMAND);
uLastItemsCount--;
}
if (uLastItemsCount == 0)
{
/* Remove the separator at the end of the menu */
DeleteMenu(hMenu,
IDM_LASTSTARTMENU_SEPARATOR,
MF_BYCOMMAND);
}
return S_OK;
}
static const ITrayPrivVtbl ITrayPrivImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(ITrayPriv, IStartMenuSite),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(ITrayPriv, IStartMenuSite),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(ITrayPriv, IStartMenuSite),
/*** IOleWindow methods ***/
IStartMenuSiteImpl_GetWindow,
IStartMenuSiteImpl_ContextSensitiveHelp,
/*** ITrayPriv methods ***/
IStartMenuSiteImpl_Execute,
IStartMenuSiteImpl_Unknown,
IStartMenuSiteImpl_AppendMenu
};
/*******************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IOleCommandTarget, IStartMenuSite)
METHOD_IUNKNOWN_INHERITED_RELEASE(IOleCommandTarget, IStartMenuSite)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IOleCommandTarget, IStartMenuSite)
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_QueryStatus(IN OUT IOleCommandTarget *iface,
IN const GUID *pguidCmdGroup OPTIONAL,
IN ULONG cCmds,
IN OUT OLECMD *prgCmds,
IN OUT OLECMDTEXT *pCmdText OPTIONAL)
{
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
IStartMenuSiteImpl_Exec(IN OUT IOleCommandTarget *iface,
IN const GUID *pguidCmdGroup OPTIONAL,
IN DWORD nCmdID,
IN DWORD nCmdExecOpt,
IN VARIANTARG *pvaIn OPTIONAL,
IN VARIANTARG *pvaOut OPTIONAL)
{
return E_NOTIMPL;
}
static const IOleCommandTargetVtbl IOleCommandTargetImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IOleCommandTarget, IStartMenuSite),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IOleCommandTarget, IStartMenuSite),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IOleCommandTarget, IStartMenuSite),
/*** IOleCommandTarget ***/
IStartMenuSiteImpl_QueryStatus,
IStartMenuSiteImpl_Exec
};
/*******************************************************************/
static IStartMenuSiteImpl*
IStartMenuSiteImpl_Construct(IN ITrayWindow *Tray)
{
IStartMenuSiteImpl *This;
This = HeapAlloc(hProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(*This));
if (This == NULL)
return NULL;
This->lpVtbl = &IStartMenuSiteImpl_Vtbl;
This->lpServiceProviderVtbl = &IServiceProviderImpl_Vtbl;
This->lpStartMenuCallbackVtbl = &ITrayPrivImpl_Vtbl;
This->lpOleCommandTargetVtbl = &IOleCommandTargetImpl_Vtbl;
This->Ref = 1;
This->Tray = Tray;
return This;
}
static IStartMenuSite*
CreateStartMenuSite(IN ITrayWindow *Tray)
{
IStartMenuSiteImpl *This;
This = IStartMenuSiteImpl_Construct(Tray);
if (This != NULL)
{
return IStartMenuSite_from_IStartMenuSiteImpl(This);
}
return NULL;
}
HRESULT
UpdateStartMenu(IN OUT IMenuPopup *pMenuPopup,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons)
{
IBanneredBar *pbb;
HRESULT hRet;
hRet = IMenuPopup_QueryInterface(pMenuPopup,
&IID_IBanneredBar,
(PVOID *)&pbb);
if (SUCCEEDED(hRet))
{
hRet = IBanneredBar_SetBitmap(pbb, hbmBanner);
/* Update the icon size */
hRet = IBanneredBar_SetIconSize(pbb,
bSmallIcons ? BMICON_SMALL : BMICON_LARGE);
IBanneredBar_Release(pbb);
}
return hRet;
}
IMenuPopup *
CreateStartMenu(IN ITrayWindow *Tray,
OUT IMenuBand **ppMenuBand,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons)
{
HRESULT hr;
IObjectWithSite *pOws = NULL;
IMenuPopup *pMp = NULL;
IStartMenuSite *pSms = NULL;
IMenuBand *pMb = NULL;
IInitializeObject *pIo;
IUnknown *pUnk = NULL;
IBandSite *pBs = NULL;
DWORD dwBandId = 0;
pSms = CreateStartMenuSite(Tray);
if (pSms == NULL)
return NULL;
hr = CoCreateInstance(&CLSID_StartMenu,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IMenuPopup,
(PVOID *)&pMp);
if (FAILED(hr))
{
DbgPrint("CoCreateInstance failed: %x\n", hr);
goto cleanup;
}
hr = IMenuPopup_QueryInterface(pMp,
&IID_IObjectWithSite,
(PVOID *)&pOws);
if (FAILED(hr))
{
DbgPrint("IMenuPopup_QueryInterface failed: %x\n", hr);
goto cleanup;
}
/* Set the menu site so we can handle messages */
hr = IObjectWithSite_SetSite(pOws, (IUnknown *)pSms);
if (FAILED(hr))
{
DbgPrint("IObjectWithSite_SetSite failed: %x\n", hr);
goto cleanup;
}
/* Initialize the menu object */
hr = IMenuPopup_QueryInterface(pMp, &IID_IInitializeObject, (PVOID*)&pIo);
if (SUCCEEDED(hr))
{
hr = IInitializeObject_Initialize(pIo);
IInitializeObject_Release(pIo);
}
else
hr = S_OK;
/* Everything is initialized now. Let's get the IMenuBand interface. */
if (FAILED(hr))
{
DbgPrint("IMenuPopup_QueryInterface failed: %x\n", hr);
goto cleanup;
}
hr = IMenuPopup_GetClient(pMp, &pUnk);
if (FAILED(hr))
{
DbgPrint("IMenuPopup_GetClient failed: %x\n", hr);
goto cleanup;
}
hr = IUnknown_QueryInterface(pUnk, &IID_IBandSite, (PVOID *)&pBs);
if (FAILED(hr))
{
DbgPrint("IUnknown_QueryInterface pBs failed: %x\n", hr);
goto cleanup;
}
/* Finally we have the IBandSite interface, there's only one
band in it that apparently provides the IMenuBand interface */
hr = IBandSite_EnumBands(pBs, 0, &dwBandId);
if (FAILED(hr))
{
DbgPrint("IBandSite_EnumBands failed: %x\n", hr);
goto cleanup;
}
hr = IBandSite_GetBandObject(pBs, dwBandId, &IID_IMenuBand, (PVOID *)&pMb);
if (FAILED(hr))
{
DbgPrint("IBandSite_GetBandObject failed: %x\n", hr);
goto cleanup;
}
UpdateStartMenu(pMp,
hbmBanner,
bSmallIcons);
cleanup:
if (SUCCEEDED(hr))
*ppMenuBand = pMb;
else if (pMb != NULL)
IMenuBand_Release(pMb);
if (pBs != NULL)
IBandSite_Release(pBs);
if (pUnk != NULL)
IUnknown_Release(pUnk);
if (pOws != NULL)
IObjectWithSite_Release(pOws);
if (pMp != NULL)
IMenuPopup_Release(pMp);
if (pSms != NULL)
IStartMenuSite_Release(pSms);
if (FAILED(hr))
return NULL;
return pMp;
}

View File

@ -0,0 +1,164 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
HRESULT
UpdateStartMenu(IN OUT IMenuPopup *pMenuPopup,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons)
{
CComPtr<IBanneredBar> pbb;
HRESULT hRet;
hRet = pMenuPopup->QueryInterface(IID_PPV_ARG(IBanneredBar, &pbb));
if (SUCCEEDED(hRet))
{
hRet = pbb->SetBitmap(hbmBanner);
/* Update the icon size */
hRet = pbb->SetIconSize(bSmallIcons ? BMICON_SMALL : BMICON_LARGE);
}
return hRet;
}
IMenuPopup *
CreateStartMenu(IN ITrayWindow *Tray,
OUT IMenuBand **ppMenuBand,
IN HBITMAP hbmBanner OPTIONAL,
IN BOOL bSmallIcons)
{
HRESULT hr;
IObjectWithSite *pOws = NULL;
IMenuPopup *pMp = NULL;
IUnknown *pSms = NULL;
IMenuBand *pMb = NULL;
IInitializeObject *pIo;
IUnknown *pUnk = NULL;
IBandSite *pBs = NULL;
DWORD dwBandId = 0;
hr = CreateStartMenuSite(Tray, IID_PPV_ARG(IUnknown, &pSms));
if (FAILED_UNEXPECTEDLY(hr))
return NULL;
#if 0
hr = CoCreateInstance(&CLSID_StartMenu,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IMenuPopup,
(PVOID *)&pMp);
#else
hr = _CStartMenu_Constructor(IID_PPV_ARG(IMenuPopup, &pMp));
#endif
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("CoCreateInstance failed: %x\n", hr);
goto cleanup;
}
hr = pMp->QueryInterface(IID_PPV_ARG(IObjectWithSite, &pOws));
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IMenuPopup_QueryInterface failed: %x\n", hr);
goto cleanup;
}
/* Set the menu site so we can handle messages */
hr = pOws->SetSite(pSms);
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IObjectWithSite_SetSite failed: %x\n", hr);
goto cleanup;
}
/* Initialize the menu object */
hr = pMp->QueryInterface(IID_PPV_ARG(IInitializeObject, &pIo));
if (SUCCEEDED(hr))
{
hr = pIo->Initialize();
pIo->Release();
}
else
hr = S_OK;
/* Everything is initialized now. Let's get the IMenuBand interface. */
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IMenuPopup_QueryInterface failed: %x\n", hr);
goto cleanup;
}
hr = pMp->GetClient(&pUnk);
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IMenuPopup_GetClient failed: %x\n", hr);
goto cleanup;
}
hr = pUnk->QueryInterface(IID_PPV_ARG(IBandSite, &pBs));
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IUnknown_QueryInterface pBs failed: %x\n", hr);
goto cleanup;
}
/* Finally we have the IBandSite interface, there's only one
band in it that apparently provides the IMenuBand interface */
hr = pBs->EnumBands(0, &dwBandId);
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IBandSite_EnumBands failed: %x\n", hr);
goto cleanup;
}
hr = pBs->GetBandObject(dwBandId, IID_PPV_ARG(IMenuBand, &pMb));
if (FAILED_UNEXPECTEDLY(hr))
{
TRACE("IBandSite_GetBandObject failed: %x\n", hr);
goto cleanup;
}
UpdateStartMenu(pMp,
hbmBanner,
bSmallIcons);
cleanup:
if (SUCCEEDED(hr))
*ppMenuBand = pMb;
else if (pMb != NULL)
pMb->Release();
if (pBs != NULL)
pBs->Release();
if (pUnk != NULL)
pUnk->Release();
if (pOws != NULL)
pOws->Release();
if (pMp != NULL)
pMp->Release();
if (pSms != NULL)
pSms->Release();
if (FAILED_UNEXPECTEDLY(hr))
return NULL;
return pMp;
}

View File

@ -0,0 +1,412 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
/*****************************************************************************
** IStartMenuSite ***********************************************************
*****************************************************************************/
class CStartMenuSite :
public CComCoClass<CStartMenuSite>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IStartMenuSite,
public IServiceProvider,
public ITrayPriv,
public IOleCommandTarget,
public IMenuPopup
{
CComPtr<ITrayWindow> Tray;
CComPtr<IMenuPopup> StartMenuPopup;
public:
CStartMenuSite()
{
}
virtual ~CStartMenuSite() {}
/*******************************************************************/
virtual HRESULT STDMETHODCALLTYPE QueryService(
IN REFGUID guidService,
IN REFIID riid,
OUT PVOID *ppvObject)
{
if (IsEqualGUID(guidService, SID_SMenuPopup))
{
return QueryInterface(riid, ppvObject);
}
return E_NOINTERFACE;
}
/*******************************************************************/
virtual HRESULT STDMETHODCALLTYPE GetWindow(
OUT HWND *phwnd)
{
TRACE("ITrayPriv::GetWindow\n");
*phwnd = Tray->GetHWND();
if (*phwnd != NULL)
return S_OK;
return E_FAIL;
}
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
IN BOOL fEnterMode)
{
TRACE("ITrayPriv::ContextSensitiveHelp\n");
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Execute(
IN IShellFolder *pShellFolder,
IN LPCITEMIDLIST pidl)
{
HMODULE hShlwapi;
HRESULT ret = S_FALSE;
TRACE("ITrayPriv::Execute\n");
hShlwapi = GetModuleHandle(TEXT("SHLWAPI.DLL"));
if (hShlwapi != NULL)
{
SHINVDEFCMD SHInvokeDefCmd;
/* SHInvokeDefaultCommand */
SHInvokeDefCmd = (SHINVDEFCMD) GetProcAddress(hShlwapi,
(LPCSTR) ((LONG) 279));
if (SHInvokeDefCmd != NULL)
{
ret = SHInvokeDefCmd(Tray->GetHWND(),
pShellFolder,
pidl);
}
}
return ret;
}
virtual HRESULT STDMETHODCALLTYPE Unknown(
IN PVOID Unknown1,
IN PVOID Unknown2,
IN PVOID Unknown3,
IN PVOID Unknown4)
{
TRACE("ITrayPriv::Unknown(0x%p,0x%p,0x%p,0x%p)\n", Unknown1, Unknown2, Unknown3, Unknown4);
return E_NOTIMPL;
}
virtual BOOL
ShowUndockMenuItem(VOID)
{
TRACE("ShowUndockMenuItem() not implemented!\n");
/* FIXME: How do we detect this?! */
return FALSE;
}
virtual BOOL
ShowSynchronizeMenuItem(VOID)
{
TRACE("ShowSynchronizeMenuItem() not implemented!\n");
/* FIXME: How do we detect this?! */
return FALSE;
}
virtual HRESULT STDMETHODCALLTYPE AppendMenu(
OUT HMENU* phMenu)
{
HMENU hMenu, hSettingsMenu;
DWORD dwLogoff;
BOOL bWantLogoff;
UINT uLastItemsCount = 5; /* 5 menu items below the last separator */
WCHAR szUser[128];
TRACE("ITrayPriv::AppendMenu\n");
hMenu = LoadPopupMenu(hExplorerInstance,
MAKEINTRESOURCE(IDM_STARTMENU));
*phMenu = hMenu;
if (hMenu == NULL)
return E_FAIL;
/* Remove menu items that don't apply */
dwLogoff = SHRestricted(REST_STARTMENULOGOFF);
bWantLogoff = (dwLogoff == 2 ||
SHRestricted(REST_FORCESTARTMENULOGOFF) ||
GetExplorerRegValueSet(HKEY_CURRENT_USER,
TEXT("Advanced"),
TEXT("StartMenuLogoff")));
/* Favorites */
if (!GetExplorerRegValueSet(HKEY_CURRENT_USER,
TEXT("Advanced"),
TEXT("StartMenuFavorites")))
{
DeleteMenu(hMenu,
IDM_FAVORITES,
MF_BYCOMMAND);
}
/* Documents */
if (SHRestricted(REST_NORECENTDOCSMENU))
{
DeleteMenu(hMenu,
IDM_DOCUMENTS,
MF_BYCOMMAND);
}
/* Settings */
hSettingsMenu = FindSubMenu(hMenu,
IDM_SETTINGS,
FALSE);
if (hSettingsMenu != NULL)
{
if (SHRestricted(REST_NOSETFOLDERS))
{
/* Control Panel */
if (SHRestricted(REST_NOCONTROLPANEL))
{
DeleteMenu(hSettingsMenu,
IDM_CONTROLPANEL,
MF_BYCOMMAND);
/* Delete the separator below it */
DeleteMenu(hSettingsMenu,
0,
MF_BYPOSITION);
}
/* Network Connections */
if (SHRestricted(REST_NONETWORKCONNECTIONS))
{
DeleteMenu(hSettingsMenu,
IDM_NETWORKCONNECTIONS,
MF_BYCOMMAND);
}
/* Printers and Faxes */
DeleteMenu(hSettingsMenu,
IDM_PRINTERSANDFAXES,
MF_BYCOMMAND);
}
/* Security */
if (GetSystemMetrics(SM_REMOTECONTROL) == 0 ||
SHRestricted(REST_NOSECURITY))
{
DeleteMenu(hSettingsMenu,
IDM_SECURITY,
MF_BYCOMMAND);
}
if (GetMenuItemCount(hSettingsMenu) == 0)
{
DeleteMenu(hMenu,
IDM_SETTINGS,
MF_BYCOMMAND);
}
}
/* Search */
/* FIXME: Enable after implementing */
/* if (SHRestricted(REST_NOFIND)) */
{
DeleteMenu(hMenu,
IDM_SEARCH,
MF_BYCOMMAND);
}
/* FIXME: Help */
/* Run */
if (SHRestricted(REST_NORUN))
{
DeleteMenu(hMenu,
IDM_RUN,
MF_BYCOMMAND);
}
/* Synchronize */
if (!ShowSynchronizeMenuItem())
{
DeleteMenu(hMenu,
IDM_SYNCHRONIZE,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Log off */
if (dwLogoff != 1 && bWantLogoff)
{
/* FIXME: We need a more sophisticated way to determine whether to show
or hide it, it might be hidden in too many cases!!! */
/* Update Log Off menu item */
if (!GetCurrentLoggedOnUserName(szUser,
sizeof(szUser) / sizeof(szUser[0])))
{
szUser[0] = _T('\0');
}
if (!FormatMenuString(hMenu,
IDM_LOGOFF,
MF_BYCOMMAND,
szUser))
{
/* We couldn't update the menu item, delete it... */
DeleteMenu(hMenu,
IDM_LOGOFF,
MF_BYCOMMAND);
}
}
else
{
DeleteMenu(hMenu,
IDM_LOGOFF,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Disconnect */
if (GetSystemMetrics(SM_REMOTECONTROL) == 0)
{
DeleteMenu(hMenu,
IDM_DISCONNECT,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Undock computer */
if (!ShowUndockMenuItem())
{
DeleteMenu(hMenu,
IDM_UNDOCKCOMPUTER,
MF_BYCOMMAND);
uLastItemsCount--;
}
/* Shut down */
if (SHRestricted(REST_NOCLOSE))
{
DeleteMenu(hMenu,
IDM_SHUTDOWN,
MF_BYCOMMAND);
uLastItemsCount--;
}
if (uLastItemsCount == 0)
{
/* Remove the separator at the end of the menu */
DeleteMenu(hMenu,
IDM_LASTSTARTMENU_SEPARATOR,
MF_BYCOMMAND);
}
return S_OK;
}
/*******************************************************************/
virtual HRESULT STDMETHODCALLTYPE QueryStatus(
IN const GUID *pguidCmdGroup OPTIONAL,
IN ULONG cCmds,
IN OUT OLECMD *prgCmds,
IN OUT OLECMDTEXT *pCmdText OPTIONAL)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Exec(
IN const GUID *pguidCmdGroup OPTIONAL,
IN DWORD nCmdID,
IN DWORD nCmdExecOpt,
IN VARIANTARG *pvaIn OPTIONAL,
IN VARIANTARG *pvaOut OPTIONAL)
{
return E_NOTIMPL;
}
/*******************************************************************/
virtual HRESULT STDMETHODCALLTYPE SetClient(IUnknown *punkClient)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetClient(IUnknown ** ppunkClient)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(RECT *prc)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnSelect(DWORD dwSelectType)
{
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE SetSubMenu(IMenuPopup *pmp, BOOL fSet)
{
if (!fSet)
{
return Tray_OnStartMenuDismissed();
}
return S_OK;
}
/*******************************************************************/
HRESULT Initialize(IN ITrayWindow *tray)
{
Tray = tray;
return S_OK;
}
DECLARE_NOT_AGGREGATABLE(CStartMenuSite)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CStartMenuSite)
COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
COM_INTERFACE_ENTRY_IID(IID_ITrayPriv, ITrayPriv)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
END_COM_MAP()
};
HRESULT CreateStartMenuSite(IN OUT ITrayWindow *Tray, const IID & riid, PVOID * ppv)
{
return ShellObjectCreatorInit<CStartMenuSite>(Tray, riid, ppv);
}

View File

@ -75,12 +75,12 @@ static int runCmd(LPWSTR cmdline, LPCWSTR dir, BOOL wait, BOOL minimized)
if (!CreateProcessW(NULL, szCmdLineExp, NULL, NULL, FALSE, 0, NULL, dir, &si, &info))
{
DbgPrint("Failed to run command (%lu)\n", GetLastError());
TRACE("Failed to run command (%lu)\n", GetLastError());
return INVALID_RUNCMD_RETURN;
}
DbgPrint("Successfully ran command\n");
TRACE("Successfully ran command\n");
if (wait)
{ /* wait for the process to exit */
@ -114,9 +114,9 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
WCHAR *szValue = NULL;
if (hkRoot == HKEY_LOCAL_MACHINE)
DbgPrint("processing %ls entries under HKLM\n", szKeyName);
TRACE("processing %ls entries under HKLM\n", szKeyName);
else
DbgPrint("processing %ls entries under HKCU\n", szKeyName);
TRACE("processing %ls entries under HKCU\n", szKeyName);
res = RegOpenKeyExW(hkRoot,
L"Software\\Microsoft\\Windows\\CurrentVersion",
@ -125,7 +125,7 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
&hkWin);
if (res != ERROR_SUCCESS)
{
DbgPrint("RegOpenKey failed on Software\\Microsoft\\Windows\\CurrentVersion (%ld)\n", res);
TRACE("RegOpenKey failed on Software\\Microsoft\\Windows\\CurrentVersion (%ld)\n", res);
goto end;
}
@ -139,12 +139,12 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
{
if (res == ERROR_FILE_NOT_FOUND)
{
DbgPrint("Key doesn't exist - nothing to be done\n");
TRACE("Key doesn't exist - nothing to be done\n");
res = ERROR_SUCCESS;
}
else
DbgPrint("RegOpenKeyEx failed on run key (%ld)\n", res);
TRACE("RegOpenKeyEx failed on run key (%ld)\n", res);
goto end;
}
@ -163,37 +163,37 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
NULL);
if (res != ERROR_SUCCESS)
{
DbgPrint("Couldn't query key info (%ld)\n", res);
TRACE("Couldn't query key info (%ld)\n", res);
goto end;
}
if (i == 0)
{
DbgPrint("No commands to execute.\n");
TRACE("No commands to execute.\n");
res = ERROR_SUCCESS;
goto end;
}
szCmdLine = HeapAlloc(hProcessHeap,
szCmdLine = (WCHAR*)HeapAlloc(hProcessHeap,
0,
cbMaxCmdLine);
if (szCmdLine == NULL)
{
DbgPrint("Couldn't allocate memory for the commands to be executed\n");
TRACE("Couldn't allocate memory for the commands to be executed\n");
res = ERROR_NOT_ENOUGH_MEMORY;
goto end;
}
++cchMaxValue;
szValue = HeapAlloc(hProcessHeap,
szValue = (WCHAR*)HeapAlloc(hProcessHeap,
0,
cchMaxValue * sizeof(*szValue));
if (szValue == NULL)
{
DbgPrint("Couldn't allocate memory for the value names\n");
TRACE("Couldn't allocate memory for the value names\n");
res = ERROR_NOT_ENOUGH_MEMORY;
goto end;
@ -216,7 +216,7 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
&cbDataLength);
if (res != ERROR_SUCCESS)
{
DbgPrint("Couldn't read in value %lu - %ld\n", i, res);
TRACE("Couldn't read in value %lu - %ld\n", i, res);
continue;
}
@ -226,12 +226,12 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
if (bDelete && (res = RegDeleteValueW(hkRun, szValue)) != ERROR_SUCCESS)
{
DbgPrint("Couldn't delete value - %lu, %ld. Running command anyways.\n", i, res);
TRACE("Couldn't delete value - %lu, %ld. Running command anyways.\n", i, res);
}
if (type != REG_SZ)
{
DbgPrint("Incorrect type of value #%lu (%lu)\n", i, type);
TRACE("Incorrect type of value #%lu (%lu)\n", i, type);
continue;
}
@ -239,10 +239,10 @@ static BOOL ProcessRunKeys(HKEY hkRoot, LPCWSTR szKeyName, BOOL bDelete,
res = runCmd(szCmdLine, NULL, bSynchronous, FALSE);
if (res == INVALID_RUNCMD_RETURN)
{
DbgPrint("Error running cmd #%lu (%lu)\n", i, GetLastError());
TRACE("Error running cmd #%lu (%lu)\n", i, GetLastError());
}
DbgPrint("Done processing cmd #%lu\n", i);
TRACE("Done processing cmd #%lu\n", i);
}
res = ERROR_SUCCESS;
@ -256,7 +256,7 @@ end:
if (hkWin != NULL)
RegCloseKey(hkWin);
DbgPrint("done\n");
TRACE("done\n");
return res == ERROR_SUCCESS ? TRUE : FALSE;
}
@ -276,14 +276,14 @@ ProcessStartupItems(VOID)
res = GetWindowsDirectoryW(gen_path, sizeof(gen_path) / sizeof(gen_path[0]));
if (res == 0)
{
DbgPrint("Couldn't get the windows directory - error %lu\n", GetLastError());
TRACE("Couldn't get the windows directory - error %lu\n", GetLastError());
return 100;
}
if (!SetCurrentDirectoryW(gen_path))
{
DbgPrint("Cannot set the dir to %ls (%lu)\n", gen_path, GetLastError());
TRACE("Cannot set the dir to %ls (%lu)\n", gen_path, GetLastError());
return 100;
}
@ -330,7 +330,7 @@ ProcessStartupItems(VOID)
if (res && bNormalBoot && (SHRestricted(REST_NOCURRENTUSERRUNONCE) == 0))
res = ProcessRunKeys(HKEY_CURRENT_USER, L"RunOnce", TRUE, FALSE);
DbgPrint("Operation done\n");
TRACE("Operation done\n");
return res ? 0 : 101;
}

View File

@ -1,663 +0,0 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
/*****************************************************************************
** ITaskBand ****************************************************************
*****************************************************************************/
const GUID CLSID_ITaskBand = {0x68284FAA,0x6A48,0x11D0,{0x8C,0x78,0x00,0xC0,0x4F,0xD9,0x18,0xB4}};
static const ITaskBandVtbl ITaskBandImpl_Vtbl;
static const IDeskBandVtbl IDeskBandImpl_Vtbl;
static const IObjectWithSiteVtbl IObjectWithSiteImpl_Vtbl;
static const IDeskBarVtbl IDeskBarImpl_Vtbl;
static const IPersistStreamVtbl IPersistStreamImpl_Vtbl;
static const IWinEventHandlerVtbl IWinEventHandlerImpl_Vtbl;
typedef struct
{
const ITaskBandVtbl *lpVtbl;
const IDeskBandVtbl *lpDeskBandVtbl;
const IObjectWithSiteVtbl *lpObjectWithSiteVtbl;
const IDeskBarVtbl *lpDeskBarVtbl;
const IPersistStreamVtbl *lpPersistStreamVtbl;
const IWinEventHandlerVtbl *lpWindowEventHandlerVtbl;
/* FIXME: Implement IOleCommandTarget */
LONG Ref;
ITrayWindow *Tray;
IUnknown *punkSite;
HWND hWnd;
DWORD dwBandID;
} ITaskBandImpl;
static IUnknown *
IUnknown_from_ITaskBandImpl(ITaskBandImpl *This)
{
return (IUnknown *)&This->lpVtbl;
}
IMPL_CASTS(ITaskBand, ITaskBand, lpVtbl)
IMPL_CASTS(IDeskBand, ITaskBand, lpDeskBandVtbl)
IMPL_CASTS(IObjectWithSite, ITaskBand, lpObjectWithSiteVtbl)
IMPL_CASTS(IDeskBar, ITaskBand, lpDeskBarVtbl)
IMPL_CASTS(IPersistStream, ITaskBand, lpPersistStreamVtbl)
IMPL_CASTS(IWinEventHandler, ITaskBand, lpWindowEventHandlerVtbl)
static ULONG STDMETHODCALLTYPE
ITaskBandImpl_AddRef(IN OUT ITaskBand *iface)
{
ITaskBandImpl *This = ITaskBandImpl_from_ITaskBand(iface);
return InterlockedIncrement(&This->Ref);
}
static VOID
ITaskBandImpl_Free(IN OUT ITaskBandImpl *This)
{
if (This->punkSite != NULL)
{
IUnknown_Release(This->punkSite);
This->punkSite = NULL;
}
HeapFree(hProcessHeap,
0,
This);
}
static ULONG STDMETHODCALLTYPE
ITaskBandImpl_Release(IN OUT ITaskBand *iface)
{
ITaskBandImpl *This = ITaskBandImpl_from_ITaskBand(iface);
ULONG Ret;
Ret = InterlockedDecrement(&This->Ref);
if (Ret == 0)
ITaskBandImpl_Free(This);
return Ret;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_QueryInterface(IN OUT ITaskBand *iface,
IN REFIID riid,
OUT LPVOID *ppvObj)
{
ITaskBandImpl *This;
if (ppvObj == NULL)
return E_POINTER;
This = ITaskBandImpl_from_ITaskBand(iface);
if (IsEqualIID(riid,
&IID_IUnknown))
{
*ppvObj = IUnknown_from_ITaskBandImpl(This);
}
else if (IsEqualIID(riid,
&IID_IDeskBand) ||
IsEqualIID(riid,
&IID_IOleWindow) ||
IsEqualIID(riid,
&IID_IDockingWindow))
{
*ppvObj = IDeskBand_from_ITaskBandImpl(This);
}
else if (IsEqualIID(riid,
&IID_IObjectWithSite))
{
*ppvObj = IObjectWithSite_from_ITaskBandImpl(This);
}
else if (IsEqualIID(riid,
&IID_IDeskBar))
{
*ppvObj = IDeskBar_from_ITaskBandImpl(This);
}
else if (IsEqualIID(riid,
&IID_IWinEventHandler))
{
/* When run on Windows the system queries this interface, which is completely
undocumented :( It's queried during initialization of the tray band site.
The system apparently uses this interface to forward messages to be handled
by the band child window. This interface appears to be implemented by a number
of classes provided by the shell, including the IBandSite interface. In that
we (the host application) forward messages to the default message handler (in
our case the IBandSite default message handler for the Rebar control)! This
interface in the ITaskBand implementation is only actually used if we use
the same interface to forward messages to the IBandSite implementation of
the shell! */
*ppvObj = IWinEventHandler_from_ITaskBandImpl(This);
}
#if 0
else if (IsEqualIID(riid,
&IID_IPersistStream) ||
IsEqualIID(riid,
&IID_IPersist))
{
*ppvObj = IPersistStream_from_ITaskBandImpl(This);
}
#endif
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
ITaskBandImpl_AddRef(iface);
return S_OK;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_GetRebarBandID(IN OUT ITaskBand *iface,
OUT DWORD *pdwBandID)
{
ITaskBandImpl *This = ITaskBandImpl_from_ITaskBand(iface);
if (This->dwBandID != (DWORD)-1)
{
if (pdwBandID != NULL)
*pdwBandID = This->dwBandID;
return S_OK;
}
return E_FAIL;
}
static const ITaskBandVtbl ITaskBandImpl_Vtbl =
{
/*** IUnknown methods ***/
ITaskBandImpl_QueryInterface,
ITaskBandImpl_AddRef,
ITaskBandImpl_Release,
/*** ITaskBand methods ***/
ITaskBandImpl_GetRebarBandID
};
/*****************************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IDeskBand, ITaskBand)
METHOD_IUNKNOWN_INHERITED_RELEASE(IDeskBand, ITaskBand)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IDeskBand, ITaskBand)
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_GetWindow(IN OUT IDeskBand *iface,
OUT HWND *phwnd)
{
ITaskBandImpl *This = ITaskBandImpl_from_IDeskBand(iface);
/* NOTE: We have to return the tray window here so that ITaskBarClient
knows the parent window of the Rebar control it creates when
calling ITaskBarClient::SetDeskBarSite()! However, once we
created a window we return the task switch window! */
if (This->hWnd != NULL)
*phwnd = This->hWnd;
else
*phwnd = ITrayWindow_GetHWND(This->Tray);
DbgPrint("ITaskBand::GetWindow(0x%p->0x%p)\n", phwnd, *phwnd);
if (*phwnd != NULL)
return S_OK;
return E_FAIL;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_ContextSensitiveHelp(IN OUT IDeskBand *iface,
IN BOOL fEnterMode)
{
/* FIXME: Implement */
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_ShowDW(IN OUT IDeskBand *iface,
IN BOOL bShow)
{
/* We don't do anything... */
return S_OK;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_CloseDW(IN OUT IDeskBand *iface,
IN DWORD dwReserved)
{
/* We don't do anything... */
return S_OK;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_ResizeBoderDW(IN OUT IDeskBand *iface,
IN LPCRECT prcBorder,
IN IUnknown *punkToolbarSite,
IN BOOL fReserved)
{
/* No need to implement this method */
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_GetBandInfo(IN OUT IDeskBand *iface,
IN DWORD dwBandID,
IN DWORD dwViewMode,
IN OUT DESKBANDINFO *pdbi)
{
ITaskBandImpl *This = ITaskBandImpl_from_IDeskBand(iface);
DbgPrint("ITaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, This->hWnd);
/* NOTE: We could save dwBandID in the instance in case we need it later... */
if (This->hWnd != NULL)
{
/* The task band never has a title */
pdbi->dwMask &= ~DBIM_TITLE;
/* NOTE: We don't return DBIMF_UNDELETEABLE here, the band site will
handle us differently and add this flag for us. The reason for
this is future changes that might allow it to be deletable.
We want the band site to be in charge of this decision rather
the band itself! */
/* FIXME: What about DBIMF_NOGRIPPER and DBIMF_ALWAYSGRIPPER */
pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
if (dwViewMode & DBIF_VIEWMODE_VERTICAL)
{
pdbi->ptIntegral.y = 1;
pdbi->ptMinSize.y = 1;
/* FIXME: Get the button metrics from the task bar object!!! */
pdbi->ptMinSize.x = (3 * GetSystemMetrics(SM_CXEDGE) / 2) + /* FIXME: Might be wrong if only one column! */
GetSystemMetrics(SM_CXSIZE) + (2 * GetSystemMetrics(SM_CXEDGE)); /* FIXME: Min button size, query!!! */
}
else
{
pdbi->ptMinSize.y = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE)); /* FIXME: Query */
pdbi->ptIntegral.y = pdbi->ptMinSize.y + (3 * GetSystemMetrics(SM_CYEDGE) / 2); /* FIXME: Query metrics */
/* We're not going to allow task bands where not even the minimum button size fits into the band */
pdbi->ptMinSize.x = pdbi->ptIntegral.y;
}
/* Ignored: pdbi->ptMaxSize.x */
pdbi->ptMaxSize.y = -1;
/* FIXME: We should query the height from the task bar object!!! */
pdbi->ptActual.y = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE));
/* Save the band ID for future use in case we need to check whether a given band
is the task band */
This->dwBandID = dwBandID;
DbgPrint("H: %d, Min: %d,%d, Integral.y: %d Actual: %d,%d\n", (dwViewMode & DBIF_VIEWMODE_VERTICAL) == 0,
pdbi->ptMinSize.x, pdbi->ptMinSize.y, pdbi->ptIntegral.y,
pdbi->ptActual.x,pdbi->ptActual.y);
return S_OK;
}
return E_FAIL;
}
static const IDeskBandVtbl IDeskBandImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IDeskBand, ITaskBand),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IDeskBand, ITaskBand),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IDeskBand, ITaskBand),
/*** IOleWindow methods ***/
ITaskBandImpl_GetWindow,
ITaskBandImpl_ContextSensitiveHelp,
/*** IDockingWindow methods ***/
ITaskBandImpl_ShowDW,
ITaskBandImpl_CloseDW,
ITaskBandImpl_ResizeBoderDW,
/*** IDeskBand methods ***/
ITaskBandImpl_GetBandInfo
};
/*****************************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IDeskBar, ITaskBand)
METHOD_IUNKNOWN_INHERITED_RELEASE(IDeskBar, ITaskBand)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IDeskBar, ITaskBand)
static HRESULT STDMETHODCALLTYPE
IDeskBarImpl_GetWindow(IN OUT IDeskBar *iface,
OUT HWND *phwnd)
{
ITaskBandImpl *This = ITaskBandImpl_from_IDeskBar(iface);
IDeskBand *DeskBand = IDeskBand_from_ITaskBandImpl(This);
/* Proxy to IDeskBand interface */
return IDeskBand_GetWindow(DeskBand,
phwnd);
}
static HRESULT STDMETHODCALLTYPE
IDeskBarImpl_ContextSensitiveHelp(IN OUT IDeskBar *iface,
IN BOOL fEnterMode)
{
ITaskBandImpl *This = ITaskBandImpl_from_IDeskBar(iface);
IDeskBand *DeskBand = IDeskBand_from_ITaskBandImpl(This);
/* Proxy to IDeskBand interface */
return IDeskBand_ContextSensitiveHelp(DeskBand,
fEnterMode);
}
static HRESULT STDMETHODCALLTYPE
IDeskBarImpl_SetClient(IN OUT IDeskBar *iface,
IN IUnknown *punkClient)
{
DbgPrint("IDeskBar::SetClient(0x%p)\n", punkClient);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
IDeskBarImpl_GetClient(IN OUT IDeskBar *iface,
OUT IUnknown **ppunkClient)
{
DbgPrint("IDeskBar::GetClient(0x%p)\n", ppunkClient);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
IDeskBarImpl_OnPosRectChangeDB(IN OUT IDeskBar *iface,
IN RECT *prc)
{
DbgPrint("IDeskBar::OnPosRectChangeDB(0x%p=(%d,%d,%d,%d))\n", prc, prc->left, prc->top, prc->right, prc->bottom);
if (prc->bottom - prc->top == 0)
return S_OK;
return S_FALSE;
}
static const IDeskBarVtbl IDeskBarImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IDeskBar, ITaskBand),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IDeskBar, ITaskBand),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IDeskBar, ITaskBand),
/*** IOleWindow methods ***/
IDeskBarImpl_GetWindow,
IDeskBarImpl_ContextSensitiveHelp,
/*** IDeskBar methods ***/
IDeskBarImpl_SetClient,
IDeskBarImpl_GetClient,
IDeskBarImpl_OnPosRectChangeDB
};
/*****************************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IPersistStream, ITaskBand)
METHOD_IUNKNOWN_INHERITED_RELEASE(IPersistStream, ITaskBand)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IPersistStream, ITaskBand)
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_GetClassID(IN OUT IPersistStream *iface,
OUT CLSID *pClassID)
{
DbgPrint("ITaskBand::GetClassID(0x%p)\n", pClassID);
/* We're going to return the (internal!) CLSID of the task band interface */
*pClassID = CLSID_ITaskBand;
return S_OK;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_IsDirty(IN OUT IPersistStream *iface)
{
/* The object hasn't changed since the last save! */
return S_FALSE;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_Load(IN OUT IPersistStream *iface,
IN IStream *pStm)
{
DbgPrint("ITaskBand::Load called\n");
/* Nothing to do */
return S_OK;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_Save(IN OUT IPersistStream *iface,
IN IStream *pStm,
IN BOOL fClearDirty)
{
/* Nothing to do */
return S_OK;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_GetSizeMax(IN OUT IPersistStream *iface,
OUT ULARGE_INTEGER *pcbSize)
{
DbgPrint("ITaskBand::GetSizeMax called\n");
/* We don't need any space for the task band */
pcbSize->QuadPart = 0;
return S_OK;
}
static const IPersistStreamVtbl IPersistStreamImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IPersistStream, ITaskBand),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IPersistStream, ITaskBand),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IPersistStream, ITaskBand),
/*** IPersist methods ***/
ITaskBandImpl_GetClassID,
/*** IPersistStream methods ***/
ITaskBandImpl_IsDirty,
ITaskBandImpl_Load,
ITaskBandImpl_Save,
ITaskBandImpl_GetSizeMax
};
/*****************************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IObjectWithSite, ITaskBand)
METHOD_IUNKNOWN_INHERITED_RELEASE(IObjectWithSite, ITaskBand)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IObjectWithSite, ITaskBand)
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_SetSite(IN OUT IObjectWithSite *iface,
IN IUnknown* pUnkSite)
{
ITaskBandImpl *This = ITaskBandImpl_from_IObjectWithSite(iface);
HRESULT hRet = E_FAIL;
DbgPrint("ITaskBand::SetSite(0x%p)\n", pUnkSite);
/* Release the current site */
if (This->punkSite != NULL)
{
IUnknown_Release(This->punkSite);
}
This->punkSite = NULL;
This->hWnd = NULL;
if (pUnkSite != NULL)
{
IOleWindow *OleWindow;
/* Check if the site supports IOleWindow */
hRet = IUnknown_QueryInterface(pUnkSite,
&IID_IOleWindow,
(PVOID *)&OleWindow);
if (SUCCEEDED(hRet))
{
HWND hWndParent = NULL;
hRet = IOleWindow_GetWindow(OleWindow,
&hWndParent);
if (SUCCEEDED(hRet))
{
/* Attempt to create the task switch window */
DbgPrint("CreateTaskSwitchWnd(Parent: 0x%p)\n", hWndParent);
This->hWnd = CreateTaskSwitchWnd(hWndParent,
This->Tray);
if (This->hWnd != NULL)
{
This->punkSite = pUnkSite;
hRet = S_OK;
}
else
{
DbgPrint("CreateTaskSwitchWnd() failed!\n");
IUnknown_Release(OleWindow);
hRet = E_FAIL;
}
}
else
IUnknown_Release(OleWindow);
}
else
DbgPrint("Querying IOleWindow failed: 0x%x\n", hRet);
}
return hRet;
}
static HRESULT STDMETHODCALLTYPE
ITaskBandImpl_GetSite(IN OUT IObjectWithSite *iface,
IN REFIID riid,
OUT VOID **ppvSite)
{
ITaskBandImpl *This = ITaskBandImpl_from_IObjectWithSite(iface);
DbgPrint("ITaskBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
if (This->punkSite != NULL)
{
return IUnknown_QueryInterface(This->punkSite,
riid,
ppvSite);
}
*ppvSite = NULL;
return E_FAIL;
}
static const IObjectWithSiteVtbl IObjectWithSiteImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IObjectWithSite, ITaskBand),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IObjectWithSite, ITaskBand),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IObjectWithSite, ITaskBand),
/*** IObjectWithSite methods ***/
ITaskBandImpl_SetSite,
ITaskBandImpl_GetSite
};
/*****************************************************************************/
METHOD_IUNKNOWN_INHERITED_ADDREF(IWinEventHandler, ITaskBand)
METHOD_IUNKNOWN_INHERITED_RELEASE(IWinEventHandler, ITaskBand)
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE(IWinEventHandler, ITaskBand)
static HRESULT STDMETHODCALLTYPE
IWinEventHandlerImpl_ProcessMessage(IN OUT IWinEventHandler *iface,
IN HWND hWnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam,
OUT LRESULT *plrResult)
{
DbgPrint("ITaskBand: IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd, uMsg, wParam, lParam, plrResult);
return E_NOTIMPL;
}
static HRESULT STDMETHODCALLTYPE
IWinEventHandlerImpl_ContainsWindow(IN OUT IWinEventHandler *iface,
IN HWND hWnd)
{
ITaskBandImpl *This = ITaskBandImpl_from_IWinEventHandler(iface);
HRESULT hRet = S_OK;
if (This->hWnd != hWnd ||
!IsChild(This->hWnd,
hWnd))
{
hRet = S_FALSE;
}
DbgPrint("ITaskBand::ContainsWindow(0x%p) returns %s\n", hWnd, hRet == S_OK ? "S_OK" : "S_FALSE");
return hRet;
}
static const IWinEventHandlerVtbl IWinEventHandlerImpl_Vtbl =
{
/*** IUnknown methods ***/
METHOD_IUNKNOWN_INHERITED_QUERYINTERFACE_NAME(IWinEventHandler, ITaskBand),
METHOD_IUNKNOWN_INHERITED_ADDREF_NAME(IWinEventHandler, ITaskBand),
METHOD_IUNKNOWN_INHERITED_RELEASE_NAME(IWinEventHandler, ITaskBand),
/*** IWinEventHandler methods ***/
IWinEventHandlerImpl_ProcessMessage,
IWinEventHandlerImpl_ContainsWindow
};
/*****************************************************************************/
static ITaskBandImpl *
ITaskBandImpl_Construct(IN OUT ITrayWindow *Tray)
{
ITaskBandImpl *This;
This = HeapAlloc(hProcessHeap,
HEAP_ZERO_MEMORY,
sizeof(*This));
if (This == NULL)
return NULL;
This->lpVtbl = &ITaskBandImpl_Vtbl;
This->lpDeskBandVtbl = &IDeskBandImpl_Vtbl;
This->lpObjectWithSiteVtbl = &IObjectWithSiteImpl_Vtbl;
This->lpDeskBarVtbl = &IDeskBarImpl_Vtbl;
This->lpPersistStreamVtbl = &IPersistStreamImpl_Vtbl;
This->lpWindowEventHandlerVtbl = &IWinEventHandlerImpl_Vtbl;
This->Ref = 1;
This->Tray = Tray;
This->dwBandID = (DWORD)-1;
return This;
}
ITaskBand *
CreateTaskBand(IN OUT ITrayWindow *Tray)
{
ITaskBandImpl *This;
This = ITaskBandImpl_Construct(Tray);
if (This != NULL)
{
return ITaskBand_from_ITaskBandImpl(This);
}
return NULL;
}

View File

@ -0,0 +1,420 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
/*****************************************************************************
** ITaskBand ****************************************************************
*****************************************************************************/
const GUID CLSID_ITaskBand = { 0x68284FAA, 0x6A48, 0x11D0, { 0x8C, 0x78, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xB4 } };
class CTaskBand :
public CComCoClass<CTaskBand>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IObjectWithSite,
public ITaskBand,
public IDeskBand,
public IDeskBar,
public IPersistStream,
public IWinEventHandler,
public IOleCommandTarget
{
CComPtr<ITrayWindow> Tray;
CComPtr<IUnknown> punkSite;
HWND hWnd;
DWORD dwBandID;
public:
CTaskBand() :
hWnd(NULL),
dwBandID(0)
{
}
virtual ~CTaskBand() { }
virtual HRESULT STDMETHODCALLTYPE GetRebarBandID(
OUT DWORD *pdwBandID)
{
if (dwBandID != (DWORD) -1)
{
if (pdwBandID != NULL)
*pdwBandID = dwBandID;
return S_OK;
}
return E_FAIL;
}
/*****************************************************************************/
virtual HRESULT STDMETHODCALLTYPE GetWindow(
OUT HWND *phwnd)
{
/* NOTE: We have to return the tray window here so that ITaskBarClient
knows the parent window of the Rebar control it creates when
calling ITaskBarClient::SetDeskBarSite()! However, once we
created a window we return the task switch window! */
if (hWnd != NULL)
*phwnd = hWnd;
else
*phwnd = Tray->GetHWND();
TRACE("ITaskBand::GetWindow(0x%p->0x%p)\n", phwnd, *phwnd);
if (*phwnd != NULL)
return S_OK;
return E_FAIL;
}
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(
IN BOOL fEnterMode)
{
/* FIXME: Implement */
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ShowDW(
IN BOOL bShow)
{
/* We don't do anything... */
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE CloseDW(
IN DWORD dwReserved)
{
/* We don't do anything... */
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(
LPCRECT prcBorder,
IUnknown *punkToolbarSite,
BOOL fReserved)
{
/* No need to implement this method */
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetBandInfo(
IN DWORD dwBandID,
IN DWORD dwViewMode,
IN OUT DESKBANDINFO *pdbi)
{
TRACE("ITaskBand::GetBandInfo(0x%x,0x%x,0x%p) hWnd=0x%p\n", dwBandID, dwViewMode, pdbi, hWnd);
if (hWnd != NULL)
{
/* The task band never has a title */
pdbi->dwMask &= ~DBIM_TITLE;
/* NOTE: We don't return DBIMF_UNDELETEABLE here, the band site will
handle us differently and add this flag for us. The reason for
this is future changes that might allow it to be deletable.
We want the band site to be in charge of this decision rather
the band itself! */
/* FIXME: What about DBIMF_NOGRIPPER and DBIMF_ALWAYSGRIPPER */
pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT;
if (dwViewMode & DBIF_VIEWMODE_VERTICAL)
{
pdbi->ptIntegral.y = 1;
pdbi->ptMinSize.y = 1;
/* FIXME: Get the button metrics from the task bar object!!! */
pdbi->ptMinSize.x = (3 * GetSystemMetrics(SM_CXEDGE) / 2) + /* FIXME: Might be wrong if only one column! */
GetSystemMetrics(SM_CXSIZE) + (2 * GetSystemMetrics(SM_CXEDGE)); /* FIXME: Min button size, query!!! */
}
else
{
pdbi->ptMinSize.y = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE)); /* FIXME: Query */
pdbi->ptIntegral.y = pdbi->ptMinSize.y + (3 * GetSystemMetrics(SM_CYEDGE) / 2); /* FIXME: Query metrics */
/* We're not going to allow task bands where not even the minimum button size fits into the band */
pdbi->ptMinSize.x = pdbi->ptIntegral.y;
}
/* Ignored: pdbi->ptMaxSize.x */
pdbi->ptMaxSize.y = -1;
/* FIXME: We should query the height from the task bar object!!! */
pdbi->ptActual.y = GetSystemMetrics(SM_CYSIZE) + (2 * GetSystemMetrics(SM_CYEDGE));
/* Save the band ID for future use in case we need to check whether a given band
is the task band */
this->dwBandID = dwBandID;
TRACE("H: %d, Min: %d,%d, Integral.y: %d Actual: %d,%d\n", (dwViewMode & DBIF_VIEWMODE_VERTICAL) == 0,
pdbi->ptMinSize.x, pdbi->ptMinSize.y, pdbi->ptIntegral.y,
pdbi->ptActual.x, pdbi->ptActual.y);
return S_OK;
}
return E_FAIL;
}
/*****************************************************************************/
// *** IOleCommandTarget methods ***
virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE 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;
}
/*****************************************************************************/
virtual HRESULT STDMETHODCALLTYPE SetClient(
IN IUnknown *punkClient)
{
TRACE("IDeskBar::SetClient(0x%p)\n", punkClient);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE GetClient(
OUT IUnknown **ppunkClient)
{
TRACE("IDeskBar::GetClient(0x%p)\n", ppunkClient);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(
IN RECT *prc)
{
TRACE("IDeskBar::OnPosRectChangeDB(0x%p=(%d,%d,%d,%d))\n", prc, prc->left, prc->top, prc->right, prc->bottom);
if (prc->bottom - prc->top == 0)
return S_OK;
return S_FALSE;
}
/*****************************************************************************/
virtual HRESULT STDMETHODCALLTYPE GetClassID(
OUT CLSID *pClassID)
{
TRACE("ITaskBand::GetClassID(0x%p)\n", pClassID);
/* We're going to return the (internal!) CLSID of the task band interface */
*pClassID = CLSID_ITaskBand;
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE IsDirty()
{
/* The object hasn't changed since the last save! */
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE Load(
IN IStream *pStm)
{
TRACE("ITaskBand::Load called\n");
/* Nothing to do */
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE Save(
IN IStream *pStm,
IN BOOL fClearDirty)
{
/* Nothing to do */
return S_OK;
}
virtual HRESULT STDMETHODCALLTYPE GetSizeMax(
OUT ULARGE_INTEGER *pcbSize)
{
TRACE("ITaskBand::GetSizeMax called\n");
/* We don't need any space for the task band */
pcbSize->QuadPart = 0;
return S_OK;
}
/*****************************************************************************/
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite)
{
HRESULT hRet = E_FAIL;
TRACE("ITaskBand::SetSite(0x%p)\n", pUnkSite);
/* Release the current site */
if (punkSite != NULL)
{
punkSite->Release();
}
punkSite = NULL;
hWnd = NULL;
if (pUnkSite != NULL)
{
IOleWindow *OleWindow;
/* Check if the site supports IOleWindow */
hRet = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &OleWindow));
if (SUCCEEDED(hRet))
{
HWND hWndParent = NULL;
hRet = OleWindow->GetWindow(
&hWndParent);
if (SUCCEEDED(hRet))
{
/* Attempt to create the task switch window */
TRACE("CreateTaskSwitchWnd(Parent: 0x%p)\n", hWndParent);
hWnd = CreateTaskSwitchWnd(hWndParent, Tray);
if (hWnd != NULL)
{
punkSite = pUnkSite;
hRet = S_OK;
}
else
{
TRACE("CreateTaskSwitchWnd() failed!\n");
OleWindow->Release();
hRet = E_FAIL;
}
}
else
OleWindow->Release();
}
else
TRACE("Querying IOleWindow failed: 0x%x\n", hRet);
}
return hRet;
}
virtual HRESULT STDMETHODCALLTYPE GetSite(
IN REFIID riid,
OUT VOID **ppvSite)
{
TRACE("ITaskBand::GetSite(0x%p,0x%p)\n", riid, ppvSite);
if (punkSite != NULL)
{
return punkSite->QueryInterface(riid, ppvSite);
}
*ppvSite = NULL;
return E_FAIL;
}
/*****************************************************************************/
virtual HRESULT STDMETHODCALLTYPE ProcessMessage(
IN HWND hWnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam,
OUT LRESULT *plrResult)
{
TRACE("ITaskBand: IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p)\n", hWnd, uMsg, wParam, lParam, plrResult);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE ContainsWindow(
IN HWND hWnd)
{
if (hWnd == hWnd ||
IsChild(hWnd, hWnd))
{
TRACE("ITaskBand::ContainsWindow(0x%p) returns S_OK\n", hWnd);
return S_OK;
}
return S_FALSE;
}
virtual HRESULT STDMETHODCALLTYPE OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd)
{
return (hWnd == this->hWnd) ? S_OK : S_FALSE;
}
/*****************************************************************************/
HRESULT STDMETHODCALLTYPE _Init(IN OUT ITrayWindow *tray)
{
Tray = tray;
dwBandID = (DWORD) -1;
return S_OK;
}
DECLARE_NOT_AGGREGATABLE(CTaskBand)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CTaskBand)
COM_INTERFACE_ENTRY2_IID(IID_IOleWindow, IOleWindow, 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)
END_COM_MAP()
};
ITaskBand * CreateTaskBand(IN OUT ITrayWindow *Tray)
{
HRESULT hr;
CTaskBand * tb = new CComObject<CTaskBand>();
if (!tb)
return NULL;
hr = tb->AddRef();
hr = tb->_Init(Tray);
if (FAILED_UNEXPECTEDLY(hr))
tb->Release();
return tb;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,829 @@
/*
* ReactOS Explorer
*
* Copyright 2006 - 2007 Thomas Weidenmueller <w3seek@reactos.org>
*
* 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"
#include <shdeprecated.h>
#include "undoc.h"
/*****************************************************************************
** ITrayBandSite ************************************************************
*****************************************************************************/
// WARNING: Can't use ATL for this class due to our ATL not fully supporting the AGGREGATION functions needed for this class to be an "outer" class
// it works just fine this way.
class CTrayBandSite :
public ITrayBandSite,
public IBandSite,
public IBandSiteStreamCallback
/* TODO: IWinEventHandler */
{
volatile LONG m_RefCount;
CComPtr<ITrayWindow> Tray;
CComPtr<IUnknown> punkInner;
CComPtr<IBandSite> BandSite;
CComPtr<ITaskBand> TaskBand;
CComPtr<IWinEventHandler> WindowEventHandler;
CComPtr<IContextMenu> ContextMenu;
HWND hWndRebar;
union
{
DWORD dwFlags;
struct
{
DWORD Locked : 1;
};
};
public:
virtual ULONG STDMETHODCALLTYPE AddRef()
{
return InterlockedIncrement(&m_RefCount);
}
virtual ULONG STDMETHODCALLTYPE Release()
{
ULONG Ret = InterlockedDecrement(&m_RefCount);
if (Ret == 0)
delete this;
return Ret;
}
virtual HRESULT STDMETHODCALLTYPE QueryInterface(IN REFIID riid, OUT LPVOID *ppvObj)
{
if (ppvObj == NULL)
return E_POINTER;
if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IBandSiteStreamCallback))
{
// return IBandSiteStreamCallback's IUnknown
*ppvObj = static_cast<IBandSiteStreamCallback*>(this);
}
else if (IsEqualIID(riid, IID_IBandSite))
{
*ppvObj = static_cast<IBandSite*>(this);
}
else if (IsEqualIID(riid, IID_IWinEventHandler))
{
TRACE("ITaskBandSite: IWinEventHandler queried!\n");
*ppvObj = NULL;
return E_NOINTERFACE;
}
else if (punkInner != NULL)
{
return punkInner->QueryInterface(riid, ppvObj);
}
else
{
*ppvObj = NULL;
return E_NOINTERFACE;
}
AddRef();
return S_OK;
}
public:
CTrayBandSite() :
m_RefCount(0),
hWndRebar(NULL)
{
}
virtual ~CTrayBandSite() { }
virtual HRESULT STDMETHODCALLTYPE OnLoad(
IN OUT IStream *pStm,
IN REFIID riid,
OUT PVOID *pvObj)
{
LARGE_INTEGER liPosZero;
ULARGE_INTEGER liCurrent;
CLSID clsid;
ULONG ulRead;
HRESULT hRet;
/* NOTE: Callback routine called by the shell while loading the task band
stream. We use it to intercept the default behavior when the task
band is loaded from the stream.
NOTE: riid always points to IID_IUnknown! This is because the shell hasn't
read anything from the stream and therefore doesn't know what CLSID
it's dealing with. We'll have to find it out ourselves by reading
the GUID from the stream. */
/* Read the current position of the stream, we'll have to reset it everytime
we read a CLSID that's not the task band... */
ZeroMemory(&liPosZero,
sizeof(liPosZero));
hRet = pStm->Seek(liPosZero, STREAM_SEEK_CUR, &liCurrent);
if (SUCCEEDED(hRet))
{
/* Now let's read the CLSID from the stream and see if it's our task band */
hRet = pStm->Read(&clsid, (ULONG)sizeof(clsid), &ulRead);
if (SUCCEEDED(hRet) && ulRead == sizeof(clsid))
{
if (IsEqualGUID(clsid, CLSID_ITaskBand))
{
ASSERT(TaskBand != NULL);
/* We're trying to load the task band! Let's create it... */
hRet = TaskBand->QueryInterface(
riid,
pvObj);
if (SUCCEEDED(hRet))
{
/* Load the stream */
TRACE("IBandSiteStreamCallback::OnLoad intercepted the task band CLSID!\n");
}
return hRet;
}
}
}
/* Reset the position and let the shell do all the work for us */
hRet = pStm->Seek(
*(LARGE_INTEGER*) &liCurrent,
STREAM_SEEK_SET,
NULL);
if (SUCCEEDED(hRet))
{
/* Let the shell handle everything else for us :) */
hRet = OleLoadFromStream(pStm,
riid,
pvObj);
}
if (!SUCCEEDED(hRet))
{
TRACE("IBandSiteStreamCallback::OnLoad(0x%p, 0x%p, 0x%p) returns 0x%x\n", pStm, riid, pvObj, hRet);
}
return hRet;
}
virtual HRESULT STDMETHODCALLTYPE OnSave(
IN OUT IUnknown *pUnk,
IN OUT IStream *pStm)
{
/* NOTE: Callback routine called by the shell while saving the task band
stream. We use it to intercept the default behavior when the task
band is saved to the stream */
/* FIXME: Implement */
TRACE("IBandSiteStreamCallback::OnSave(0x%p, 0x%p) returns E_NOTIMPL\n", pUnk, pStm);
return E_NOTIMPL;
}
virtual HRESULT STDMETHODCALLTYPE IsTaskBand(
IN IUnknown *punk)
{
return IsSameObject((IUnknown *) BandSite,
punk);
}
virtual HRESULT STDMETHODCALLTYPE ProcessMessage(
IN HWND hWnd,
IN UINT uMsg,
IN WPARAM wParam,
IN LPARAM lParam,
OUT LRESULT *plResult)
{
HRESULT hRet;
ASSERT(hWndRebar != NULL);
/* Custom task band behavior */
switch (uMsg)
{
case WM_NOTIFY:
{
const NMHDR *nmh = (const NMHDR *) lParam;
if (nmh->hwndFrom == hWndRebar)
{
switch (nmh->code)
{
case NM_NCHITTEST:
{
LPNMMOUSE nmm = (LPNMMOUSE) lParam;
if (nmm->dwHitInfo == RBHT_CLIENT || nmm->dwHitInfo == RBHT_NOWHERE ||
nmm->dwItemSpec == (DWORD_PTR) -1)
{
/* Make the rebar control appear transparent so the user
can drag the tray window */
*plResult = HTTRANSPARENT;
}
return S_OK;
}
case RBN_MINMAX:
/* Deny if an Administrator disabled this "feature" */
*plResult = (SHRestricted(REST_NOMOVINGBAND) != 0);
return S_OK;
}
}
//TRACE("ITrayBandSite::ProcessMessage: WM_NOTIFY for 0x%p, From: 0x%p, Code: NM_FIRST-%u...\n", hWnd, nmh->hwndFrom, NM_FIRST - nmh->code);
break;
}
}
/* Forward to the shell's IWinEventHandler interface to get the default shell behavior! */
if (!WindowEventHandler)
return E_FAIL;
/*TRACE("Calling IWinEventHandler::ProcessMessage(0x%p, 0x%x, 0x%p, 0x%p, 0x%p) hWndRebar=0x%p\n", hWnd, uMsg, wParam, lParam, plResult, hWndRebar);*/
hRet = WindowEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, plResult);
#if 0
if (FAILED(hRet))
{
if (uMsg == WM_NOTIFY)
{
const NMHDR *nmh = (const NMHDR *) lParam;
ERR("ITrayBandSite->IWinEventHandler::ProcessMessage: WM_NOTIFY for 0x%p, From: 0x%p, Code: NM_FIRST-%u returned 0x%x\n", hWnd, nmh->hwndFrom, NM_FIRST - nmh->code, hRet);
}
else
{
ERR("ITrayBandSite->IWinEventHandler::ProcessMessage(0x%p,0x%x,0x%p,0x%p,0x%p->0x%p) returned: 0x%x\n", hWnd, uMsg, wParam, lParam, plResult, *plResult, hRet);
}
}
#endif
return hRet;
}
virtual HRESULT STDMETHODCALLTYPE AddContextMenus(
IN HMENU hmenu,
IN UINT indexMenu,
IN UINT idCmdFirst,
IN UINT idCmdLast,
IN UINT uFlags,
OUT IContextMenu **ppcm)
{
IShellService *pSs;
HRESULT hRet;
if (ContextMenu == NULL)
{
/* Cache the context menu so we don't need to CoCreateInstance all the time... */
hRet = CoCreateInstance(CLSID_IShellBandSiteMenu, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellService, &pSs));
TRACE("CoCreateInstance(CLSID_IShellBandSiteMenu) for IShellService returned: 0x%x\n", hRet);
if (!SUCCEEDED(hRet))
return hRet;
hRet = pSs->SetOwner((IBandSite*)this);
if (!SUCCEEDED(hRet))
{
pSs->Release();
return hRet;
}
hRet = pSs->QueryInterface(IID_PPV_ARG(IContextMenu, &ContextMenu));
pSs->Release();
if (!SUCCEEDED(hRet))
return hRet;
}
if (ppcm != NULL)
{
ContextMenu->AddRef();
*ppcm = ContextMenu;
}
/* Add the menu items */
return ContextMenu->QueryContextMenu(
hmenu,
indexMenu,
idCmdFirst,
idCmdLast,
uFlags);
}
virtual HRESULT STDMETHODCALLTYPE Lock(
IN BOOL bLock)
{
BOOL bPrevLocked = Locked;
BANDSITEINFO bsi;
HRESULT hRet;
ASSERT(BandSite != NULL);
if (bPrevLocked != bLock)
{
Locked = bLock;
bsi.dwMask = BSIM_STYLE;
bsi.dwStyle = (Locked ? BSIS_LOCKED | BSIS_NOGRIPPER : BSIS_AUTOGRIPPER);
hRet = BandSite->SetBandSiteInfo(&bsi);
if (SUCCEEDED(hRet))
{
hRet = Update();
}
return hRet;
}
return S_FALSE;
}
/*******************************************************************/
virtual HRESULT STDMETHODCALLTYPE AddBand(
IN IUnknown *punk)
{
IOleCommandTarget *pOct;
HRESULT hRet;
hRet = punk->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOct));
if (SUCCEEDED(hRet))
{
/* Send the DBID_DELAYINIT command to initialize the band to be added */
/* FIXME: Should be delayed */
pOct->Exec(
&IID_IDeskBand,
DBID_DELAYINIT,
0,
NULL,
NULL);
pOct->Release();
}
return BandSite->AddBand(
punk);
}
virtual HRESULT STDMETHODCALLTYPE EnumBands(
IN UINT uBand,
OUT DWORD *pdwBandID)
{
return BandSite->EnumBands(
uBand,
pdwBandID);
}
virtual HRESULT STDMETHODCALLTYPE QueryBand(
IN DWORD dwBandID,
OUT IDeskBand **ppstb,
OUT DWORD *pdwState,
OUT LPWSTR pszName,
IN int cchName)
{
HRESULT hRet;
IDeskBand *pstb = NULL;
hRet = BandSite->QueryBand(
dwBandID,
&pstb,
pdwState,
pszName,
cchName);
if (SUCCEEDED(hRet))
{
hRet = IsSameObject(pstb, TaskBand);
if (hRet == S_OK)
{
/* Add the BSSF_UNDELETEABLE flag to pdwState because the task bar band shouldn't be deletable */
if (pdwState != NULL)
*pdwState |= BSSF_UNDELETEABLE;
}
else if (!SUCCEEDED(hRet))
{
pstb->Release();
pstb = NULL;
}
if (ppstb != NULL)
*ppstb = pstb;
}
else if (ppstb != NULL)
*ppstb = NULL;
return hRet;
}
virtual HRESULT STDMETHODCALLTYPE SetBandState(
IN DWORD dwBandID,
IN DWORD dwMask,
IN DWORD dwState)
{
return BandSite->SetBandState(dwBandID, dwMask, dwState);
}
virtual HRESULT STDMETHODCALLTYPE RemoveBand(
IN DWORD dwBandID)
{
return BandSite->RemoveBand(dwBandID);
}
virtual HRESULT STDMETHODCALLTYPE GetBandObject(
IN DWORD dwBandID,
IN REFIID riid,
OUT VOID **ppv)
{
return BandSite->GetBandObject(dwBandID, riid, ppv);
}
virtual HRESULT STDMETHODCALLTYPE SetBandSiteInfo(
IN const BANDSITEINFO *pbsinfo)
{
return BandSite->SetBandSiteInfo(pbsinfo);
}
virtual HRESULT STDMETHODCALLTYPE GetBandSiteInfo(
IN OUT BANDSITEINFO *pbsinfo)
{
return BandSite->GetBandSiteInfo(pbsinfo);
}
virtual BOOL HasTaskBand()
{
ASSERT(TaskBand != NULL);
return SUCCEEDED(TaskBand->GetRebarBandID(
NULL));
}
virtual HRESULT AddTaskBand()
{
#if 0
/* FIXME: This is the code for the simple taskbar */
IObjectWithSite *pOws;
HRESULT hRet;
hRet = TaskBand->QueryInterface(
&IID_IObjectWithSite,
(PVOID*) &pOws);
if (SUCCEEDED(hRet))
{
hRet = pOws->SetSite(
(IUnknown *)TaskBand);
pOws->Release();
}
return hRet;
#else
if (!HasTaskBand())
{
return BandSite->AddBand(TaskBand);
}
return S_OK;
#endif
}
virtual HRESULT Update()
{
IOleCommandTarget *pOct;
HRESULT hRet;
hRet = punkInner->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &pOct));
if (SUCCEEDED(hRet))
{
/* Send the DBID_BANDINFOCHANGED command to update the band site */
hRet = pOct->Exec(
&IID_IDeskBand,
DBID_BANDINFOCHANGED,
0,
NULL,
NULL);
pOct->Release();
}
return hRet;
}
virtual VOID BroadcastOleCommandExec(const GUID *pguidCmdGroup,
DWORD nCmdID,
DWORD nCmdExecOpt,
VARIANTARG *pvaIn,
VARIANTARG *pvaOut)
{
IOleCommandTarget *pOct;
DWORD dwBandID;
UINT uBand = 0;
/* Enumerate all bands */
while (SUCCEEDED(BandSite->EnumBands(uBand, &dwBandID)))
{
if (SUCCEEDED(BandSite->GetBandObject(dwBandID, IID_PPV_ARG(IOleCommandTarget, &pOct))))
{
/* Execute the command */
pOct->Exec(
pguidCmdGroup,
nCmdID,
nCmdExecOpt,
pvaIn,
pvaOut);
pOct->Release();
}
uBand++;
}
}
virtual HRESULT FinishInit()
{
/* Broadcast the DBID_FINISHINIT command */
BroadcastOleCommandExec(&IID_IDeskBand, DBID_FINISHINIT, 0, NULL, NULL);
return S_OK;
}
virtual HRESULT Show(
IN BOOL bShow)
{
IDeskBarClient *pDbc;
HRESULT hRet;
hRet = BandSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDbc));
if (SUCCEEDED(hRet))
{
hRet = pDbc->UIActivateDBC(
bShow ? DBC_SHOW : DBC_HIDE);
pDbc->Release();
}
return hRet;
}
virtual HRESULT LoadFromStream(IN OUT IStream *pStm)
{
IPersistStream *pPStm;
HRESULT hRet;
ASSERT(BandSite != NULL);
/* We implement the undocumented COM interface IBandSiteStreamCallback
that the shell will query so that we can intercept and custom-load
the task band when it finds the task band's CLSID (which is internal).
This way we can prevent the shell from attempting to CoCreateInstance
the (internal) task band, resulting in a failure... */
hRet = BandSite->QueryInterface(IID_PPV_ARG(IPersistStream, &pPStm));
if (SUCCEEDED(hRet))
{
hRet = pPStm->Load(
pStm);
TRACE("->Load() returned 0x%x\n", hRet);
pPStm->Release();
}
return hRet;
}
virtual IStream *
GetUserBandsStream(IN DWORD grfMode)
{
HKEY hkStreams;
IStream *Stream = NULL;
if (RegCreateKey(hkExplorer,
TEXT("Streams"),
&hkStreams) == ERROR_SUCCESS)
{
Stream = SHOpenRegStream(hkStreams,
TEXT("Desktop"),
TEXT("TaskbarWinXP"),
grfMode);
RegCloseKey(hkStreams);
}
return Stream;
}
virtual IStream *
GetDefaultBandsStream(IN DWORD grfMode)
{
HKEY hkStreams;
IStream *Stream = NULL;
if (RegCreateKey(HKEY_LOCAL_MACHINE,
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Streams"),
&hkStreams) == ERROR_SUCCESS)
{
Stream = SHOpenRegStream(hkStreams,
TEXT("Desktop"),
TEXT("Default Taskbar"),
grfMode);
RegCloseKey(hkStreams);
}
return Stream;
}
virtual HRESULT Load()
{
IStream *pStm;
HRESULT hRet;
/* Try to load the user's settings */
pStm = GetUserBandsStream(STGM_READ);
if (pStm != NULL)
{
hRet = LoadFromStream(pStm);
TRACE("Loaded user bands settings: 0x%x\n", hRet);
pStm->Release();
}
else
hRet = E_FAIL;
/* If the user's settings couldn't be loaded, try with
default settings (ie. when the user logs in for the
first time! */
if (!SUCCEEDED(hRet))
{
pStm = GetDefaultBandsStream(STGM_READ);
if (pStm != NULL)
{
hRet = LoadFromStream(pStm);
TRACE("Loaded default user bands settings: 0x%x\n", hRet);
pStm->Release();
}
else
hRet = E_FAIL;
}
return hRet;
}
HRESULT _Init(IN OUT ITrayWindow *tray, OUT HWND *phWndRebar, OUT HWND *phwndTaskSwitch)
{
IDeskBarClient *pDbc;
IDeskBand *pDb;
IOleWindow *pOw;
HRESULT hRet;
*phWndRebar = NULL;
*phwndTaskSwitch = NULL;
Tray = tray;
/* Create a RebarBandSite provided by the shell */
hRet = CoCreateInstance(CLSID_RebarBandSite,
static_cast<IBandSite*>(this),
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IUnknown, &punkInner));
if (!SUCCEEDED(hRet))
{
return hRet;
}
hRet = punkInner->QueryInterface(IID_PPV_ARG(IBandSite, &BandSite));
if (!SUCCEEDED(hRet))
{
return hRet;
}
hRet = punkInner->QueryInterface(IID_PPV_ARG(IWinEventHandler, &WindowEventHandler));
if (!SUCCEEDED(hRet))
{
return hRet;
}
TaskBand = CreateTaskBand(Tray);
if (TaskBand != NULL)
{
/* Add the task band to the site */
hRet = BandSite->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDbc));
if (SUCCEEDED(hRet))
{
hRet = TaskBand->QueryInterface(IID_PPV_ARG(IOleWindow, &pOw));
if (SUCCEEDED(hRet))
{
/* We cause IDeskBarClient to create the rebar control by passing the new
task band to it. The band reports the tray window handle as window handle
so that IDeskBarClient knows the parent window of the Rebar control that
it wants to create. */
hRet = pDbc->SetDeskBarSite(pOw);
if (SUCCEEDED(hRet))
{
/* The Rebar control is now created, we can query the window handle */
hRet = pDbc->GetWindow(&hWndRebar);
if (SUCCEEDED(hRet))
{
/* We need to manually remove the RBS_BANDBORDERS style! */
SetWindowStyle(hWndRebar, RBS_BANDBORDERS, 0);
}
}
pOw->Release();
}
if (SUCCEEDED(hRet))
{
DWORD dwMode = 0;
/* Set the Desk Bar mode to the current one */
/* FIXME: We need to set the mode (and update) whenever the user docks
the tray window to another monitor edge! */
if (!Tray->IsHorizontal())
dwMode = DBIF_VIEWMODE_VERTICAL;
hRet = pDbc->SetModeDBC(dwMode);
}
pDbc->Release();
}
/* Load the saved state of the task band site */
/* FIXME: We should delay loading shell extensions, also see DBID_DELAYINIT */
Load();
/* Add the task bar band if it hasn't been added already */
hRet = AddTaskBand();
if (SUCCEEDED(hRet))
{
hRet = TaskBand->QueryInterface(IID_PPV_ARG(IDeskBand, &pDb));
if (SUCCEEDED(hRet))
{
hRet = pDb->GetWindow(phwndTaskSwitch);
if (!SUCCEEDED(hRet))
*phwndTaskSwitch = NULL;
pDb->Release();
}
}
/* Should we send this after showing it? */
Update();
/* FIXME: When should we send this? Does anyone care anyway? */
FinishInit();
/* Activate the band site */
Show(
TRUE);
}
*phWndRebar = hWndRebar;
return S_OK;
}
};
/*******************************************************************/
ITrayBandSite *
CreateTrayBandSite(IN OUT ITrayWindow *Tray,
OUT HWND *phWndRebar,
OUT HWND *phWndTaskSwitch)
{
HRESULT hr;
CTrayBandSite * tb = new CTrayBandSite();
if (!tb)
return NULL;
tb->AddRef();
hr = tb->_Init(Tray, phWndRebar, phWndTaskSwitch);
if (FAILED_UNEXPECTEDLY(hr))
tb->Release();
return tb;
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -78,7 +78,7 @@ UpdateTaskbarBitmap(PPROPSHEET_INFO pPropInfo)
DeleteObject(pPropInfo->hTaskbarBitmap);
}
pPropInfo->hTaskbarBitmap = LoadImage(hExplorerInstance,
pPropInfo->hTaskbarBitmap = (HBITMAP)LoadImage(hExplorerInstance,
lpImageName,
IMAGE_BITMAP,
0,
@ -367,7 +367,7 @@ DisplayTrayProperties(IN HWND hwndOwner)
PROPSHEET_INFO propInfo;
PROPSHEETHEADER psh;
PROPSHEETPAGE psp[5];
TCHAR szCaption[256];
WCHAR szCaption[256];
if (!LoadString(hExplorerInstance,
IDS_TASKBAR_STARTMENU_PROP_CAPTION,

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,323 @@
#include "precomp.h"
#include <winver.h>
typedef struct _LANGCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
} LANGCODEPAGE, *PLANGCODEPAGE;
HRESULT
IsSameObject(IN IUnknown *punk1, IN IUnknown *punk2)
{
HRESULT hRet;
hRet = punk1->QueryInterface(IID_PPV_ARG(IUnknown, &punk1));
if (!SUCCEEDED(hRet))
return hRet;
hRet = punk2->QueryInterface(IID_PPV_ARG(IUnknown, &punk2));
punk1->Release();
if (!SUCCEEDED(hRet))
return hRet;
punk2->Release();
/* We're dealing with the same object if the IUnknown pointers are equal */
return (punk1 == punk2) ? S_OK : S_FALSE;
}
LONG
SetWindowStyle(IN HWND hWnd,
IN LONG dwStyleMask,
IN LONG dwStyle)
{
LONG PrevStyle, Style;
ASSERT((~dwStyleMask & dwStyle) == 0);
PrevStyle = GetWindowLong(hWnd, GWL_STYLE);
if (PrevStyle != 0 &&
(PrevStyle & dwStyleMask) != dwStyle)
{
Style = PrevStyle & ~dwStyleMask;
Style |= dwStyle;
PrevStyle = SetWindowLong(hWnd, GWL_STYLE, Style);
}
return PrevStyle;
}
LONG
SetWindowExStyle(IN HWND hWnd,
IN LONG dwStyleMask,
IN LONG dwStyle)
{
LONG PrevStyle, Style;
ASSERT((~dwStyleMask & dwStyle) == 0);
PrevStyle = GetWindowLong(hWnd, GWL_EXSTYLE);
if (PrevStyle != 0 &&
(PrevStyle & dwStyleMask) != dwStyle)
{
Style = PrevStyle & ~dwStyleMask;
Style |= dwStyle;
PrevStyle = SetWindowLong(hWnd, GWL_EXSTYLE, Style);
}
return PrevStyle;
}
HMENU
LoadPopupMenu(IN HINSTANCE hInstance,
IN LPCTSTR lpMenuName)
{
HMENU hMenu, hSubMenu = NULL;
hMenu = LoadMenu(hInstance,
lpMenuName);
if (hMenu != NULL)
{
hSubMenu = GetSubMenu(hMenu,
0);
if (hSubMenu != NULL &&
!RemoveMenu(hMenu,
0,
MF_BYPOSITION))
{
hSubMenu = NULL;
}
DestroyMenu(hMenu);
}
return hSubMenu;
}
HMENU
FindSubMenu(IN HMENU hMenu,
IN UINT uItem,
IN BOOL fByPosition)
{
MENUITEMINFO mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
if (GetMenuItemInfo(hMenu,
uItem,
fByPosition,
&mii))
{
return mii.hSubMenu;
}
return NULL;
}
BOOL
GetCurrentLoggedOnUserName(OUT LPTSTR szBuffer,
IN DWORD dwBufferSize)
{
DWORD dwType;
DWORD dwSize;
/* Query the user name from the registry */
dwSize = (dwBufferSize * sizeof(WCHAR)) - 1;
if (RegQueryValueEx(hkExplorer,
TEXT("Logon User Name"),
0,
&dwType,
(LPBYTE) szBuffer,
&dwSize) == ERROR_SUCCESS &&
(dwSize / sizeof(WCHAR)) > 1 &&
szBuffer[0] != _T('\0'))
{
szBuffer[dwSize / sizeof(WCHAR)] = _T('\0');
return TRUE;
}
/* Fall back to GetUserName() */
dwSize = dwBufferSize;
if (!GetUserName(szBuffer,
&dwSize))
{
szBuffer[0] = _T('\0');
return FALSE;
}
return TRUE;
}
BOOL
FormatMenuString(IN HMENU hMenu,
IN UINT uPosition,
IN UINT uFlags,
...)
{
va_list vl;
MENUITEMINFO mii;
WCHAR szBuf[128];
WCHAR szBufFmt[128];
/* Find the menu item and read the formatting string */
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_STRING;
mii.dwTypeData = (LPTSTR) szBufFmt;
mii.cch = sizeof(szBufFmt) / sizeof(szBufFmt[0]);
if (GetMenuItemInfo(hMenu,
uPosition,
uFlags,
&mii))
{
/* Format the string */
va_start(vl, uFlags);
_vsntprintf(szBuf,
(sizeof(szBuf) / sizeof(szBuf[0])) - 1,
szBufFmt,
vl);
va_end(vl);
szBuf[(sizeof(szBuf) / sizeof(szBuf[0])) - 1] = _T('\0');
/* Update the menu item */
mii.dwTypeData = (LPTSTR) szBuf;
if (SetMenuItemInfo(hMenu,
uPosition,
uFlags,
&mii))
{
return TRUE;
}
}
return FALSE;
}
BOOL
GetExplorerRegValueSet(IN HKEY hKey,
IN LPCTSTR lpSubKey,
IN LPCTSTR lpValue)
{
WCHAR szBuffer[MAX_PATH];
HKEY hkSubKey;
DWORD dwType, dwSize;
BOOL Ret = FALSE;
StringCbCopy(szBuffer, sizeof(szBuffer),
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer"));
if (FAILED_UNEXPECTEDLY(StringCbCat(szBuffer, sizeof(szBuffer),
_T("\\"))))
return FALSE;
if (FAILED_UNEXPECTEDLY(StringCbCat(szBuffer, sizeof(szBuffer),
lpSubKey)))
return FALSE;
dwSize = sizeof(szBuffer);
if (RegOpenKeyEx(hKey,
szBuffer,
0,
KEY_QUERY_VALUE,
&hkSubKey) == ERROR_SUCCESS)
{
ZeroMemory(szBuffer,
sizeof(szBuffer));
if (RegQueryValueEx(hkSubKey,
lpValue,
0,
&dwType,
(LPBYTE) szBuffer,
&dwSize) == ERROR_SUCCESS)
{
if (dwType == REG_DWORD && dwSize == sizeof(DWORD))
Ret = *((PDWORD) szBuffer) != 0;
else if (dwSize > 0)
Ret = *((PCHAR) szBuffer) != 0;
}
RegCloseKey(hkSubKey);
}
return Ret;
}
BOOL
GetVersionInfoString(IN WCHAR *szFileName,
IN WCHAR *szVersionInfo,
OUT WCHAR *szBuffer,
IN UINT cbBufLen)
{
LPVOID lpData = NULL;
WCHAR szSubBlock[128];
WCHAR *lpszLocalBuf = NULL;
LANGID UserLangId;
PLANGCODEPAGE lpTranslate = NULL;
DWORD dwLen;
DWORD dwHandle;
UINT cbTranslate;
UINT cbLen;
BOOL bRet = FALSE;
unsigned int i;
dwLen = GetFileVersionInfoSize(szFileName, &dwHandle);
if (dwLen > 0)
{
lpData = HeapAlloc(hProcessHeap, 0, dwLen);
if (lpData != NULL)
{
if (GetFileVersionInfo(szFileName,
0,
dwLen,
lpData) != 0)
{
UserLangId = GetUserDefaultLangID();
VerQueryValue(lpData,
TEXT("\\VarFileInfo\\Translation"),
(LPVOID *) &lpTranslate,
&cbTranslate);
for (i = 0; i < cbTranslate / sizeof(LANGCODEPAGE); i++)
{
/* If the bottom eight bits of the language id's
match, use this version information (since this
means that the version information and the users
default language are the same). */
if ((lpTranslate[i].wLanguage & 0xFF) ==
(UserLangId & 0xFF))
{
wnsprintf(szSubBlock,
sizeof(szSubBlock) / sizeof(szSubBlock[0]),
TEXT("\\StringFileInfo\\%04X%04X\\%s"),
lpTranslate[i].wLanguage,
lpTranslate[i].wCodePage,
szVersionInfo);
if (VerQueryValue(lpData,
szSubBlock,
(LPVOID *) &lpszLocalBuf,
&cbLen) != 0)
{
_tcsncpy(szBuffer, lpszLocalBuf, cbBufLen / sizeof(*szBuffer));
bRet = TRUE;
break;
}
}
}
}
HeapFree(hProcessHeap, 0, lpData);
lpData = NULL;
}
}
return bRet;
}

View File

@ -46,18 +46,18 @@ if(ARCH STREQUAL "i386")
list(APPEND I386_SOURCE i386-stub-win32.c)
endif()
add_executable(explorer
add_executable(explorer_old
${SOURCE}
${I386_SOURCE}
services/startup.c
explorer.rc)
target_link_libraries(explorer comsupp wine uuid)
set_module_type(explorer win32gui UNICODE)
add_importlibs(explorer advapi32 gdi32 user32 ws2_32 msimg32 comctl32 ole32 oleaut32 shell32 shlwapi notifyhook msvcrt kernel32 ntdll)
add_pch(explorer precomp.h SOURCE)
add_dependencies(explorer psdk)
add_cd_file(TARGET explorer DESTINATION reactos FOR all)
target_link_libraries(explorer_old comsupp wine uuid)
set_module_type(explorer_old win32gui UNICODE)
add_importlibs(explorer_old advapi32 gdi32 user32 ws2_32 msimg32 comctl32 ole32 oleaut32 shell32 shlwapi notifyhook msvcrt kernel32 ntdll)
add_pch(explorer_old precomp.h SOURCE)
add_dependencies(explorer_old psdk)
add_cd_file(TARGET explorer_old DESTINATION reactos FOR all)
add_cd_file(FILE ${CMAKE_CURRENT_SOURCE_DIR}/explorer-cfg-template.xml DESTINATION reactos FOR all)
if(NOT MSVC)
@ -65,6 +65,6 @@ if(NOT MSVC)
# GCC bug #59472
if(LTCG)
add_target_link_flags(explorer "-Wno-error")
add_target_link_flags(explorer_old "-Wno-error")
endif()
endif()

View File

@ -0,0 +1,12 @@
PROJECT(SHELL)
list(APPEND SOURCE
filebrowser.c
filebrowser.rc)
add_executable(filebrowser ${SOURCE})
set_module_type(filebrowser win32gui UNICODE)
add_importlibs(filebrowser shell32 browseui msvcrt kernel32)
add_cd_file(TARGET filebrowser DESTINATION reactos FOR all)

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="browseui.sxs"
version="6.0.2900.2180" />
<file name="browseui.dll">
<comClass clsid="{0BE35200-8F91-11CE-9DE3-00AA004BB851}"/>
<comClass clsid="{00BB2765-6A77-11D0-A535-00C04FD7D062}"/>
<comClass clsid="{01E04581-4EEE-11d0-BFE9-00AA005B4383}"/>
<comClass clsid="{A08C11D2-A228-11d0-825B-00AA005B4383}"/>
<comClass clsid="{F61FFEC1-754F-11d0-80CA-00AA005B4383}"/>
<comClass clsid="{ECD4FC4D-521C-11D0-B792-00A0C90312E1}"/>
<comClass clsid="{ECD4FC4E-521C-11D0-B792-00A0C90312E1}"/>
<comClass clsid="{22BF0C20-6DA7-11D0-B373-00A0C9034938}"/>
<comClass clsid="{AF604EFE-8897-11D1-B944-00A0C90312E1}"/>
<comClass clsid="{EF8AD2D1-AE36-11D1-B2D2-006097DF8C11}"/>
<comClass clsid="{5E6AB780-7743-11CF-A12B-00AA004AE837}"/>
<comClass clsid="{AF4F6510-F982-11d0-8595-00AA004CD6D8}"/>
</file>
</assembly>

View File

@ -0,0 +1,50 @@
/*
* 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 <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <shobjidl.h>
#include <shlobj.h>
#include <shlwapi.h>
#include <shlwapi_undoc.h>
#include <stdio.h>
int _tmain(int argc, _TCHAR* argv[])
{
EXPLORER_CMDLINE_PARSE_RESULTS parseResults = { 0 };
if (SHExplorerParseCmdLine(&parseResults))
{
parseResults.dwFlags |= SH_EXPLORER_CMDLINE_FLAG_SEPARATE;
return SHCreateFromDesktop(&parseResults);
}
if (parseResults.strPath)
SHFree(parseResults.strPath);
if (parseResults.pidlPath)
ILFree(parseResults.pidlPath);
if (parseResults.pidlRoot)
ILFree(parseResults.pidlRoot);
return 0;
}

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="ReactOS.FileBrowser"
type="win32"
/>
<description>This is ReactOS File Browser</description>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
type="win32"
name="client"
version="1.0.0.0" />
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="browseui.sxs"
version="6.0.2900.2180" />
</dependentAssembly>
</dependency>
<dependency>
<dependentAssembly>
<assemblyIdentity
type="win32"
name="Microsoft.Windows.Common-Controls"
version="6.0.0.0"
processorArchitecture="X86"
publicKeyToken="6595b64144ccf1df"
language="*"
/>
</dependentAssembly>
</dependency>
</assembly>

View File

@ -0,0 +1,9 @@
#include <windef.h>
#include <winuser.h>
#define REACTOS_STR_FILE_DESCRIPTION "ReactOS File Browser"
#define REACTOS_STR_INTERNAL_NAME "filebrowser"
#define REACTOS_STR_ORIGINAL_FILENAME "filebrowser.exe"
#include <reactos/version.rc>
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US

View File

@ -0,0 +1,568 @@
/*
* 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 [] = L"Progman";
static const WCHAR szProgmanWindowName [] = L"Program Manager";
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 = static_cast<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, static_cast<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)
{
/* FIXME: Implement executing filebrowser.exe and somehow pass the pidl to it */
/* Returning failure here will make windows 7 and 8 to use the default file browser */
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 = reinterpret_cast<CDesktopBrowser*>(GetWindowLongPtrW(hwnd, 0));
if (pThis == NULL)
goto DefMsgHandler;
}
if (pThis != NULL || uMsg == WM_NCCREATE)
{
switch (uMsg)
{
case WM_ERASEBKGND:
return (LRESULT) PaintDesktop(reinterpret_cast<HDC>(wParam));
case WM_GETISHELLBROWSER:
Ret = reinterpret_cast<LRESULT>(static_cast<IShellBrowser *>(pThis));
break;
case WM_SIZE:
if (wParam == SIZE_MINIMIZED)
{
/* Hey, we're the desktop!!! */
ShowWindow(hwnd,
SW_RESTORE);
}
else
{
/* FIXME: Update work area */
#if 0
RECT rcDesktop;
rcDesktop.left = GetSystemMetrics(SM_XVIRTUALSCREEN);
rcDesktop.top = GetSystemMetrics(SM_YVIRTUALSCREEN);
rcDesktop.right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
rcDesktop.bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
#endif
}
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 = reinterpret_cast<LPCREATESTRUCT>(lParam);
pThis = SHDESK_Create(hwnd, CreateStruct);
if (pThis == NULL)
{
WARN("Failed to create desktop structure\n");
break;
}
SetWindowLongPtrW(hwnd,
0,
reinterpret_cast<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(WS_EX_TOOLWINDOW, szProgmanClassName, szProgmanWindowName,
WS_POPUP | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
rcDesk.left, rcDesk.top, rcDesk.right, rcDesk.bottom,
NULL, NULL, shell32_hInstance, reinterpret_cast<LPVOID>(ShellDesk));
if (hWndDesk != NULL)
return (HANDLE) GetWindowLongPtrW(hWndDesk, 0);
return NULL;
}
/*************************************************************************
* SHCreateDesktop [SHELL32.201]
*
*/
BOOL WINAPI SHDesktopMessageLoop(HANDLE hDesktop)
{
CDesktopBrowser *Desk = reinterpret_cast<CDesktopBrowser *>(hDesktop);
if (Desk == NULL || Desk->Tag != SHDESK_TAG)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return Desk->MessageLoop();
}

View File

@ -0,0 +1,61 @@
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
CMenuBand.cpp
CMenuDeskBar.cpp
CMenuFocusManager.cpp
CMenuSite.cpp
CMenuToolbars.cpp
CMergedFolder.cpp
CStartMenu.cpp
misc.cpp
ShellDDE.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
uxtheme
shlwapi
shell32
comctl32
gdi32
ole32
user32
msvcrt
kernel32
ntdll)
add_cd_file(TARGET rshell DESTINATION reactos FOR all)
add_custom_command(TARGET rshell POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:rshell>"
"$<TARGET_FILE_DIR:explorer>/$<TARGET_FILE_NAME:rshell>"
COMMENT "Copying to output directory")
add_custom_command(TARGET rshell POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:rshell>"
"$<TARGET_FILE_DIR:filebrowser>/$<TARGET_FILE_NAME:rshell>"
COMMENT "Copying to output directory")
add_custom_command(TARGET rshell POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:rshell>"
"$<TARGET_FILE_DIR:filebrowser>/$<TARGET_FILE_NAME:rshell>"
COMMENT "Copying to output directory")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,211 @@
/*
* Shell Menu Band
*
* Copyright 2014 David Quintana
*
* 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
*/
#pragma once
class CMenuToolbarBase;
class CMenuStaticToolbar;
class CMenuSFToolbar;
class CMenuFocusManager;
class CMenuBand :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IDeskBand,
public IObjectWithSite,
public IInputObject,
public IPersistStream,
public IOleCommandTarget,
public IServiceProvider,
public IMenuPopup,
public IMenuBand,
public IShellMenu2,
public IWinEventHandler,
public IShellMenuAcc
{
private:
CMenuFocusManager * m_focusManager;
CMenuStaticToolbar * m_staticToolbar;
CMenuSFToolbar * m_SFToolbar;
CComPtr<IOleWindow> m_site;
CComPtr<IShellMenuCallback> m_psmc;
CComPtr<IMenuPopup> m_subMenuChild;
CComPtr<IMenuPopup> m_subMenuParent;
CComPtr<CMenuBand> m_childBand;
CComPtr<CMenuBand> m_parentBand;
UINT m_uId;
UINT m_uIdAncestor;
DWORD m_dwFlags;
PVOID m_UserData;
HMENU m_hmenu;
HWND m_menuOwner;
BOOL m_useBigIcons;
HWND m_topLevelWindow;
CMenuToolbarBase * m_hotBar;
INT m_hotItem;
CMenuToolbarBase * m_popupBar;
INT m_popupItem;
BOOL m_Show;
BOOL m_shellBottom;
HMENU m_trackedPopup;
HWND m_trackedHwnd;
public:
CMenuBand();
virtual ~CMenuBand();
DECLARE_NOT_AGGREGATABLE(CMenuBand)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMenuBand)
COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IMenuPopup)
COM_INTERFACE_ENTRY_IID(IID_IShellMenu, IShellMenu)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IDeskBand)
COM_INTERFACE_ENTRY_IID(IID_IDockingWindow, IDockingWindow)
COM_INTERFACE_ENTRY_IID(IID_IDeskBand, IDeskBand)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersistStream)
COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
COM_INTERFACE_ENTRY_IID(IID_IMenuBand, IMenuBand)
COM_INTERFACE_ENTRY_IID(IID_IShellMenu2, IShellMenu2)
COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
COM_INTERFACE_ENTRY_IID(IID_IShellMenuAcc, IShellMenuAcc)
END_COM_MAP()
// *** IDeskBand methods ***
virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO *pdbi);
// *** IDockingWindow methods ***
virtual HRESULT STDMETHODCALLTYPE ShowDW(BOOL fShow);
virtual HRESULT STDMETHODCALLTYPE CloseDW(DWORD dwReserved);
virtual HRESULT STDMETHODCALLTYPE ResizeBorderDW(LPCRECT prcBorder, IUnknown *punkToolbarSite, BOOL fReserved);
// *** IOleWindow methods ***
virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
// *** IObjectWithSite methods ***
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, PVOID *ppvSite);
// *** IInputObject methods ***
virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
// *** IPersistStream methods ***
virtual HRESULT STDMETHODCALLTYPE IsDirty();
virtual HRESULT STDMETHODCALLTYPE Load(IStream *pStm);
virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
// *** IPersist methods ***
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *pClassID);
// *** IOleCommandTarget methods ***
virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText);
virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
// *** IServiceProvider methods ***
virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
// *** IMenuPopup methods ***
virtual HRESULT STDMETHODCALLTYPE Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags);
virtual HRESULT STDMETHODCALLTYPE OnSelect(DWORD dwSelectType);
virtual HRESULT STDMETHODCALLTYPE SetSubMenu(IMenuPopup *pmp, BOOL fSet);
// *** IDeskBar methods ***
virtual HRESULT STDMETHODCALLTYPE SetClient(IUnknown *punkClient);
virtual HRESULT STDMETHODCALLTYPE GetClient(IUnknown **ppunkClient);
virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(RECT *prc);
// *** IMenuBand methods ***
virtual HRESULT STDMETHODCALLTYPE IsMenuMessage(MSG *pmsg);
virtual HRESULT STDMETHODCALLTYPE TranslateMenuMessage(MSG *pmsg, LRESULT *plRet);
// *** IShellMenu methods ***
virtual HRESULT STDMETHODCALLTYPE Initialize(IShellMenuCallback *psmc, UINT uId, UINT uIdAncestor, DWORD dwFlags);
virtual HRESULT STDMETHODCALLTYPE GetMenuInfo(IShellMenuCallback **ppsmc, UINT *puId, UINT *puIdAncestor, DWORD *pdwFlags);
virtual HRESULT STDMETHODCALLTYPE SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags);
virtual HRESULT STDMETHODCALLTYPE GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv);
virtual HRESULT STDMETHODCALLTYPE SetMenu(HMENU hmenu, HWND hwnd, DWORD dwFlags);
virtual HRESULT STDMETHODCALLTYPE GetMenu(HMENU *phmenu, HWND *phwnd, DWORD *pdwFlags);
virtual HRESULT STDMETHODCALLTYPE InvalidateItem(LPSMDATA psmd, DWORD dwFlags);
virtual HRESULT STDMETHODCALLTYPE GetState(LPSMDATA psmd);
virtual HRESULT STDMETHODCALLTYPE SetMenuToolbar(IUnknown *punk, DWORD dwFlags);
// *** IWinEventHandler methods ***
virtual HRESULT STDMETHODCALLTYPE OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult);
virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd);
// *** IShellMenu2 methods ***
virtual HRESULT STDMETHODCALLTYPE GetSubMenu(THIS);
virtual HRESULT STDMETHODCALLTYPE SetToolbar(THIS);
virtual HRESULT STDMETHODCALLTYPE SetMinWidth(THIS);
virtual HRESULT STDMETHODCALLTYPE SetNoBorder(THIS);
virtual HRESULT STDMETHODCALLTYPE SetTheme(THIS);
// *** IShellMenuAcc methods ***
virtual HRESULT STDMETHODCALLTYPE GetTop(THIS);
virtual HRESULT STDMETHODCALLTYPE GetBottom(THIS);
virtual HRESULT STDMETHODCALLTYPE GetTracked(THIS);
virtual HRESULT STDMETHODCALLTYPE GetParentSite(THIS);
virtual HRESULT STDMETHODCALLTYPE GetState(THIS);
virtual HRESULT STDMETHODCALLTYPE DoDefaultAction(THIS);
virtual HRESULT STDMETHODCALLTYPE IsEmpty(THIS);
HRESULT _CallCBWithItemId(UINT Id, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT _CallCBWithItemPidl(LPITEMIDLIST pidl, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT _TrackSubMenu(HMENU popup, INT x, INT y, RECT& rcExclude);
HRESULT _TrackContextMenu(IContextMenu * popup, INT x, INT y);
HRESULT _GetTopLevelWindow(HWND*topLevel);
HRESULT _ChangeHotItem(CMenuToolbarBase * tb, INT id, DWORD dwFlags);
HRESULT _ChangePopupItem(CMenuToolbarBase * tb, INT id);
HRESULT _MenuItemHotTrack(DWORD changeType);
HRESULT _CancelCurrentPopup();
HRESULT _OnPopupSubMenu(IShellMenu * childShellMenu, POINTL * pAt, RECTL * pExclude, BOOL mouseInitiated);
HRESULT _BeforeCancelPopup();
HRESULT _DisableMouseTrack(BOOL bDisable);
HRESULT _SetChildBand(CMenuBand * child);
HRESULT _SetParentBand(CMenuBand * parent);
HRESULT _IsPopup();
HRESULT _IsTracking();
HRESULT _KillPopupTimers();
HRESULT _MenuBarMouseDown(HWND hwnd, INT item);
HRESULT _MenuBarMouseUp(HWND hwnd, INT item);
HRESULT _HasSubMenu();
BOOL UseBigIcons()
{
return m_useBigIcons;
}
private:
HRESULT _KeyboardItemChange(DWORD change);
HRESULT _CallCB(UINT uMsg, WPARAM wParam, LPARAM lParam, UINT id = 0, LPITEMIDLIST pidl = NULL);
};

View File

@ -0,0 +1,716 @@
/*
* Shell Menu Desk Bar
*
* Copyright 2014 David Quintana
*
* 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"
#include <atlwin.h>
#include <shlwapi_undoc.h>
#include "CMenuDeskBar.h"
WINE_DEFAULT_DEBUG_CHANNEL(CMenuDeskBar);
const static GUID CGID_MenuDeskBar = { 0x5C9F0A12, 0x959E, 0x11D0, { 0xA3, 0xA4, 0x00, 0xA0, 0xC9, 0x08, 0x26, 0x36 } };
extern "C"
HRESULT WINAPI CMenuDeskBar_Constructor(REFIID riid, LPVOID *ppv)
{
return ShellObjectCreator<CMenuDeskBar>(riid, ppv);
}
CMenuDeskBar::CMenuDeskBar() :
m_Client(NULL),
m_ClientWindow(NULL),
m_IconSize(0),
m_Banner(NULL),
m_Shown(FALSE),
m_ShowFlags(0),
m_didAddRef(FALSE)
{
}
CMenuDeskBar::~CMenuDeskBar()
{
}
LRESULT CMenuDeskBar::_OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
if (!m_didAddRef)
{
this->AddRef();
m_didAddRef = TRUE;
}
bHandled = FALSE;
return 0;
}
void CMenuDeskBar::OnFinalMessage(HWND /* hWnd */)
{
if (m_didAddRef)
{
this->Release();
m_didAddRef = FALSE;
}
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::Initialize(THIS)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetWindow(HWND *lphwnd)
{
if (lphwnd == NULL)
return E_POINTER;
*lphwnd = m_hWnd;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
{
CComPtr<IInputObjectSite> ios;
HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IInputObjectSite, &ios));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return ios->OnFocusChangeIS(punkObj, fSetFocus);
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds,
OLECMD prgCmds [], OLECMDTEXT *pCmdText)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::Exec(const GUID *pguidCmdGroup, DWORD nCmdID,
DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
if (IsEqualIID(*pguidCmdGroup, CGID_MenuDeskBar))
{
switch (nCmdID)
{
case 2: // refresh
return S_OK;
case 3: // load complete
return S_OK;
case 4: // set font metrics
return S_OK;
}
}
if (IsEqualIID(*pguidCmdGroup, CGID_Explorer))
{
}
else if (IsEqualIID(*pguidCmdGroup, IID_IDeskBarClient))
{
switch (nCmdID)
{
case 0:
// hide current band
break;
case 2:
break;
case 3:
break;
}
}
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
{
HRESULT hr;
if (IsEqualGUID(guidService, SID_SMenuPopup) ||
IsEqualGUID(guidService, SID_SMenuBandParent) ||
IsEqualGUID(guidService, SID_STopLevelBrowser))
{
hr = this->QueryInterface(riid, ppvObject);
if (SUCCEEDED(hr))
return hr;
}
if (IsEqualGUID(guidService, SID_SMenuBandBottom) ||
IsEqualGUID(guidService, SID_SMenuBandBottomSelected) ||
IsEqualGUID(guidService, SID_SMenuBandChild))
{
if (m_Client == NULL)
return E_NOINTERFACE;
hr = IUnknown_QueryService(m_Client, guidService, riid, ppvObject);
if (SUCCEEDED(hr))
return hr;
}
if (m_Site == NULL)
return E_NOINTERFACE;
return IUnknown_QueryService(m_Site, guidService, riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
{
return IUnknown_UIActivateIO(m_Client, fActivate, lpMsg);
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::HasFocusIO()
{
CComPtr<IInputObject> io;
HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IInputObject, &io));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return io->HasFocusIO();
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::TranslateAcceleratorIO(LPMSG lpMsg)
{
CComPtr<IInputObject> io;
HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IInputObject, &io));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return io->TranslateAcceleratorIO(lpMsg);
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetClient(IUnknown *punkClient)
{
CComPtr<IDeskBarClient> pDeskBandClient;
HRESULT hr;
if (m_Client)
{
hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDeskBandClient));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
pDeskBandClient->SetDeskBarSite(NULL);
pDeskBandClient = NULL;
m_Client = NULL;
}
if (punkClient == NULL)
return S_OK;
if (m_hWnd == NULL)
{
Create(NULL);
}
hr = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &m_Client));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &pDeskBandClient));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pDeskBandClient->SetDeskBarSite(static_cast<IDeskBar*>(this));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return IUnknown_GetWindow(m_Client, &m_ClientWindow);
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetClient(IUnknown **ppunkClient)
{
if (ppunkClient == NULL)
return E_POINTER;
if (!m_Client)
return E_FAIL;
return m_Client->QueryInterface(IID_PPV_ARG(IUnknown, ppunkClient));
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnPosRectChangeDB(LPRECT prc)
{
if (prc == NULL)
return E_POINTER;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSite(IUnknown *pUnkSite)
{
// Windows closes the bar if this is called when the bar is shown
if (m_Shown)
_CloseBar();
m_SubMenuParent = NULL;
m_Site = pUnkSite;
if (m_Site)
{
IUnknown_QueryService(m_Site, SID_SMenuPopup, IID_PPV_ARG(IMenuPopup, &m_SubMenuParent));
}
else
{
SetClient(NULL);
DestroyWindow();
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetSite(REFIID riid, void **ppvSite)
{
if (m_Site == NULL)
return E_FAIL;
return m_Site->QueryInterface(riid, ppvSite);
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags)
{
HRESULT hr;
CComPtr<IOleCommandTarget> oct;
CComPtr<IInputObject> io;
CComPtr<IDeskBand> band;
CComPtr<IDeskBarClient> dbc;
if (m_hWnd == NULL)
return E_FAIL;
hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IOleCommandTarget, &oct));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
// Windows calls this, but it appears to be unimplemented?
hr = dbc->SetModeDBC(1);
// Allow it to fail with E_NOTIMPL.
// No clue about the arg, using anything != 0
hr = dbc->UIActivateDBC(TRUE);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
RECT rc = { 0 };
hr = dbc->GetSize(0, &rc);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
// Unknown meaning
const int CMD = 19;
const int CMD_EXEC_OPT = 0;
hr = IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD, CMD_EXEC_OPT, NULL, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
::AdjustWindowRect(&rc, ::GetWindowLong(m_hWnd, GWL_STYLE), FALSE);
::OffsetRect(&rc, -rc.left, -rc.top);
if (m_Banner != NULL)
{
BITMAP bm;
::GetObject(m_Banner, sizeof(bm), &bm);
rc.right += bm.bmWidth;
}
RECT rcWorkArea;
GetWindowRect(GetDesktopWindow(), &rcWorkArea);
int waHeight = rcWorkArea.bottom - rcWorkArea.top;
int x = ppt->x;
int y = ppt->y;
int cx = rc.right - rc.left;
int cy = rc.bottom - rc.top;
switch (dwFlags & 0xFF000000)
{
case MPPF_BOTTOM:
x = ppt->x;
y = ppt->y - rc.bottom;
break;
case MPPF_RIGHT:
x = ppt->x + rc.left;
y = ppt->y + rc.top;
break;
case MPPF_TOP | MPPF_ALIGN_LEFT:
x = ppt->x - rc.right;
y = ppt->y + rc.top;
break;
case MPPF_TOP | MPPF_ALIGN_RIGHT:
x = ppt->x;
y = ppt->y + rc.top;
break;
}
if (x + cx > rcWorkArea.right)
{
// FIXME: Works, but it's oversimplified.
x = prcExclude->left - cx;
dwFlags = (dwFlags & (~MPPF_TOP)) | MPPF_LEFT;
}
if (y < rcWorkArea.top)
{
y = rcWorkArea.top;
}
if (cy > waHeight)
{
cy = waHeight;
}
if (y + cy > rcWorkArea.bottom)
{
y = rcWorkArea.bottom - cy;
}
this->SetWindowPos(HWND_TOPMOST, x, y, cx, cy, SWP_SHOWWINDOW);
m_ShowFlags = dwFlags;
m_Shown = true;
// HACK: The bar needs to be notified of the size AFTER it is shown.
// Quick & dirty way of getting it done.
BOOL bHandled;
_OnSize(WM_SIZE, 0, 0, bHandled);
UIActivateIO(TRUE, NULL);
if (dwFlags & (MPPF_INITIALSELECT | MPPF_FINALSELECT))
{
const int CMD_SELECT = 5;
int CMD_SELECT_OPTS = dwFlags & MPPF_INITIALSELECT ? 0 : -2;
IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD_SELECT, CMD_SELECT_OPTS, NULL, NULL);
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetIconSize(THIS_ DWORD iIcon)
{
HRESULT hr;
m_IconSize = iIcon;
// Unknown meaning (set flags? set icon size?)
const int CMD = 16;
const int CMD_EXEC_OPT = iIcon ? 0 : 2; // seems to work
hr = IUnknown_QueryServiceExec(m_Client, SID_SMenuBandChild, &CLSID_MenuBand, CMD, CMD_EXEC_OPT, NULL, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
BOOL bHandled;
_OnSize(WM_SIZE, 0, 0, bHandled);
return hr;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetIconSize(THIS_ DWORD* piIcon)
{
if (piIcon)
*piIcon = m_IconSize;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetBitmap(THIS_ HBITMAP hBitmap)
{
m_Banner = hBitmap;
BOOL bHandled;
_OnSize(WM_SIZE, 0, 0, bHandled);
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::GetBitmap(THIS_ HBITMAP* phBitmap)
{
if (phBitmap)
*phBitmap = m_Banner;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::SetSubMenu(IMenuPopup *pmp, BOOL fSet)
{
// Called by the MenuBand to assign itself as the logical child of the DeskBar
if (fSet)
{
m_SubMenuChild = pmp;
}
else
{
if (m_SubMenuChild)
{
if (pmp == m_SubMenuChild)
{
m_SubMenuChild = NULL;
}
}
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuDeskBar::OnSelect(DWORD dwSelectType)
{
CComPtr<IDeskBar> safeThis = this;
/* As far as I can tell, the submenu hierarchy looks like this:
*
* The DeskBar's Child is the Band it contains.
* The DeskBar's Parent is the SID_SMenuPopup of the Site.
*
* The Band's Child is the IMenuPopup of the child submenu.
* The Band's Parent is the SID_SMenuPopup of the Site (the DeskBar).
*
* When the DeskBar receives a selection event:
* If it requires closing the window, it will notify the Child (Band) using CancelLevel.
* If it has to spread upwards (everything but CancelLevel), it will notify the Parent.
*
* When the Band receives a selection event, this is where it gets fuzzy:
* In which cases does it call the Parent? Probably not CancelLevel.
* In which cases does it call the Child?
* How does it react to calls?
*
*/
CComPtr<IMenuPopup> oldParent = m_SubMenuParent;
TRACE("OnSelect dwSelectType=%d\n", this, dwSelectType);
switch (dwSelectType)
{
case MPOS_EXECUTE:
case MPOS_FULLCANCEL:
case MPOS_CANCELLEVEL:
_CloseBar();
if (dwSelectType == MPOS_CANCELLEVEL)
return S_OK;
case MPOS_SELECTLEFT:
case MPOS_SELECTRIGHT:
case MPOS_CHILDTRACKING:
if (oldParent)
return oldParent->OnSelect(dwSelectType);
break;
}
return S_OK;
}
HRESULT CMenuDeskBar::_CloseBar()
{
CComPtr<IDeskBar> safeThis = this;
CComPtr<IDeskBarClient> dbc;
HRESULT hr;
m_Shown = false;
if (m_SubMenuParent)
{
m_SubMenuParent->SetSubMenu(this, FALSE);
}
if (m_SubMenuChild)
{
hr = m_SubMenuChild->OnSelect(MPOS_CANCELLEVEL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
hr = m_Client->QueryInterface(IID_PPV_ARG(IDeskBarClient, &dbc));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = dbc->UIActivateDBC(FALSE);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
SetWindowPos(NULL, 0, 0, 0, 0, SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE);
return UIActivateIO(FALSE, NULL);
}
BOOL CMenuDeskBar::_IsSubMenuParent(HWND hwnd)
{
CComPtr<IMenuPopup> popup = m_SubMenuParent;
while (popup)
{
HRESULT hr;
CComPtr<IOleWindow> window;
hr = popup->QueryInterface(IID_PPV_ARG(IOleWindow, &window));
if (FAILED_UNEXPECTEDLY(hr))
return FALSE;
HWND parent;
hr = window->GetWindow(&parent);
if (SUCCEEDED(hr) && hwnd == parent)
return TRUE;
popup = NULL;
hr = IUnknown_GetSite(window, IID_PPV_ARG(IMenuPopup, &popup));
if (FAILED(hr))
return FALSE;
}
return FALSE;
}
LRESULT CMenuDeskBar::_OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
if (m_Client)
{
RECT rc;
GetClientRect(&rc);
if (m_Banner != NULL)
{
BITMAP bm;
::GetObject(m_Banner, sizeof(bm), &bm);
rc.left += bm.bmWidth;
}
::SetWindowPos(m_ClientWindow, NULL, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, 0);
}
return 0;
}
LRESULT CMenuDeskBar::_OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
if (!m_Client)
return 0;
CComPtr<IWinEventHandler> winEventHandler;
HRESULT hr = m_Client->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
if (FAILED_UNEXPECTEDLY(hr))
return 0;
if (winEventHandler)
{
LRESULT result;
hr = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
if (FAILED_UNEXPECTEDLY(hr))
return 0;
return result;
}
return 0;
}
LRESULT CMenuDeskBar::_OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
bHandled = FALSE;
if (m_Banner && !m_IconSize)
{
BITMAP bm;
PAINTSTRUCT ps;
HDC hdc = BeginPaint(&ps);
HDC hdcMem = ::CreateCompatibleDC(hdc);
HGDIOBJ hbmOld = ::SelectObject(hdcMem, m_Banner);
::GetObject(m_Banner, sizeof(bm), &bm);
RECT rc;
if (!GetClientRect(&rc))
WARN("GetClientRect failed\n");
const int bx = bm.bmWidth;
const int by = bm.bmHeight;
const int cy = rc.bottom;
TRACE("Painting banner: %d by %d\n", bm.bmWidth, bm.bmHeight);
if (!::StretchBlt(hdc, 0, 0, bx, cy - by, hdcMem, 0, 0, bx, 1, SRCCOPY))
WARN("StretchBlt failed\n");
if (!::BitBlt(hdc, 0, cy - by, bx, by, hdcMem, 0, 0, SRCCOPY))
WARN("BitBlt failed\n");
::SelectObject(hdcMem, hbmOld);
::DeleteDC(hdcMem);
EndPaint(&ps);
}
return TRUE;
}
LRESULT CMenuDeskBar::_OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
// BUG in ReactOS: WM_ACTIVATE/WA_INACTIVE makes no sense with lParam==hWnd
if (LOWORD(wParam) != 0 || reinterpret_cast<HWND>(lParam) == m_hWnd)
{
return 0;
}
// HACK! I just want it to work !!!
CComPtr<IDeskBar> db;
HRESULT hr = IUnknown_QueryService(m_Client, SID_SMenuBandChild, IID_PPV_ARG(IDeskBar, &db));
if (FAILED_UNEXPECTEDLY(hr))
return 0;
CComPtr<IUnknown> punk;
hr = db->GetClient(&punk);
if (FAILED_UNEXPECTEDLY(hr))
return 0;
if (!punk && m_Shown)
{
if (!_IsSubMenuParent(reinterpret_cast<HWND>(lParam)))
{
OnSelect(MPOS_FULLCANCEL);
}
}
return 0;
}
LRESULT CMenuDeskBar::_OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
return MA_NOACTIVATE;
}
LRESULT CMenuDeskBar::_OnAppActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
#if 0
if (wParam == 0 && m_Shown)
{
OnSelect(MPOS_FULLCANCEL);
}
#endif
return 0;
}

View File

@ -0,0 +1,142 @@
/*
* Shell Menu Desk Bar
*
* Copyright 2014 David Quintana
*
* 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
*/
#pragma once
typedef CWinTraits<
WS_POPUP | WS_DLGFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_PALETTEWINDOW
> CMenuWinTraits;
class CMenuDeskBar :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl<CMenuDeskBar, CWindow, CMenuWinTraits>,
public IOleCommandTarget,
public IServiceProvider,
public IInputObjectSite,
public IInputObject,
public IMenuPopup,
public IObjectWithSite,
public IBanneredBar,
public IInitializeObject
{
private:
CComPtr<IUnknown> m_Site;
CComPtr<IUnknown> m_Client;
CComPtr<IMenuPopup> m_SubMenuParent;
CComPtr<IMenuPopup> m_SubMenuChild;
HWND m_ClientWindow;
DWORD m_IconSize;
HBITMAP m_Banner;
BOOL m_Shown;
DWORD m_ShowFlags;
BOOL m_didAddRef;
virtual void OnFinalMessage(HWND hWnd);
public:
CMenuDeskBar();
virtual ~CMenuDeskBar();
DECLARE_NOT_AGGREGATABLE(CMenuDeskBar)
DECLARE_PROTECT_FINAL_CONSTRUCT()
DECLARE_WND_CLASS_EX(_T("BaseBar"), CS_SAVEBITS | CS_DROPSHADOW, COLOR_3DFACE)
BEGIN_MSG_MAP(CMenuDeskBar)
MESSAGE_HANDLER(WM_CREATE, _OnCreate)
MESSAGE_HANDLER(WM_SIZE, _OnSize)
MESSAGE_HANDLER(WM_NOTIFY, _OnNotify)
MESSAGE_HANDLER(WM_PAINT, _OnPaint)
MESSAGE_HANDLER(WM_ACTIVATE, _OnActivate)
MESSAGE_HANDLER(WM_ACTIVATEAPP, _OnAppActivate)
MESSAGE_HANDLER(WM_MOUSEACTIVATE, _OnMouseActivate)
END_MSG_MAP()
BEGIN_COM_MAP(CMenuDeskBar)
COM_INTERFACE_ENTRY_IID(IID_IMenuPopup, IMenuPopup)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
COM_INTERFACE_ENTRY_IID(IID_IDeskBar, IMenuPopup)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IMenuPopup)
COM_INTERFACE_ENTRY_IID(IID_IObjectWithSite, IObjectWithSite)
COM_INTERFACE_ENTRY_IID(IID_IBanneredBar, IBanneredBar)
COM_INTERFACE_ENTRY_IID(IID_IInitializeObject, IInitializeObject)
END_COM_MAP()
// *** IMenuPopup methods ***
virtual HRESULT STDMETHODCALLTYPE Popup(POINTL *ppt, RECTL *prcExclude, MP_POPUPFLAGS dwFlags);
virtual HRESULT STDMETHODCALLTYPE OnSelect(DWORD dwSelectType);
virtual HRESULT STDMETHODCALLTYPE SetSubMenu(IMenuPopup *pmp, BOOL fSet);
// *** IOleWindow methods ***
virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
// *** IObjectWithSite methods ***
virtual HRESULT STDMETHODCALLTYPE SetSite(IUnknown *pUnkSite);
virtual HRESULT STDMETHODCALLTYPE GetSite(REFIID riid, PVOID *ppvSite);
// *** IBanneredBar methods ***
virtual HRESULT STDMETHODCALLTYPE SetIconSize(DWORD iIcon);
virtual HRESULT STDMETHODCALLTYPE GetIconSize(DWORD* piIcon);
virtual HRESULT STDMETHODCALLTYPE SetBitmap(HBITMAP hBitmap);
virtual HRESULT STDMETHODCALLTYPE GetBitmap(HBITMAP* phBitmap);
// *** IInitializeObject methods ***
virtual HRESULT STDMETHODCALLTYPE Initialize(THIS);
// *** IOleCommandTarget methods ***
virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText);
virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
// *** IServiceProvider methods ***
virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
// *** IInputObjectSite methods ***
virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(LPUNKNOWN lpUnknown, BOOL bFocus);
// *** IInputObject methods ***
virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL bActivating, LPMSG lpMsg);
virtual HRESULT STDMETHODCALLTYPE HasFocusIO(THIS);
virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
// *** IDeskBar methods ***
virtual HRESULT STDMETHODCALLTYPE SetClient(IUnknown *punkClient);
virtual HRESULT STDMETHODCALLTYPE GetClient(IUnknown **ppunkClient);
virtual HRESULT STDMETHODCALLTYPE OnPosRectChangeDB(LPRECT prc);
private:
// message handlers
LRESULT _OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnMouseActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT _OnAppActivate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
BOOL _IsSubMenuParent(HWND hwnd);
HRESULT _CloseBar();
};

View File

@ -0,0 +1,948 @@
/*
* Shell Menu Band
*
* Copyright 2014 David Quintana
*
* 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"
#include <windowsx.h>
#include <commoncontrols.h>
#include <shlwapi_undoc.h>
#include "CMenuFocusManager.h"
#include "CMenuToolbars.h"
#include "CMenuBand.h"
#if DBG
# undef _ASSERT
# define _ASSERT(x) DbgAssert(!!(x), __FILE__, __LINE__, #x)
bool DbgAssert(bool x, const char * filename, int line, const char * expr)
{
if (!x)
{
char szMsg[512];
const char *fname;
fname = strrchr(filename, '\\');
if (fname == NULL)
{
fname = strrchr(filename, '/');
}
if (fname == NULL)
fname = filename;
else
fname++;
sprintf(szMsg, "%s:%d: Assertion failed: %s\n", fname, line, expr);
OutputDebugStringA(szMsg);
__debugbreak();
}
return x;
}
#else
# undef _ASSERT
# define _ASSERT(x) (!!(x))
#endif
WINE_DEFAULT_DEBUG_CHANNEL(CMenuFocus);
DWORD CMenuFocusManager::TlsIndex = 0;
CMenuFocusManager * CMenuFocusManager::GetManager()
{
return reinterpret_cast<CMenuFocusManager *>(TlsGetValue(TlsIndex));
}
CMenuFocusManager * CMenuFocusManager::AcquireManager()
{
CMenuFocusManager * obj = NULL;
if (!TlsIndex)
{
if ((TlsIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
return NULL;
}
obj = GetManager();
if (!obj)
{
obj = new CComObject<CMenuFocusManager>();
TlsSetValue(TlsIndex, obj);
}
obj->AddRef();
return obj;
}
void CMenuFocusManager::ReleaseManager(CMenuFocusManager * obj)
{
if (!obj->Release())
{
TlsSetValue(TlsIndex, NULL);
}
}
LRESULT CALLBACK CMenuFocusManager::s_MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam)
{
return GetManager()->MsgFilterHook(nCode, wParam, lParam);
}
LRESULT CALLBACK CMenuFocusManager::s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam)
{
return GetManager()->GetMsgHook(nCode, wParam, lParam);
}
HRESULT CMenuFocusManager::PushToArray(StackEntryType type, CMenuBand * mb, HMENU hmenu)
{
if (m_bandCount >= MAX_RECURSE)
return E_OUTOFMEMORY;
m_bandStack[m_bandCount].type = type;
m_bandStack[m_bandCount].mb = mb;
m_bandStack[m_bandCount].hmenu = hmenu;
m_bandCount++;
return S_OK;
}
HRESULT CMenuFocusManager::PopFromArray(StackEntryType * pType, CMenuBand ** pMb, HMENU * pHmenu)
{
if (pType) *pType = NoEntry;
if (pMb) *pMb = NULL;
if (pHmenu) *pHmenu = NULL;
if (m_bandCount <= 0)
return S_FALSE;
m_bandCount--;
if (pType) *pType = m_bandStack[m_bandCount].type;
if (*pType == TrackedMenuEntry)
{
if (pHmenu) *pHmenu = m_bandStack[m_bandCount].hmenu;
}
else
{
if (pMb) *pMb = m_bandStack[m_bandCount].mb;
}
return S_OK;
}
CMenuFocusManager::CMenuFocusManager() :
m_current(NULL),
m_parent(NULL),
m_hMsgFilterHook(NULL),
m_hGetMsgHook(NULL),
m_mouseTrackDisabled(FALSE),
m_captureHwnd(0),
m_hwndUnderMouse(NULL),
m_entryUnderMouse(NULL),
m_selectedMenu(NULL),
m_selectedItem(0),
m_selectedItemFlags(0),
m_isLButtonDown(FALSE),
m_movedSinceDown(FALSE),
m_windowAtDown(NULL),
m_bandCount(0)
{
m_ptPrev.x = 0;
m_ptPrev.y = 0;
m_threadId = GetCurrentThreadId();
}
CMenuFocusManager::~CMenuFocusManager()
{
}
void CMenuFocusManager::DisableMouseTrack(HWND parent, BOOL disableThis)
{
BOOL bDisable = FALSE;
BOOL lastDisable = FALSE;
int i = m_bandCount;
while (--i >= 0)
{
StackEntry& entry = m_bandStack[i];
if (entry.type != TrackedMenuEntry)
{
HWND hwnd;
HRESULT hr = entry.mb->_GetTopLevelWindow(&hwnd);
if (FAILED_UNEXPECTEDLY(hr))
break;
if (hwnd == parent)
{
lastDisable = disableThis;
entry.mb->_DisableMouseTrack(disableThis);
bDisable = TRUE;
}
else
{
lastDisable = bDisable;
entry.mb->_DisableMouseTrack(bDisable);
}
}
}
m_mouseTrackDisabled = lastDisable;
}
void CMenuFocusManager::SetCapture(HWND child)
{
if (m_captureHwnd != child)
{
if (child)
{
::SetCapture(child);
m_captureHwnd = child;
TRACE("MouseTrack is now capturing %p\n", child);
}
else
{
::ReleaseCapture();
m_captureHwnd = NULL;
TRACE("MouseTrack is now off\n");
}
}
}
HRESULT CMenuFocusManager::IsTrackedWindow(HWND hWnd, StackEntry ** pentry)
{
if (pentry)
*pentry = NULL;
for (int i = m_bandCount; --i >= 0;)
{
StackEntry& entry = m_bandStack[i];
if (entry.type != TrackedMenuEntry)
{
HRESULT hr = entry.mb->IsWindowOwner(hWnd);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (hr == S_OK)
{
if (pentry)
*pentry = &entry;
return S_OK;
}
}
}
return S_FALSE;
}
HRESULT CMenuFocusManager::IsTrackedWindowOrParent(HWND hWnd)
{
for (int i = m_bandCount; --i >= 0;)
{
StackEntry& entry = m_bandStack[i];
if (entry.type != TrackedMenuEntry)
{
HRESULT hr = entry.mb->IsWindowOwner(hWnd);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (hr == S_OK)
return S_OK;
if (entry.mb->_IsPopup() == S_OK)
{
CComPtr<IUnknown> site;
CComPtr<IOleWindow> pw;
hr = entry.mb->GetSite(IID_PPV_ARG(IUnknown, &site));
if (FAILED_UNEXPECTEDLY(hr))
continue;
hr = IUnknown_QueryService(site, SID_SMenuBandParent, IID_PPV_ARG(IOleWindow, &pw));
if (FAILED_UNEXPECTEDLY(hr))
continue;
HWND hParent;
if (pw->GetWindow(&hParent) == S_OK && hParent == hWnd)
return S_OK;
}
}
}
return S_FALSE;
}
LRESULT CMenuFocusManager::ProcessMouseMove(MSG* msg)
{
HWND child;
int iHitTestResult = -1;
POINT pt2 = { GET_X_LPARAM(msg->lParam), GET_Y_LPARAM(msg->lParam) };
ClientToScreen(msg->hwnd, &pt2);
// Don't do anything if the mouse has not been moved
POINT pt = msg->pt;
if (pt.x == m_ptPrev.x && pt.y == m_ptPrev.y)
return TRUE;
// Don't do anything if another window is capturing the mouse.
HWND cCapture = ::GetCapture();
if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
return TRUE;
m_movedSinceDown = TRUE;
m_ptPrev = pt;
child = WindowFromPoint(pt);
StackEntry * entry = NULL;
if (IsTrackedWindow(child, &entry) == S_OK)
{
TRACE("MouseMove %d\n", m_isLButtonDown);
}
BOOL isTracking = FALSE;
if (entry && (entry->type == MenuBarEntry || m_current->type != TrackedMenuEntry))
{
ScreenToClient(child, &pt);
iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
isTracking = entry->mb->_IsTracking();
if (SendMessage(child, WM_USER_ISTRACKEDITEM, iHitTestResult, 0) == S_FALSE)
{
TRACE("Hot item tracking detected a change (capture=%p / cCapture=%p)...\n", m_captureHwnd, cCapture);
DisableMouseTrack(NULL, FALSE);
if (isTracking && iHitTestResult >= 0 && m_current->type == TrackedMenuEntry)
SendMessage(entry->hwnd, WM_CANCELMODE, 0, 0);
PostMessage(child, WM_USER_CHANGETRACKEDITEM, iHitTestResult, MAKELPARAM(isTracking, TRUE));
if (m_current->type == TrackedMenuEntry)
return FALSE;
}
}
if (m_entryUnderMouse != entry)
{
// Mouse moved away from a tracked window
if (m_entryUnderMouse)
{
m_entryUnderMouse->mb->_ChangeHotItem(NULL, -1, HICF_MOUSE);
}
if (cCapture == m_captureHwnd)
SetCapture(NULL);
}
if (m_hwndUnderMouse != child)
{
if (entry)
{
// Mouse moved to a tracked window
if (m_current->type == MenuPopupEntry)
{
ScreenToClient(child, &pt2);
SendMessage(child, WM_MOUSEMOVE, msg->wParam, MAKELPARAM(pt2.x, pt2.y));
}
}
m_hwndUnderMouse = child;
m_entryUnderMouse = entry;
}
if (m_current->type == MenuPopupEntry)
{
HWND parent = GetAncestor(child, GA_ROOT);
DisableMouseTrack(parent, FALSE);
}
return TRUE;
}
LRESULT CMenuFocusManager::ProcessMouseDown(MSG* msg)
{
HWND child;
int iHitTestResult = -1;
TRACE("ProcessMouseDown %d %d %d\n", msg->message, msg->wParam, msg->lParam);
// Don't do anything if another window is capturing the mouse.
HWND cCapture = ::GetCapture();
if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
{
TRACE("Foreign capture active.\n");
return TRUE;
}
POINT pt = msg->pt;
child = WindowFromPoint(pt);
StackEntry * entry = NULL;
if (IsTrackedWindow(child, &entry) != S_OK)
{
TRACE("Foreign window detected.\n");
return TRUE;
}
TRACE("MouseDown %d\n", m_isLButtonDown);
if (entry->type == MenuBarEntry)
{
if (entry != m_current)
{
TRACE("Menubar with popup active.\n");
return TRUE;
}
}
if (entry)
{
ScreenToClient(child, &pt);
iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
if (iHitTestResult >= 0)
{
TRACE("MouseDown send %d\n", iHitTestResult);
entry->mb->_MenuBarMouseDown(child, iHitTestResult);
}
}
msg->message = WM_NULL;
m_isLButtonDown = TRUE;
m_movedSinceDown = FALSE;
m_windowAtDown = child;
TRACE("MouseDown end %d\n", m_isLButtonDown);
return TRUE;
}
LRESULT CMenuFocusManager::ProcessMouseUp(MSG* msg)
{
HWND child;
int iHitTestResult = -1;
TRACE("ProcessMouseUp %d %d %d\n", msg->message, msg->wParam, msg->lParam);
// Don't do anything if another window is capturing the mouse.
HWND cCapture = ::GetCapture();
if (cCapture && cCapture != m_captureHwnd && m_current->type != TrackedMenuEntry)
return TRUE;
if (!m_isLButtonDown)
return TRUE;
m_isLButtonDown = FALSE;
POINT pt = msg->pt;
child = WindowFromPoint(pt);
StackEntry * entry = NULL;
if (IsTrackedWindow(child, &entry) != S_OK)
return TRUE;
TRACE("MouseUp %d\n", m_isLButtonDown);
if (entry)
{
ScreenToClient(child, &pt);
iHitTestResult = SendMessageW(child, TB_HITTEST, 0, (LPARAM) &pt);
if (iHitTestResult >= 0)
{
TRACE("MouseUp send %d\n", iHitTestResult);
entry->mb->_MenuBarMouseUp(child, iHitTestResult);
}
}
return TRUE;
}
LRESULT CMenuFocusManager::MsgFilterHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam)
{
if (nCode < 0)
return CallNextHookEx(m_hMsgFilterHook, nCode, hookWParam, hookLParam);
if (nCode == MSGF_MENU)
{
BOOL callNext = TRUE;
MSG* msg = reinterpret_cast<MSG*>(hookLParam);
switch (msg->message)
{
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
if (m_menuBar && m_current->type == TrackedMenuEntry)
{
POINT pt = msg->pt;
HWND child = WindowFromPoint(pt);
BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK;
if (hoveringMenuBar)
{
m_menuBar->mb->_BeforeCancelPopup();
}
}
break;
case WM_MOUSEMOVE:
callNext = ProcessMouseMove(msg);
break;
case WM_INITMENUPOPUP:
TRACE("WM_INITMENUPOPUP %p %p\n", msg->wParam, msg->lParam);
m_selectedMenu = reinterpret_cast<HMENU>(msg->lParam);
m_selectedItem = -1;
m_selectedItemFlags = 0;
break;
case WM_MENUSELECT:
TRACE("WM_MENUSELECT %p %p\n", msg->wParam, msg->lParam);
m_selectedMenu = reinterpret_cast<HMENU>(msg->lParam);
m_selectedItem = GET_X_LPARAM(msg->wParam);
m_selectedItemFlags = HIWORD(msg->wParam);
break;
case WM_KEYDOWN:
switch (msg->wParam)
{
case VK_LEFT:
if (m_current->hmenu == m_selectedMenu)
{
m_parent->mb->_MenuItemHotTrack(VK_LEFT);
}
break;
case VK_RIGHT:
if (m_selectedItem < 0 || !(m_selectedItemFlags & MF_POPUP))
{
m_parent->mb->_MenuItemHotTrack(VK_RIGHT);
}
break;
}
break;
}
if (!callNext)
return 1;
}
return CallNextHookEx(m_hMsgFilterHook, nCode, hookWParam, hookLParam);
}
LRESULT CMenuFocusManager::GetMsgHook(INT nCode, WPARAM hookWParam, LPARAM hookLParam)
{
BOOL isLButton = FALSE;
if (nCode < 0)
return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
if (nCode == HC_ACTION)
{
BOOL callNext = TRUE;
MSG* msg = reinterpret_cast<MSG*>(hookLParam);
POINT pt = msg->pt;
switch (msg->message)
{
case WM_NCLBUTTONDOWN:
case WM_LBUTTONDOWN:
isLButton = TRUE;
// fallthrough;
case WM_NCRBUTTONDOWN:
case WM_RBUTTONDOWN:
if (m_menuBar && m_current->type == MenuPopupEntry)
{
POINT pt = msg->pt;
HWND child = WindowFromPoint(pt);
BOOL hoveringMenuBar = m_menuBar->mb->IsWindowOwner(child) == S_OK;
if (hoveringMenuBar)
{
m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL);
break;
}
}
if (m_current->type == MenuPopupEntry)
{
HWND child = WindowFromPoint(pt);
if (IsTrackedWindowOrParent(child) != S_OK)
{
SetCapture(NULL);
m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL);
break;
}
}
if (isLButton)
{
ProcessMouseDown(msg);
}
break;
case WM_NCLBUTTONUP:
case WM_LBUTTONUP:
ProcessMouseUp(msg);
break;
case WM_MOUSEMOVE:
callNext = ProcessMouseMove(msg);
break;
case WM_MOUSELEAVE:
callNext = ProcessMouseMove(msg);
//callNext = ProcessMouseLeave(msg);
break;
case WM_SYSKEYDOWN:
case WM_KEYDOWN:
if (m_current->type == MenuPopupEntry)
{
DisableMouseTrack(m_current->hwnd, TRUE);
switch (msg->wParam)
{
case VK_ESCAPE:
case VK_MENU:
case VK_LMENU:
case VK_RMENU:
m_current->mb->_MenuItemHotTrack(MPOS_FULLCANCEL);
break;
case VK_RETURN:
m_current->mb->_MenuItemHotTrack(MPOS_EXECUTE);
break;
case VK_LEFT:
m_current->mb->_MenuItemHotTrack(VK_LEFT);
break;
case VK_RIGHT:
m_current->mb->_MenuItemHotTrack(VK_RIGHT);
break;
case VK_UP:
m_current->mb->_MenuItemHotTrack(VK_UP);
break;
case VK_DOWN:
m_current->mb->_MenuItemHotTrack(VK_DOWN);
break;
}
msg->message = WM_NULL;
msg->lParam = 0;
msg->wParam = 0;
}
break;
}
if (!callNext)
return 1;
}
return CallNextHookEx(m_hGetMsgHook, nCode, hookWParam, hookLParam);
}
HRESULT CMenuFocusManager::PlaceHooks()
{
if (m_hMsgFilterHook)
{
WARN("GETMESSAGE hook already placed!\n");
return S_OK;
}
if (m_hMsgFilterHook)
{
WARN("MSGFILTER hook already placed!\n");
return S_OK;
}
if (m_current->type == TrackedMenuEntry)
{
TRACE("Entering MSGFILTER hook...\n");
m_hMsgFilterHook = SetWindowsHookEx(WH_MSGFILTER, s_MsgFilterHook, NULL, m_threadId);
}
else
{
TRACE("Entering GETMESSAGE hook...\n");
m_hGetMsgHook = SetWindowsHookEx(WH_GETMESSAGE, s_GetMsgHook, NULL, m_threadId);
}
return S_OK;
}
HRESULT CMenuFocusManager::RemoveHooks()
{
TRACE("Removing all hooks...\n");
if (m_hMsgFilterHook)
UnhookWindowsHookEx(m_hMsgFilterHook);
if (m_hGetMsgHook)
UnhookWindowsHookEx(m_hGetMsgHook);
m_hMsgFilterHook = NULL;
m_hGetMsgHook = NULL;
return S_OK;
}
HRESULT CMenuFocusManager::UpdateFocus()
{
HRESULT hr;
StackEntry * old = m_current;
TRACE("UpdateFocus\n");
if (old)
SetCapture(NULL);
if (m_bandCount > 0)
m_current = &(m_bandStack[m_bandCount - 1]);
else
m_current = NULL;
if (m_current && m_current->type != TrackedMenuEntry)
{
hr = m_current->mb->_GetTopLevelWindow(&(m_current->hwnd));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
if (m_bandCount >= 2)
{
m_parent = &(m_bandStack[m_bandCount - 2]);
_ASSERT(m_parent->type != TrackedMenuEntry);
}
else
{
m_parent = NULL;
}
if (m_bandCount >= 1 && m_bandStack[0].type == MenuBarEntry)
{
m_menuBar = &(m_bandStack[0]);
}
else
{
m_menuBar = NULL;
}
if (old && (!m_current || old->type != m_current->type))
{
if (m_current && m_current->type != TrackedMenuEntry)
{
DisableMouseTrack(m_current->hwnd, FALSE);
}
hr = RemoveHooks();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
if (m_current && (!old || old->type != m_current->type))
{
hr = PlaceHooks();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
if (m_parent)
{
DisableMouseTrack(m_parent->hwnd, TRUE);
}
if ((m_current && m_current->type == MenuPopupEntry) &&
(!m_parent || m_parent->type == MenuBarEntry))
{
// When the mouse moves, it should set itself to the proper band
SetCapture(m_current->hwnd);
if (old && old->type == TrackedMenuEntry)
{
// FIXME: Debugging code, probably not right
POINT pt2;
RECT rc2;
GetCursorPos(&pt2);
ScreenToClient(m_current->hwnd, &pt2);
GetClientRect(m_current->hwnd, &rc2);
if (PtInRect(&rc2, pt2))
SendMessage(m_current->hwnd, WM_MOUSEMOVE, 0, MAKELPARAM(pt2.x, pt2.y));
else
SendMessage(m_current->hwnd, WM_MOUSELEAVE, 0, 0);
}
}
_ASSERT(!m_parent || m_parent->type != TrackedMenuEntry);
return S_OK;
}
HRESULT CMenuFocusManager::PushMenuBar(CMenuBand * mb)
{
DbgPrint("PushMenuBar %p\n", mb);
mb->AddRef();
_ASSERT(m_bandCount == 0);
HRESULT hr = PushToArray(MenuBarEntry, mb, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return UpdateFocus();
}
HRESULT CMenuFocusManager::PushMenuPopup(CMenuBand * mb)
{
DbgPrint("PushTrackedPopup %p\n", mb);
mb->AddRef();
_ASSERT(!m_current || m_current->type != TrackedMenuEntry);
HRESULT hr = PushToArray(MenuPopupEntry, mb, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = UpdateFocus();
if (m_parent && m_parent->type != TrackedMenuEntry)
{
m_parent->mb->_SetChildBand(mb);
mb->_SetParentBand(m_parent->mb);
}
return hr;
}
HRESULT CMenuFocusManager::PushTrackedPopup(HMENU popup)
{
DbgPrint("PushTrackedPopup %p\n", popup);
_ASSERT(m_bandCount > 0);
_ASSERT(!m_current || m_current->type != TrackedMenuEntry);
HRESULT hr = PushToArray(TrackedMenuEntry, NULL, popup);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
DbgPrint("PushTrackedPopup %p\n", popup);
m_selectedMenu = popup;
m_selectedItem = -1;
m_selectedItemFlags = 0;
return UpdateFocus();
}
HRESULT CMenuFocusManager::PopMenuBar(CMenuBand * mb)
{
StackEntryType type;
CMenuBand * mbc;
HRESULT hr;
DbgPrint("PopMenuBar %p\n", mb);
if (m_current == m_entryUnderMouse)
{
m_entryUnderMouse = NULL;
}
hr = PopFromArray(&type, &mbc, NULL);
if (FAILED_UNEXPECTEDLY(hr))
{
UpdateFocus();
return hr;
}
_ASSERT(type == MenuBarEntry);
if (type != MenuBarEntry)
return E_FAIL;
if (!mbc)
return E_FAIL;
mbc->_SetParentBand(NULL);
mbc->Release();
hr = UpdateFocus();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (m_current)
{
_ASSERT(m_current->type != TrackedMenuEntry);
m_current->mb->_SetChildBand(NULL);
}
return S_OK;
}
HRESULT CMenuFocusManager::PopMenuPopup(CMenuBand * mb)
{
StackEntryType type;
CMenuBand * mbc;
HRESULT hr;
DbgPrint("PopMenuPopup %p\n", mb);
if (m_current == m_entryUnderMouse)
{
m_entryUnderMouse = NULL;
}
hr = PopFromArray(&type, &mbc, NULL);
if (FAILED_UNEXPECTEDLY(hr))
{
UpdateFocus();
return hr;
}
_ASSERT(type == MenuPopupEntry);
if (type != MenuPopupEntry)
return E_FAIL;
if (!mbc)
return E_FAIL;
mbc->_SetParentBand(NULL);
mbc->Release();
hr = UpdateFocus();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (m_current)
{
_ASSERT(m_current->type != TrackedMenuEntry);
m_current->mb->_SetChildBand(NULL);
}
return S_OK;
}
HRESULT CMenuFocusManager::PopTrackedPopup(HMENU popup)
{
StackEntryType type;
HMENU hmenu;
HRESULT hr;
DbgPrint("PopTrackedPopup %p\n", popup);
hr = PopFromArray(&type, NULL, &hmenu);
if (FAILED_UNEXPECTEDLY(hr))
{
UpdateFocus();
return hr;
}
_ASSERT(type == TrackedMenuEntry);
if (type != TrackedMenuEntry)
return E_FAIL;
if (hmenu != popup)
return E_FAIL;
hr = UpdateFocus();
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return S_OK;
}

View File

@ -0,0 +1,125 @@
/*
* Shell Menu Band
*
* Copyright 2014 David Quintana
*
* 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
*/
#pragma once
class CMenuBand;
class CMenuFocusManager :
public CComCoClass<CMenuFocusManager>,
public CComObjectRootEx<CComMultiThreadModelNoCS>
{
private:
static DWORD TlsIndex;
static CMenuFocusManager * GetManager();
enum StackEntryType
{
NoEntry,
MenuBarEntry,
MenuPopupEntry,
TrackedMenuEntry
};
struct StackEntry
{
StackEntryType type;
CMenuBand * mb;
HMENU hmenu;
HWND hwnd;
};
public:
static CMenuFocusManager * AcquireManager();
static void ReleaseManager(CMenuFocusManager * obj);
private:
static LRESULT CALLBACK s_MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam);
static LRESULT CALLBACK s_GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam);
private:
StackEntry * m_current;
StackEntry * m_parent;
StackEntry * m_menuBar;
HHOOK m_hMsgFilterHook;
HHOOK m_hGetMsgHook;
DWORD m_threadId;
BOOL m_mouseTrackDisabled;
POINT m_ptPrev;
HWND m_captureHwnd;
HWND m_hwndUnderMouse;
StackEntry * m_entryUnderMouse;
HMENU m_selectedMenu;
INT m_selectedItem;
DWORD m_selectedItemFlags;
BOOL m_isLButtonDown;
BOOL m_movedSinceDown;
HWND m_windowAtDown;
// TODO: make dynamic
#define MAX_RECURSE 20
StackEntry m_bandStack[MAX_RECURSE];
int m_bandCount;
HRESULT PushToArray(StackEntryType type, CMenuBand * mb, HMENU hmenu);
HRESULT PopFromArray(StackEntryType * pType, CMenuBand ** pMb, HMENU * pHmenu);
protected:
CMenuFocusManager();
~CMenuFocusManager();
public:
DECLARE_NOT_AGGREGATABLE(CMenuFocusManager)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMenuFocusManager)
END_COM_MAP()
private:
LRESULT GetMsgHook(INT nCode, WPARAM wParam, LPARAM lParam);
LRESULT MsgFilterHook(INT nCode, WPARAM wParam, LPARAM lParam);
HRESULT PlaceHooks();
HRESULT RemoveHooks();
HRESULT UpdateFocus();
HRESULT IsTrackedWindow(HWND hWnd, StackEntry ** pentry = NULL);
HRESULT IsTrackedWindowOrParent(HWND hWnd);
void DisableMouseTrack(HWND parent, BOOL disableThis);
void SetCapture(HWND child);
LRESULT ProcessMouseMove(MSG* msg);
LRESULT ProcessMouseDown(MSG* msg);
LRESULT ProcessMouseUp(MSG* msg);
public:
HRESULT PushMenuBar(CMenuBand * mb);
HRESULT PushMenuPopup(CMenuBand * mb);
HRESULT PushTrackedPopup(HMENU popup);
HRESULT PopMenuBar(CMenuBand * mb);
HRESULT PopMenuPopup(CMenuBand * mb);
HRESULT PopTrackedPopup(HMENU popup);
};

View File

@ -0,0 +1,361 @@
/*
* Shell Menu Site
*
* Copyright 2014 David Quintana
*
* 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"
#include <atlwin.h>
#include <shlwapi_undoc.h>
#include "CMenuSite.h"
WINE_DEFAULT_DEBUG_CHANNEL(menusite);
extern "C"
HRESULT WINAPI CMenuSite_Constructor(REFIID riid, LPVOID *ppv)
{
return ShellObjectCreator<CMenuSite>(riid, ppv);
}
CMenuSite::CMenuSite() :
m_DeskBarSite(NULL),
m_BandObject(NULL),
m_DeskBand(NULL),
m_WinEventHandler(NULL),
m_hWndBand(NULL)
{
}
HRESULT STDMETHODCALLTYPE CMenuSite::ContextSensitiveHelp(BOOL fEnterMode)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuSite::GetBandSiteInfo(BANDSITEINFO *pbsinfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuSite::RemoveBand(DWORD dwBandID)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuSite::SetBandSiteInfo(const BANDSITEINFO *pbsinfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuSite::SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuSite::SetModeDBC(DWORD dwMode)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMenuSite::TranslateAcceleratorIO(LPMSG lpMsg)
{
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CMenuSite::HasFocusIO()
{
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CMenuSite::OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus)
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuSite::AddBand(IUnknown * punk)
{
HRESULT hr;
#define TO_HRESULT(x) ((HRESULT)(S_OK+(x)))
CComPtr<IUnknown> pUnknown;
punk->QueryInterface(IID_PPV_ARG(IUnknown, &pUnknown));
if (pUnknown == m_BandObject)
return TO_HRESULT(0);
if (m_BandObject)
{
hr = IUnknown_SetSite(m_BandObject, NULL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
m_BandObject = NULL;
m_DeskBand = NULL;
m_WinEventHandler = NULL;
m_hWndBand = NULL;
if (!pUnknown)
return TO_HRESULT(0);
hr = pUnknown->QueryInterface(IID_PPV_ARG(IDeskBand, &m_DeskBand));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pUnknown->QueryInterface(IID_PPV_ARG(IWinEventHandler, &m_WinEventHandler));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = IUnknown_SetSite(pUnknown, this->ToIUnknown());
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = IUnknown_GetWindow(pUnknown, &m_hWndBand);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
m_BandObject = pUnknown;
return TO_HRESULT(0);
}
HRESULT STDMETHODCALLTYPE CMenuSite::EnumBands(UINT uBand, DWORD* pdwBandID)
{
if (uBand != 0)
return E_FAIL;
*pdwBandID = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuSite::Exec(const GUID * pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
return IUnknown_Exec(m_DeskBarSite, *pguidCmdGroup, nCmdID, nCmdexecopt, pvaIn, pvaOut);
}
HRESULT STDMETHODCALLTYPE CMenuSite::GetBandObject(DWORD dwBandID, REFIID riid, VOID **ppv)
{
if (dwBandID != 0 || m_BandObject == NULL)
{
*ppv = NULL;
return E_NOINTERFACE;
}
return m_BandObject->QueryInterface(riid, ppv);
}
HRESULT STDMETHODCALLTYPE CMenuSite::GetSize(DWORD dwWhich, LPRECT prc)
{
memset(prc, 0, sizeof(*prc));
if (dwWhich != 0)
return S_OK;
if (m_DeskBand == NULL)
return S_OK;
DESKBANDINFO info = { 0 };
info.dwMask = DBIM_MAXSIZE;
m_DeskBand->GetBandInfo(0, 0, &info);
prc->right = info.ptMaxSize.x;
prc->bottom = info.ptMaxSize.y;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuSite::GetWindow(HWND *phwnd)
{
if (!IsWindow())
return E_FAIL;
*phwnd = m_hWnd;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuSite::IsWindowOwner(HWND hWnd)
{
if (hWnd == m_hWnd)
return S_OK;
if (!m_WinEventHandler)
return S_FALSE;
return m_WinEventHandler->IsWindowOwner(hWnd);
}
HRESULT STDMETHODCALLTYPE CMenuSite::OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
if (!m_WinEventHandler)
return S_OK;
return m_WinEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
}
HRESULT STDMETHODCALLTYPE CMenuSite::QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName)
{
if (dwBandID != 0)
return E_FAIL;
if (!m_BandObject)
{
*ppstb = NULL;
return E_NOINTERFACE;
}
HRESULT hr = m_BandObject->QueryInterface(IID_PPV_ARG(IDeskBand, ppstb));
*pdwState = 1;
if (cchName > 0)
pszName[0] = 0;
return hr;
}
HRESULT STDMETHODCALLTYPE CMenuSite::QueryService(REFGUID guidService, REFIID riid, void **ppvObject)
{
*ppvObject = NULL;
if (IsEqualGUID(guidService, SID_SMenuBandBottom) ||
IsEqualGUID(guidService, SID_SMenuBandBottomSelected) ||
IsEqualGUID(guidService, SID_SMenuBandChild))
{
if (m_BandObject == NULL)
return E_NOINTERFACE;
return IUnknown_QueryService(m_BandObject, guidService, riid, ppvObject);
}
if (!m_DeskBarSite)
return E_NOINTERFACE;
return IUnknown_QueryService(m_DeskBarSite, guidService, riid, ppvObject);
}
HRESULT STDMETHODCALLTYPE CMenuSite::QueryStatus(const GUID * pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
{
if (!m_DeskBarSite)
return E_FAIL;
return IUnknown_QueryStatus(m_DeskBarSite, *pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
HRESULT STDMETHODCALLTYPE CMenuSite::SetDeskBarSite(IUnknown *punkSite)
{
HRESULT hr;
CComPtr<IUnknown> protectThis(this->ToIUnknown());
if (punkSite)
{
HWND hWndSite;
m_DeskBarSite = NULL;
hr = IUnknown_GetWindow(punkSite, &hWndSite);
if (FAILED(hr) || !hWndSite)
return E_FAIL;
if (!m_hWnd)
{
Create(hWndSite, NULL, L"MenuSite");
}
m_DeskBarSite = punkSite;
return S_OK;
}
if (m_DeskBand)
{
m_DeskBand->CloseDW(0);
}
hr = IUnknown_SetSite(m_BandObject, NULL);
m_BandObject = NULL;
m_DeskBand = NULL;
m_WinEventHandler = NULL;
m_hWndBand = NULL;
m_hWnd = NULL;
m_DeskBarSite = NULL;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMenuSite::UIActivateDBC(DWORD dwState)
{
if (!m_DeskBand)
return S_OK;
return m_DeskBand->ShowDW(dwState != 0);
}
HRESULT STDMETHODCALLTYPE CMenuSite::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
{
if (lpMsg)
return E_FAIL;
return IUnknown_UIActivateIO(m_BandObject, fActivate, lpMsg);
}
BOOL CMenuSite::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD mapId)
{
HWND hWndTarget = NULL;
CComPtr<IUnknown> protectThis(this->ToIUnknown());
switch (uMsg)
{
case WM_SIZE:
if (m_BandObject)
{
CComPtr<IMenuPopup> pMenuPopup;
if (SUCCEEDED(m_BandObject->QueryInterface(IID_PPV_ARG(IMenuPopup, &pMenuPopup))))
{
RECT Rect = { 0 };
GetClientRect(&Rect);
pMenuPopup->OnPosRectChangeDB(&Rect);
}
}
hWndTarget = hWnd;
lResult = 1;
break;
case WM_NOTIFY:
hWndTarget = reinterpret_cast<LPNMHDR>(lParam)->hwndFrom;
break;
case WM_COMMAND:
hWndTarget = (HWND) lParam;
break;
default:
return FALSE;
}
if (hWndTarget && m_WinEventHandler &&
m_WinEventHandler->IsWindowOwner(hWndTarget) == S_OK)
{
if (SUCCEEDED(m_WinEventHandler->OnWinEvent(hWndTarget, uMsg, wParam, lParam, &lResult)))
return TRUE;
}
return FALSE;
}

View File

@ -0,0 +1,106 @@
/*
* Shell Menu Site
*
* Copyright 2014 David Quintana
*
* 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
*/
#pragma once
class CMenuSite :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl<CMenuSite, CWindow, CControlWinTraits>,
public IBandSite,
public IDeskBarClient,
public IOleCommandTarget,
public IInputObject,
public IInputObjectSite,
public IWinEventHandler,
public IServiceProvider
{
private:
CComPtr<IUnknown> m_DeskBarSite;
CComPtr<IUnknown> m_BandObject;
CComPtr<IDeskBand> m_DeskBand;
CComPtr<IWinEventHandler> m_WinEventHandler;
HWND m_hWndBand;
public:
CMenuSite();
virtual ~CMenuSite() {}
DECLARE_WND_CLASS_EX(_T("MenuSite"), 0, COLOR_MENU)
DECLARE_NOT_AGGREGATABLE(CMenuSite)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMenuSite)
COM_INTERFACE_ENTRY_IID(IID_IBandSite, IBandSite)
COM_INTERFACE_ENTRY_IID(IID_IDeskBarClient, IDeskBarClient)
COM_INTERFACE_ENTRY_IID(IID_IOleWindow, IOleWindow)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
COM_INTERFACE_ENTRY_IID(IID_IInputObject, IInputObject)
COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
COM_INTERFACE_ENTRY_IID(IID_IWinEventHandler, IWinEventHandler)
COM_INTERFACE_ENTRY_IID(IID_IServiceProvider, IServiceProvider)
END_COM_MAP()
// IBandSite
virtual HRESULT STDMETHODCALLTYPE AddBand(IUnknown * punk);
virtual HRESULT STDMETHODCALLTYPE EnumBands(UINT uBand, DWORD* pdwBandID);
virtual HRESULT STDMETHODCALLTYPE QueryBand(DWORD dwBandID, IDeskBand **ppstb, DWORD *pdwState, LPWSTR pszName, int cchName);
virtual HRESULT STDMETHODCALLTYPE GetBandObject(DWORD dwBandID, REFIID riid, VOID **ppv);
// IDeskBarClient
virtual HRESULT STDMETHODCALLTYPE SetDeskBarSite(IUnknown *punkSite);
virtual HRESULT STDMETHODCALLTYPE GetSize(DWORD dwWhich, LPRECT prc);
virtual HRESULT STDMETHODCALLTYPE UIActivateDBC(DWORD dwState);
// IOleWindow
virtual HRESULT STDMETHODCALLTYPE GetWindow(HWND *phwnd);
// IOleCommandTarget
virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID * pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText);
virtual HRESULT STDMETHODCALLTYPE Exec(const GUID * pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
// IInputObject
virtual HRESULT STDMETHODCALLTYPE UIActivateIO(BOOL fActivate, LPMSG lpMsg);
virtual HRESULT STDMETHODCALLTYPE HasFocusIO();
virtual HRESULT STDMETHODCALLTYPE TranslateAcceleratorIO(LPMSG lpMsg);
// IInputObjectSite
virtual HRESULT STDMETHODCALLTYPE OnFocusChangeIS(IUnknown *punkObj, BOOL fSetFocus);
// IWinEventHandler
virtual HRESULT STDMETHODCALLTYPE IsWindowOwner(HWND hWnd);
virtual HRESULT STDMETHODCALLTYPE OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult);
// IServiceProvider
virtual HRESULT STDMETHODCALLTYPE QueryService(REFGUID guidService, REFIID riid, void **ppvObject);
// Using custom message map instead
virtual BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD mapId = 0);
// UNIMPLEMENTED
virtual HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
virtual HRESULT STDMETHODCALLTYPE GetBandSiteInfo(BANDSITEINFO *pbsinfo);
virtual HRESULT STDMETHODCALLTYPE RemoveBand(DWORD dwBandID);
virtual HRESULT STDMETHODCALLTYPE SetBandSiteInfo(const BANDSITEINFO *pbsinfo);
virtual HRESULT STDMETHODCALLTYPE SetBandState(DWORD dwBandID, DWORD dwMask, DWORD dwState);
virtual HRESULT STDMETHODCALLTYPE SetModeDBC(DWORD dwMode);
private:
IUnknown * ToIUnknown() { return static_cast<IDeskBarClient*>(this); }
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,193 @@
/*
* Shell Menu Band
*
* Copyright 2014 David Quintana
*
* 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
*/
#pragma once
class CMenuBand;
class CMenuFocusManager;
#define WM_USER_ISTRACKEDITEM (WM_APP+41)
#define WM_USER_CHANGETRACKEDITEM (WM_APP+42)
class CMenuToolbarBase :
public CToolbar<DWORD_PTR>
{
CContainedWindow m_pager;
private:
HFONT m_marlett;
BOOL m_useFlatMenus;
WNDPROC m_SubclassOld;
BOOL m_disableMouseTrack;
BOOL m_timerEnabled;
protected:
CMenuBand * m_menuBand;
DWORD m_dwMenuFlags;
BOOL m_hasSizes;
SIZE m_idealSize;
SIZE m_itemSize;
BOOL m_usePager;
CMenuToolbarBase * m_hotBar;
INT m_hotItem;
CMenuToolbarBase * m_popupBar;
INT m_popupItem;
DWORD m_initFlags;
BOOL m_isTrackingPopup;
INT m_executeIndex;
INT m_executeItem;
DWORD_PTR m_executeData;
BOOL m_cancelingPopup;
public:
CMenuToolbarBase(CMenuBand *menuBand, BOOL usePager);
virtual ~CMenuToolbarBase();
HRESULT IsWindowOwner(HWND hwnd);
HRESULT CreateToolbar(HWND hwndParent, DWORD dwFlags);
HRESULT GetWindow(HWND *phwnd);
HRESULT ShowDW(BOOL fShow);
HRESULT Close();
HRESULT OnWinEvent(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult);
HRESULT ChangeHotItem(CMenuToolbarBase * toolbar, INT item, DWORD dwFlags);
HRESULT ChangePopupItem(CMenuToolbarBase * toolbar, INT item);
HRESULT PopupSubMenu(UINT itemId, UINT index, IShellMenu* childShellMenu, BOOL keyInitiated);
HRESULT PopupSubMenu(UINT itemId, UINT index, HMENU menu);
HRESULT TrackContextMenu(IContextMenu* contextMenu, POINT pt);
HRESULT KeyboardItemChange(DWORD changeType);
HRESULT PrepareExecuteItem(INT iItem);
HRESULT ExecuteItem();
HRESULT GetSizes(SIZE* pMinSize, SIZE* pMaxSize, SIZE* pIntegralSize);
HRESULT SetPosSize(int x, int y, int cx, int cy);
void InvalidateDraw();
HRESULT DisableMouseTrack(BOOL bDisable);
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE) = 0;
HRESULT CancelCurrentPopup();
HRESULT PopupItem(INT iItem, BOOL keyInitiated);
HRESULT GetDataFromId(INT iItem, INT* pIndex, DWORD_PTR* pData);
HRESULT KillPopupTimer();
HRESULT MenuBarMouseDown(INT iIndex);
HRESULT MenuBarMouseUp(INT iIndex);
HRESULT ProcessClick(INT iItem);
HRESULT BeforeCancelPopup();
protected:
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb) = 0;
virtual HRESULT InternalGetTooltip(INT iItem, INT index, DWORD_PTR dwData, LPWSTR pszText, INT cchTextMax) = 0;
virtual HRESULT InternalExecuteItem(INT iItem, INT index, DWORD_PTR dwData) = 0;
virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData, BOOL keyInitiated) = 0;
virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData) = 0;
virtual HRESULT InternalContextMenu(INT iItem, INT index, DWORD_PTR dwData, POINT pt) = 0;
HRESULT AddButton(DWORD commandId, LPCWSTR caption, BOOL hasSubMenu, INT iconId, DWORD_PTR buttonData, BOOL last);
HRESULT AddSeparator(BOOL last);
HRESULT AddPlaceholder();
HRESULT ClearToolbar();
HWND GetToolbar() { return m_hWnd; }
private:
HRESULT UpdateImageLists();
HRESULT OnPagerCalcSize(LPNMPGCALCSIZE csize);
HRESULT OnContextMenu(NMMOUSE * rclick);
HRESULT OnCustomDraw(LPNMTBCUSTOMDRAW cdraw, LRESULT * theResult);
HRESULT OnGetInfoTip(NMTBGETINFOTIP * tip);
LRESULT IsTrackedItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT ChangeTrackedItem(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnWinEventWrap(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
HRESULT OnPopupTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
BEGIN_MSG_MAP(CMenuToolbarBase)
MESSAGE_HANDLER(WM_USER_ISTRACKEDITEM, IsTrackedItem)
MESSAGE_HANDLER(WM_USER_CHANGETRACKEDITEM, ChangeTrackedItem)
MESSAGE_HANDLER(WM_COMMAND, OnWinEventWrap)
MESSAGE_HANDLER(WM_NOTIFY, OnWinEventWrap)
MESSAGE_HANDLER(WM_TIMER, OnPopupTimer)
END_MSG_MAP()
};
class CMenuStaticToolbar :
public CMenuToolbarBase
{
private:
HMENU m_hmenu;
HWND m_hwndMenu;
public:
CMenuStaticToolbar(CMenuBand *menuBand);
virtual ~CMenuStaticToolbar();
HRESULT SetMenu(HMENU hmenu, HWND hwnd, DWORD dwFlags);
HRESULT GetMenu(HMENU *phmenu, HWND *phwnd, DWORD *pdwFlags);
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE);
protected:
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb);
virtual HRESULT InternalGetTooltip(INT iItem, INT index, DWORD_PTR dwData, LPWSTR pszText, INT cchTextMax);
virtual HRESULT InternalExecuteItem(INT iItem, INT index, DWORD_PTR dwData);
virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData, BOOL keyInitiated);
virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData);
virtual HRESULT InternalContextMenu(INT iItem, INT index, DWORD_PTR dwData, POINT pt);
};
class CMenuSFToolbar :
public CMenuToolbarBase
{
private:
CComPtr<IShellFolder> m_shellFolder;
LPCITEMIDLIST m_idList;
HKEY m_hKey;
public:
CMenuSFToolbar(CMenuBand *menuBand);
virtual ~CMenuSFToolbar();
HRESULT SetShellFolder(IShellFolder *psf, LPCITEMIDLIST pidlFolder, HKEY hKey, DWORD dwFlags);
HRESULT GetShellFolder(DWORD *pdwFlags, LPITEMIDLIST *ppidl, REFIID riid, void **ppv);
virtual HRESULT FillToolbar(BOOL clearFirst=FALSE);
protected:
virtual HRESULT OnDeletingButton(const NMTOOLBAR * tb);
virtual HRESULT InternalGetTooltip(INT iItem, INT index, DWORD_PTR dwData, LPWSTR pszText, INT cchTextMax);
virtual HRESULT InternalExecuteItem(INT iItem, INT index, DWORD_PTR dwData);
virtual HRESULT InternalPopupItem(INT iItem, INT index, DWORD_PTR dwData, BOOL keyInitiated);
virtual HRESULT InternalHasSubMenu(INT iItem, INT index, DWORD_PTR dwData);
virtual HRESULT InternalContextMenu(INT iItem, INT index, DWORD_PTR dwData, POINT pt);
};

View File

@ -0,0 +1,789 @@
/*
* Shell Menu Site
*
* Copyright 2014 David Quintana
*
* 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"
#include <atlwin.h>
#include <shlwapi_undoc.h>
#include "CMergedFolder.h"
WINE_DEFAULT_DEBUG_CHANNEL(CMergedFolder);
struct LocalPidlInfo
{
BOOL shared;
IShellFolder * parent;
LPITEMIDLIST pidl;
};
class CEnumMergedFolder :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IEnumIDList
{
private:
CComPtr<IShellFolder> m_UserLocalFolder;
CComPtr<IShellFolder> m_AllUSersFolder;
HWND m_HwndOwner;
SHCONTF m_Flags;
HDSA m_hDsa;
UINT m_hDsaIndex;
UINT m_hDsaCount;
public:
CEnumMergedFolder();
virtual ~CEnumMergedFolder();
DECLARE_NOT_AGGREGATABLE(CEnumMergedFolder)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CEnumMergedFolder)
COM_INTERFACE_ENTRY_IID(IID_IEnumIDList, IEnumIDList)
END_COM_MAP()
int DsaDeleteCallback(LocalPidlInfo * info);
static int CALLBACK s_DsaDeleteCallback(void *pItem, void *pData);
HRESULT SetSources(IShellFolder * userLocal, IShellFolder * allUSers);
HRESULT Begin(HWND hwndOwner, SHCONTF flags);
HRESULT FindPidlInList(HWND hwndOwner, LPCITEMIDLIST pcidl, LocalPidlInfo * pinfo);
virtual HRESULT STDMETHODCALLTYPE Next(
ULONG celt,
LPITEMIDLIST *rgelt,
ULONG *pceltFetched);
virtual HRESULT STDMETHODCALLTYPE Skip(ULONG celt);
virtual HRESULT STDMETHODCALLTYPE Reset();
virtual HRESULT STDMETHODCALLTYPE Clone(IEnumIDList **ppenum);
};
CEnumMergedFolder::CEnumMergedFolder() :
m_UserLocalFolder(NULL),
m_AllUSersFolder(NULL),
m_HwndOwner(NULL),
m_Flags(0),
m_hDsa(NULL),
m_hDsaIndex(0),
m_hDsaCount(0)
{
}
CEnumMergedFolder::~CEnumMergedFolder()
{
DSA_DestroyCallback(m_hDsa, s_DsaDeleteCallback, this);
}
int CEnumMergedFolder::DsaDeleteCallback(LocalPidlInfo * info)
{
ILFree(info->pidl);
return 0;
}
int CALLBACK CEnumMergedFolder::s_DsaDeleteCallback(void *pItem, void *pData)
{
CEnumMergedFolder * mf = (CEnumMergedFolder*) pData;
LocalPidlInfo * item = (LocalPidlInfo*) pItem;
return mf->DsaDeleteCallback(item);
}
HRESULT CEnumMergedFolder::SetSources(IShellFolder * userLocal, IShellFolder * allUSers)
{
m_UserLocalFolder = userLocal;
m_AllUSersFolder = allUSers;
TRACE("SetSources %p %p\n", userLocal, allUSers);
return S_OK;
}
HRESULT CEnumMergedFolder::Begin(HWND hwndOwner, SHCONTF flags)
{
HRESULT hr;
if (m_hDsa && m_HwndOwner == hwndOwner && m_Flags == flags)
{
return Reset();
}
TRACE("Search conditions changed, recreating list...\n");
CComPtr<IEnumIDList> userLocal;
CComPtr<IEnumIDList> allUSers;
hr = m_UserLocalFolder->EnumObjects(hwndOwner, flags, &userLocal);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_AllUSersFolder->EnumObjects(hwndOwner, flags, &allUSers);
if (FAILED_UNEXPECTEDLY(hr))
{
userLocal = NULL;
return hr;
}
if (!m_hDsa)
{
m_hDsa = DSA_Create(sizeof(LocalPidlInfo), 10);
}
DSA_EnumCallback(m_hDsa, s_DsaDeleteCallback, this);
DSA_DeleteAllItems(m_hDsa);
m_hDsaCount = 0;
HRESULT hr1 = S_OK;
HRESULT hr2 = S_OK;
LPITEMIDLIST pidl1 = NULL;
LPITEMIDLIST pidl2 = NULL;
int order = 0;
do
{
if (order <= 0)
{
if (hr1 == S_OK)
{
hr1 = userLocal->Next(1, &pidl1, NULL);
if (FAILED_UNEXPECTEDLY(hr1))
return hr1;
}
else
{
pidl1 = NULL;
}
}
if (order >= 0)
{
if (hr2 == S_OK)
{
hr2 = allUSers->Next(1, &pidl2, NULL);
if (FAILED_UNEXPECTEDLY(hr2))
return hr2;
}
else
{
pidl2 = NULL;
}
}
if (hr1 == S_OK && hr2 == S_OK)
{
LPWSTR name1;
LPWSTR name2;
STRRET str1 = { STRRET_WSTR };
STRRET str2 = { STRRET_WSTR };
hr = m_UserLocalFolder->GetDisplayNameOf(pidl1, SHGDN_FORPARSING | SHGDN_INFOLDER, &str1);
if (FAILED(hr))
return hr;
hr = m_AllUSersFolder->GetDisplayNameOf(pidl2, SHGDN_FORPARSING | SHGDN_INFOLDER, &str2);
if (FAILED(hr))
return hr;
StrRetToStrW(&str1, pidl1, &name1);
StrRetToStrW(&str2, pidl2, &name2);
order = StrCmpW(name1, name2);
TRACE("Both sources are S_OK, comparison between %S and %S returns %d\n", name1, name2, order);
CoTaskMemFree(name1);
CoTaskMemFree(name2);
}
else if (hr1 == S_OK)
{
order = -1;
TRACE("Both sources are S_OK, forcing %d\n", order);
}
else if (hr2 == S_OK)
{
order = 1;
TRACE("Both sources are S_OK, forcing %d\n", order);
}
else
{
TRACE("None of the sources\n");
break;
}
LocalPidlInfo info = { FALSE };
if (order < 0)
{
info.parent = m_UserLocalFolder;
info.pidl = ILClone(pidl1);
ILFree(pidl1);
}
else if (order > 0)
{
info.parent = m_AllUSersFolder;
info.pidl = ILClone(pidl2);
ILFree(pidl2);
}
else // if (order == 0)
{
info.shared = TRUE;
info.parent = m_UserLocalFolder;
info.pidl = ILClone(pidl1);
ILFree(pidl1);
ILFree(pidl2);
}
TRACE("Inserting item %d with parent %p and pidl { cb=%d }\n", m_hDsaCount, info.parent, info.pidl->mkid.cb);
int idx = DSA_InsertItem(m_hDsa, DSA_APPEND, &info);
TRACE("New index: %d\n", idx);
m_hDsaCount++;
} while (hr1 == S_OK || hr2 == S_OK);
m_HwndOwner = hwndOwner;
m_Flags = flags;
return Reset();
}
HRESULT CEnumMergedFolder::FindPidlInList(HWND hwndOwner, LPCITEMIDLIST pcidl, LocalPidlInfo * pinfo)
{
HRESULT hr;
if (!m_hDsa)
{
Begin(hwndOwner, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS);
}
TRACE("Searching for pidl { cb=%d } in a list of %d items\n", pcidl->mkid.cb, m_hDsaCount);
for (int i = 0; i < (int)m_hDsaCount; i++)
{
LocalPidlInfo * tinfo = (LocalPidlInfo *)DSA_GetItemPtr(m_hDsa, i);
if (!tinfo)
return E_FAIL;
LocalPidlInfo info = *tinfo;
TRACE("Comparing with item at %d with parent %p and pidl { cb=%d }\n", i, info.parent, info.pidl->mkid.cb);
hr = info.parent->CompareIDs(0, info.pidl, pcidl);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
if (hr == S_OK)
{
*pinfo = info;
return S_OK;
}
else
{
TRACE("Comparison returned %d\n", (int) (short) (hr & 0xFFFF));
}
}
TRACE("Pidl not found\n");
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Next(
ULONG celt,
LPITEMIDLIST *rgelt,
ULONG *pceltFetched)
{
if (pceltFetched) *pceltFetched = 0;
if (m_hDsaIndex == m_hDsaCount)
return S_FALSE;
for (int i = 0; i < (int)celt;)
{
LocalPidlInfo * tinfo = (LocalPidlInfo *) DSA_GetItemPtr(m_hDsa, m_hDsaIndex);
if (!tinfo)
return E_FAIL;
LocalPidlInfo info = *tinfo;
TRACE("Returning next item at %d with parent %p and pidl { cb=%d }\n", m_hDsaIndex, info.parent, info.pidl->mkid.cb);
// FIXME: ILClone shouldn't be needed here! This should be causing leaks
if (rgelt) rgelt[i] = ILClone(info.pidl);
i++;
m_hDsaIndex++;
if (m_hDsaIndex == m_hDsaCount)
{
if (pceltFetched) *pceltFetched = i;
return (i == (int)celt) ? S_OK : S_FALSE;
}
}
if (pceltFetched) *pceltFetched = celt;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Skip(ULONG celt)
{
return Next(celt, NULL, NULL);
}
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Reset()
{
m_hDsaIndex = 0;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CEnumMergedFolder::Clone(
IEnumIDList **ppenum)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
//-----------------------------------------------------------------------------
// CMergedFolder
extern "C"
HRESULT WINAPI CMergedFolder_Constructor(REFIID riid, LPVOID *ppv)
{
return ShellObjectCreator<CMergedFolder>(riid, ppv);
}
CMergedFolder::CMergedFolder() :
m_UserLocal(NULL),
m_AllUSers(NULL),
m_EnumSource(NULL),
m_UserLocalPidl(NULL),
m_AllUsersPidl(NULL),
m_shellPidl(NULL)
{
}
CMergedFolder::~CMergedFolder()
{
if (m_UserLocalPidl) ILFree(m_UserLocalPidl);
if (m_AllUsersPidl) ILFree(m_AllUsersPidl);
}
// IAugmentedShellFolder2
HRESULT STDMETHODCALLTYPE CMergedFolder::AddNameSpace(LPGUID lpGuid, IShellFolder * psf, LPCITEMIDLIST pcidl, ULONG dwUnknown)
{
if (lpGuid)
{
TRACE("FIXME: No idea how to handle the GUID\n");
return E_NOTIMPL;
}
TRACE("AddNameSpace %p %p\n", m_UserLocal.p, m_AllUSers.p);
// FIXME: Use a DSA to store the list of merged namespaces, together with their related info (psf, pidl, ...)
// For now, assume only 2 will ever be used, and ignore all the other data.
if (!m_UserLocal)
{
m_UserLocal = psf;
m_UserLocalPidl = ILClone(pcidl);
return S_OK;
}
if (m_AllUSers)
return E_FAIL;
m_AllUSers = psf;
m_AllUsersPidl = ILClone(pcidl);
m_EnumSource = new CComObject<CEnumMergedFolder>();
return m_EnumSource->SetSources(m_UserLocal, m_AllUSers);
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetNameSpaceID(LPCITEMIDLIST pcidl, LPGUID lpGuid)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::QueryNameSpace(ULONG dwUnknown, LPGUID lpGuid, IShellFolder ** ppsf)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::EnumNameSpace(ULONG dwUnknown, PULONG lpUnknown)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::UnWrapIDList(LPCITEMIDLIST pcidl, LONG lUnknown, IShellFolder ** ppsf, LPITEMIDLIST * ppidl1, LPITEMIDLIST *ppidl2, LONG * lpUnknown)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
// IShellFolder
HRESULT STDMETHODCALLTYPE CMergedFolder::ParseDisplayName(
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
ULONG *pchEaten,
LPITEMIDLIST *ppidl,
ULONG *pdwAttributes)
{
HRESULT hr;
LocalPidlInfo info;
LPITEMIDLIST pidl;
if (!ppidl) return E_FAIL;
if (pchEaten) *pchEaten = 0;
if (pdwAttributes) *pdwAttributes = 0;
TRACE("ParseDisplayName name=%S\n", lpszDisplayName);
hr = m_UserLocal->ParseDisplayName(hwndOwner, pbcReserved, lpszDisplayName, pchEaten, &pidl, pdwAttributes);
if (SUCCEEDED(hr))
{
TRACE("ParseDisplayName result local\n");
hr = m_EnumSource->FindPidlInList(hwndOwner, pidl, &info);
if (SUCCEEDED(hr))
{
ILFree(pidl);
*ppidl = ILClone(info.pidl);
return hr;
}
}
hr = m_AllUSers->ParseDisplayName(hwndOwner, pbcReserved, lpszDisplayName, pchEaten, &pidl, pdwAttributes);
if (SUCCEEDED(hr))
{
TRACE("ParseDisplayName result common\n");
hr = m_EnumSource->FindPidlInList(hwndOwner, pidl, &info);
if (SUCCEEDED(hr))
{
ILFree(pidl);
*ppidl = ILClone(info.pidl);
return hr;
}
}
if (ppidl) *ppidl = NULL;
if (pchEaten) *pchEaten = 0;
if (pdwAttributes) *pdwAttributes = 0;
return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
}
HRESULT STDMETHODCALLTYPE CMergedFolder::EnumObjects(
HWND hwndOwner,
SHCONTF grfFlags,
IEnumIDList **ppenumIDList)
{
TRACE("EnumObjects\n");
HRESULT hr = m_EnumSource->QueryInterface(IID_PPV_ARG(IEnumIDList, ppenumIDList));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return m_EnumSource->Begin(hwndOwner, grfFlags);
}
HRESULT STDMETHODCALLTYPE CMergedFolder::BindToObject(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
void **ppvOut)
{
LocalPidlInfo info;
HRESULT hr;
hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
TRACE("BindToObject shared = %d\n", info.shared);
if (!info.shared)
return info.parent->BindToObject(info.pidl, pbcReserved, riid, ppvOut);
if (riid != IID_IShellFolder)
return E_FAIL;
CComPtr<IShellFolder> fld1;
CComPtr<IShellFolder> fld2;
hr = m_UserLocal->BindToObject(info.pidl, pbcReserved, IID_PPV_ARG(IShellFolder, &fld1));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_AllUSers->BindToObject(info.pidl, pbcReserved, IID_PPV_ARG(IShellFolder, &fld2));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComPtr<IAugmentedShellFolder> pasf;
hr = CMergedFolder_Constructor(IID_PPV_ARG(IAugmentedShellFolder, &pasf));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pasf->QueryInterface(riid, ppvOut);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pasf->AddNameSpace(NULL, fld1, info.pidl, 0xFF00);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pasf->AddNameSpace(NULL, fld2, info.pidl, 0x0000);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return hr;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::BindToStorage(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
void **ppvObj)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::CompareIDs(
LPARAM lParam,
LPCITEMIDLIST pidl1,
LPCITEMIDLIST pidl2)
{
TRACE("CompareIDs\n");
return m_UserLocal->CompareIDs(lParam, pidl1, pidl2);
}
HRESULT STDMETHODCALLTYPE CMergedFolder::CreateViewObject(
HWND hwndOwner,
REFIID riid,
void **ppvOut)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetAttributesOf(
UINT cidl,
LPCITEMIDLIST *apidl,
SFGAOF *rgfInOut)
{
LocalPidlInfo info;
HRESULT hr;
TRACE("GetAttributesOf\n");
for (int i = 0; i < (int)cidl; i++)
{
LPCITEMIDLIST pidl = apidl[i];
hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
pidl = info.pidl;
SFGAOF * pinOut1 = rgfInOut ? rgfInOut + i : NULL;
hr = info.parent->GetAttributesOf(1, &pidl, pinOut1);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
LPCITEMIDLIST *apidl,
REFIID riid,
UINT *prgfInOut,
void **ppvOut)
{
LocalPidlInfo info;
HRESULT hr;
TRACE("GetUIObjectOf\n");
for (int i = 0; i < (int)cidl; i++)
{
LPCITEMIDLIST pidl = apidl[i];
TRACE("Processing GetUIObjectOf item %d of %u...\n", i, cidl);
hr = m_EnumSource->FindPidlInList(hwndOwner, pidl, &info);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
pidl = info.pidl;
TRACE("FindPidlInList succeeded with parent %p and pidl { db=%d }\n", info.parent, info.pidl->mkid.cb);
UINT * pinOut1 = prgfInOut ? prgfInOut+i : NULL;
void** ppvOut1 = ppvOut ? ppvOut + i : NULL;
hr = info.parent->GetUIObjectOf(hwndOwner, 1, &pidl, riid, pinOut1, ppvOut1);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDisplayNameOf(
LPCITEMIDLIST pidl,
SHGDNF uFlags,
STRRET *lpName)
{
LocalPidlInfo info;
HRESULT hr;
TRACE("GetDisplayNameOf\n");
hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = info.parent->GetDisplayNameOf(info.pidl, uFlags, lpName);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::SetNameOf(
HWND hwnd,
LPCITEMIDLIST pidl,
LPCOLESTR lpszName,
SHGDNF uFlags,
LPITEMIDLIST *ppidlOut)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
// IPersist
HRESULT STDMETHODCALLTYPE CMergedFolder::GetClassID(CLSID *lpClassId)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
// IPersistFolder
HRESULT STDMETHODCALLTYPE CMergedFolder::Initialize(LPCITEMIDLIST pidl)
{
m_shellPidl = ILClone(pidl);
return S_OK;
}
// IPersistFolder2
HRESULT STDMETHODCALLTYPE CMergedFolder::GetCurFolder(LPITEMIDLIST * pidl)
{
if (pidl)
*pidl = m_shellPidl;
return S_OK;
}
// IShellFolder2
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultSearchGUID(
GUID *lpguid)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::EnumSearches(
IEnumExtraSearch **ppenum)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultColumn(
DWORD dwReserved,
ULONG *pSort,
ULONG *pDisplay)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDefaultColumnState(
UINT iColumn,
SHCOLSTATEF *pcsFlags)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDetailsEx(
LPCITEMIDLIST pidl,
const SHCOLUMNID *pscid,
VARIANT *pv)
{
LocalPidlInfo info;
HRESULT hr;
TRACE("GetDetailsEx\n");
hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComPtr<IShellFolder2> parent2;
hr = info.parent->QueryInterface(IID_PPV_ARG(IShellFolder2, &parent2));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = parent2->GetDetailsEx(info.pidl, pscid, pv);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::GetDetailsOf(
LPCITEMIDLIST pidl,
UINT iColumn,
SHELLDETAILS *psd)
{
LocalPidlInfo info;
HRESULT hr;
TRACE("GetDetailsOf\n");
hr = m_EnumSource->FindPidlInList(NULL, pidl, &info);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComPtr<IShellFolder2> parent2;
hr = info.parent->QueryInterface(IID_PPV_ARG(IShellFolder2, &parent2));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = parent2->GetDetailsOf(info.pidl, iColumn, psd);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CMergedFolder::MapColumnToSCID(
UINT iColumn,
SHCOLUMNID *pscid)
{
UNIMPLEMENTED;
return E_NOTIMPL;
}

View File

@ -0,0 +1,205 @@
/*
* Shell Menu Site
*
* Copyright 2014 David Quintana
*
* 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
*/
#pragma once
extern IID IID_IAugmentedShellFolder;
extern IID IID_IAugmentedShellFolder2;
extern CLSID CLSID_MergedFolder;
interface IAugmentedShellFolder : public IShellFolder
{
virtual HRESULT STDMETHODCALLTYPE AddNameSpace(LPGUID, IShellFolder *, LPCITEMIDLIST, ULONG) = 0;
virtual HRESULT STDMETHODCALLTYPE GetNameSpaceID(LPCITEMIDLIST, LPGUID) = 0;
virtual HRESULT STDMETHODCALLTYPE QueryNameSpace(ULONG, LPGUID, IShellFolder **) = 0;
virtual HRESULT STDMETHODCALLTYPE EnumNameSpace(ULONG, PULONG) = 0;
};
interface IAugmentedShellFolder2 : public IAugmentedShellFolder
{
virtual HRESULT STDMETHODCALLTYPE UnWrapIDList(LPCITEMIDLIST, LONG, IShellFolder **, LPITEMIDLIST *, LPITEMIDLIST *, LONG *) = 0;
};
/* No idea what QUERYNAMESPACEINFO struct contains -- the prototype comes from the PDB info
interface IAugmentedShellFolder3 : public IAugmentedShellFolder2
{
virtual HRESULT STDMETHODCALLTYPE QueryNameSpace2(ULONG, QUERYNAMESPACEINFO *) = 0;
};
*/
class CEnumMergedFolder;
class CMergedFolder :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public IShellFolder2,
//public IStorage,
public IAugmentedShellFolder2, // -- undocumented
//public IAugmentedShellFolder3, // -- undocumented
//public IShellService, // -- undocumented
//public ITranslateShellChangeNotify,// -- undocumented
public IPersistFolder2
//public IPersistPropertyBag,
//public IShellIconOverlay, // -- undocumented
//public ICompositeFolder, // -- undocumented
//public IItemNameLimits, // -- undocumented
{
private:
CComPtr<IShellFolder> m_UserLocal;
CComPtr<IShellFolder> m_AllUSers;
CComPtr<CEnumMergedFolder> m_EnumSource;
LPITEMIDLIST m_UserLocalPidl;
LPITEMIDLIST m_AllUsersPidl;
LPITEMIDLIST m_shellPidl;
public:
CMergedFolder();
virtual ~CMergedFolder();
HRESULT _SetSources(IShellFolder* userLocal, IShellFolder* allUSers);
DECLARE_NOT_AGGREGATABLE(CMergedFolder)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CMergedFolder)
COM_INTERFACE_ENTRY2_IID(IID_IShellFolder, IShellFolder, IShellFolder2)
COM_INTERFACE_ENTRY_IID(IID_IShellFolder2, IShellFolder2)
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder, IPersistFolder)
COM_INTERFACE_ENTRY_IID(IID_IPersistFolder2, IPersistFolder2)
COM_INTERFACE_ENTRY_IID(IID_IAugmentedShellFolder, IAugmentedShellFolder)
COM_INTERFACE_ENTRY_IID(IID_IAugmentedShellFolder2, IAugmentedShellFolder2)
//COM_INTERFACE_ENTRY_IID(IID_IAugmentedShellFolder3, IAugmentedShellFolder3)
//COM_INTERFACE_ENTRY_IID(IID_IStorage, IStorage)
//COM_INTERFACE_ENTRY_IID(IID_IShellService, IShellService)
//COM_INTERFACE_ENTRY_IID(IID_ITranslateShellChangeNotify,ITranslateShellChangeNotify)
//COM_INTERFACE_ENTRY_IID(IID_IPersistPropertyBag,IPersistPropertyBag)
//COM_INTERFACE_ENTRY_IID(IID_IShellIconOverlay, IShellIconOverlay)
//COM_INTERFACE_ENTRY_IID(IID_ICompositeFolder, ICompositeFolder)
//COM_INTERFACE_ENTRY_IID(IID_IItemNameLimits, IItemNameLimits)
END_COM_MAP()
// IShellFolder
virtual HRESULT STDMETHODCALLTYPE ParseDisplayName(
HWND hwndOwner,
LPBC pbcReserved,
LPOLESTR lpszDisplayName,
ULONG *pchEaten,
LPITEMIDLIST *ppidl,
ULONG *pdwAttributes);
virtual HRESULT STDMETHODCALLTYPE EnumObjects(
HWND hwndOwner,
SHCONTF grfFlags,
IEnumIDList **ppenumIDList);
virtual HRESULT STDMETHODCALLTYPE BindToObject(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
void **ppvOut);
virtual HRESULT STDMETHODCALLTYPE BindToStorage(
LPCITEMIDLIST pidl,
LPBC pbcReserved,
REFIID riid,
void **ppvObj);
virtual HRESULT STDMETHODCALLTYPE CompareIDs(
LPARAM lParam,
LPCITEMIDLIST pidl1,
LPCITEMIDLIST pidl2);
virtual HRESULT STDMETHODCALLTYPE CreateViewObject(
HWND hwndOwner,
REFIID riid,
void **ppvOut);
virtual HRESULT STDMETHODCALLTYPE GetAttributesOf(
UINT cidl,
LPCITEMIDLIST *apidl,
SFGAOF *rgfInOut);
virtual HRESULT STDMETHODCALLTYPE GetUIObjectOf(
HWND hwndOwner,
UINT cidl,
LPCITEMIDLIST *apidl,
REFIID riid,
UINT *prgfInOut,
void **ppvOut);
virtual HRESULT STDMETHODCALLTYPE GetDisplayNameOf(
LPCITEMIDLIST pidl,
SHGDNF uFlags,
STRRET *lpName);
virtual HRESULT STDMETHODCALLTYPE SetNameOf(
HWND hwnd,
LPCITEMIDLIST pidl,
LPCOLESTR lpszName,
SHGDNF uFlags,
LPITEMIDLIST *ppidlOut);
// IShellFolder2
virtual HRESULT STDMETHODCALLTYPE GetDefaultSearchGUID(
GUID *lpguid);
virtual HRESULT STDMETHODCALLTYPE EnumSearches(
IEnumExtraSearch **ppenum);
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumn(
DWORD dwReserved,
ULONG *pSort,
ULONG *pDisplay);
virtual HRESULT STDMETHODCALLTYPE GetDefaultColumnState(
UINT iColumn,
SHCOLSTATEF *pcsFlags);
virtual HRESULT STDMETHODCALLTYPE GetDetailsEx(
LPCITEMIDLIST pidl,
const SHCOLUMNID *pscid,
VARIANT *pv);
virtual HRESULT STDMETHODCALLTYPE GetDetailsOf(
LPCITEMIDLIST pidl,
UINT iColumn,
SHELLDETAILS *psd);
virtual HRESULT STDMETHODCALLTYPE MapColumnToSCID(
UINT iColumn,
SHCOLUMNID *pscid);
// IPersist
virtual HRESULT STDMETHODCALLTYPE GetClassID(CLSID *lpClassId);
// IPersistFolder
virtual HRESULT STDMETHODCALLTYPE Initialize(LPCITEMIDLIST pidl);
// IPersistFolder2
virtual HRESULT STDMETHODCALLTYPE GetCurFolder(LPITEMIDLIST * pidl);
// IAugmentedShellFolder2
virtual HRESULT STDMETHODCALLTYPE AddNameSpace(LPGUID lpGuid, IShellFolder * psf, LPCITEMIDLIST pcidl, ULONG dwUnknown);
virtual HRESULT STDMETHODCALLTYPE GetNameSpaceID(LPCITEMIDLIST pcidl, LPGUID lpGuid);
virtual HRESULT STDMETHODCALLTYPE QueryNameSpace(ULONG dwUnknown, LPGUID lpGuid, IShellFolder ** ppsf);
virtual HRESULT STDMETHODCALLTYPE EnumNameSpace(ULONG dwUnknown, PULONG lpUnknown);
virtual HRESULT STDMETHODCALLTYPE UnWrapIDList(LPCITEMIDLIST pcidl, LONG lUnknown, IShellFolder ** ppsf, LPITEMIDLIST * ppidl1, LPITEMIDLIST *ppidl2, LONG * lpUnknown);
};

View File

@ -0,0 +1,500 @@
/*
* 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"
#include "CMergedFolder.h"
WINE_DEFAULT_DEBUG_CHANNEL(CStartMenu);
// TODO: declare these GUIDs and interfaces in the right place (whatever that may be)
IID IID_IAugmentedShellFolder = { 0x91EA3F8C, 0xC99B, 0x11D0, { 0x98, 0x15, 0x00, 0xC0, 0x4F, 0xD9, 0x19, 0x72 } };
IID IID_IAugmentedShellFolder2 = { 0x8DB3B3F4, 0x6CFE, 0x11D1, { 0x8A, 0xE9, 0x00, 0xC0, 0x4F, 0xD9, 0x18, 0xD0 } };
CLSID CLSID_MergedFolder = { 0x26FDC864, 0xBE88, 0x46E7, { 0x92, 0x35, 0x03, 0x2D, 0x8E, 0xA5, 0x16, 0x2E } };
//#define TEST_TRACKPOPUPMENU_SUBMENUS
/* NOTE: The following constants *MUST 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_RUN 401
#define IDM_LOGOFF 402
#define IDM_UNDOCKCOMPUTER 410
#define IDM_TASKBARANDSTARTMENU 413
#define IDM_LASTSTARTMENU_SEPARATOR 450
#define IDM_DOCUMENTS 501
#define IDM_HELPANDSUPPORT 503
#define IDM_PROGRAMS 504
#define IDM_CONTROLPANEL 505
#define IDM_SHUTDOWN 506
#define IDM_FAVORITES 507
#define IDM_SETTINGS 508
#define IDM_PRINTERSANDFAXES 510
#define IDM_SEARCH 520
#define IDM_SYNCHRONIZE 553
#define IDM_NETWORKCONNECTIONS 557
#define IDM_DISCONNECT 5000
#define IDM_SECURITY 5001
/*
* 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
* 4. showing the programs start menu is SLOW compared to windows. this needs some investigation
*/
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;
CComPtr<IShellFolder> m_psfPrograms;
LPITEMIDLIST m_pidlPrograms;
HRESULT OnInitMenu()
{
HMENU hmenu;
HRESULT hr;
if (m_pTrayPriv.p)
return S_OK;
hr = IUnknown_GetSite(m_pDeskBar, IID_PPV_ARG(ITrayPriv, &m_pTrayPriv));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = IUnknown_GetWindow(m_pTrayPriv, &m_hwndTray);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_pTrayPriv->AppendMenuW(&hmenu);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = m_pShellMenu->SetMenu(hmenu, NULL, SMSET_BOTTOM);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return hr;
}
HRESULT OnGetInfo(LPSMDATA psmd, SMINFO *psminfo)
{
int iconIndex = 0;
switch (psmd->uId)
{
// Smaller "24x24" icons used for the start menu
// The bitmaps are still 32x32, but the image is centered
case IDM_FAVORITES: iconIndex = -322; break;
case IDM_SEARCH: iconIndex = -323; break;
case IDM_HELPANDSUPPORT: iconIndex = -324; break;
case IDM_LOGOFF: iconIndex = -325; break;
case IDM_PROGRAMS: iconIndex = -326; break;
case IDM_DOCUMENTS: iconIndex = -327; break;
case IDM_RUN: iconIndex = -328; break;
case IDM_SHUTDOWN: iconIndex = -329; break;
case IDM_SETTINGS: iconIndex = -330; break;
case IDM_CONTROLPANEL: iconIndex = -22; break;
case IDM_NETWORKCONNECTIONS: iconIndex = -257; break;
case IDM_PRINTERSANDFAXES: iconIndex = -138; break;
case IDM_TASKBARANDSTARTMENU: iconIndex = -40; break;
//case IDM_SECURITY: iconIndex = -21; break;
//case IDM_SYNCHRONIZE: iconIndex = -21; break;
//case IDM_DISCONNECT: iconIndex = -21; break;
//case IDM_UNDOCKCOMPUTER: iconIndex = -21; break;
default:
return S_FALSE;
}
if (iconIndex)
{
if ((psminfo->dwMask & SMIM_TYPE) != 0)
psminfo->dwType = SMIT_STRING;
if ((psminfo->dwMask & SMIM_ICON) != 0)
psminfo->iIcon = Shell_GetCachedImageIndex(L"shell32.dll", iconIndex, FALSE);
if ((psminfo->dwMask & SMIM_FLAGS) != 0)
psminfo->dwFlags |= SMIF_ICON;
#ifdef TEST_TRACKPOPUPMENU_SUBMENUS
if ((psminfo->dwMask & SMIM_FLAGS) != 0)
psminfo->dwFlags |= SMIF_TRACKPOPUP;
#endif
}
else
{
if ((psminfo->dwMask & SMIM_TYPE) != 0)
psminfo->dwType = SMIT_SEPARATOR;
}
return S_OK;
}
HRESULT OnGetSubMenu(LPSMDATA psmd, REFIID iid, void ** pv)
{
HRESULT hr;
int csidl = 0;
IShellMenu *pShellMenu;
#if USE_SYSTEM_MENUBAND
hr = CoCreateInstance(CLSID_MenuBand,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IShellMenu, &pShellMenu));
#else
hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &pShellMenu));
#endif
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pShellMenu->Initialize(this, 0, ANCESTORDEFAULT, SMINIT_VERTICAL);
switch (psmd->uId)
{
case IDM_PROGRAMS: csidl = CSIDL_PROGRAMS; break;
case IDM_FAVORITES: csidl = CSIDL_FAVORITES; break;
case IDM_DOCUMENTS: csidl = CSIDL_RECENT; break;
}
if (csidl)
{
IShellFolder *psfStartMenu;
if (csidl == CSIDL_PROGRAMS && m_psfPrograms)
{
psfStartMenu = m_psfPrograms;
}
else
{
LPITEMIDLIST pidlStartMenu;
IShellFolder *psfDestop;
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)
{
// HACK: Instead of running explorer.exe with the path, we should be using ShellExecute to "open" the path directly!
// Remove once ShellExecute can handle CLSID path components.
if (psmd->uId == IDM_CONTROLPANEL)
ShellExecuteW(NULL, NULL, L"explorer.exe", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}", NULL, SW_SHOWNORMAL);
else if (psmd->uId == IDM_NETWORKCONNECTIONS)
ShellExecuteW(NULL, NULL, L"explorer.exe", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}", NULL, SW_SHOWNORMAL);
else if (psmd->uId == IDM_PRINTERSANDFAXES)
ShellExecuteW(NULL, NULL, L"explorer.exe", L"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}", NULL, SW_SHOWNORMAL);
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 = pShellMenu;
m_pBandSite = pBandSite;
m_pDeskBar = pDeskBar;
}
~CShellMenuCallback()
{
}
HRESULT _SetProgramsFolder(IShellFolder * psf, LPITEMIDLIST pidl)
{
m_psfPrograms = psf;
m_pidlPrograms = pidl;
return S_OK;
}
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;
case 0x10000000: // _FilterPIDL from CMenuSFToolbar
if (psmd->psf->CompareIDs(0, psmd->pidlItem, m_pidlPrograms) == 0)
return S_FALSE;
return S_OK;
}
return S_FALSE;
}
};
HRESULT BindToDesktop(LPCITEMIDLIST pidl, IShellFolder ** ppsfResult)
{
HRESULT hr;
CComPtr<IShellFolder> psfDesktop;
*ppsfResult = NULL;
hr = SHGetDesktopFolder(&psfDesktop);
if (FAILED(hr))
return hr;
hr = psfDesktop->BindToObject(pidl, NULL, IID_PPV_ARG(IShellFolder, ppsfResult));
return hr;
}
static HRESULT GetStartMenuFolder(IShellFolder ** ppsfStartMenu)
{
HRESULT hr;
LPITEMIDLIST pidlUserStartMenu;
LPITEMIDLIST pidlCommonStartMenu;
CComPtr<IShellFolder> psfUserStartMenu;
CComPtr<IShellFolder> psfCommonStartMenu;
CComPtr<IAugmentedShellFolder> pasf;
*ppsfStartMenu = NULL;
hr = SHGetSpecialFolderLocation(NULL, CSIDL_STARTMENU, &pidlUserStartMenu);
if (FAILED(hr))
{
WARN("Failed to get the USER start menu folder. Trying to run with just the COMMON one.\n");
hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_STARTMENU, &pidlCommonStartMenu);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
TRACE("COMMON start menu obtained.\n");
hr = BindToDesktop(pidlCommonStartMenu, ppsfStartMenu);
ILFree(pidlCommonStartMenu);
return hr;
}
hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_STARTMENU, &pidlCommonStartMenu);
if (FAILED_UNEXPECTEDLY(hr))
{
WARN("Failed to get the COMMON start menu folder. Will use only the USER contents.\n");
hr = BindToDesktop(pidlUserStartMenu, ppsfStartMenu);
ILFree(pidlUserStartMenu);
return hr;
}
TRACE("Both COMMON and USER statr menu folders obtained, merging them...\n");
hr = BindToDesktop(pidlUserStartMenu, &psfUserStartMenu);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = BindToDesktop(pidlCommonStartMenu, &psfCommonStartMenu);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
#if !USE_SYSTEM_MERGED_FOLDERS
hr = CMergedFolder_Constructor(IID_PPV_ARG(IAugmentedShellFolder, &pasf));
#else
hr = CoCreateInstance(CLSID_MergedFolder, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IAugmentedShellFolder, &pasf));
#endif
if (FAILED_UNEXPECTEDLY(hr))
{
*ppsfStartMenu = psfUserStartMenu.Detach();
ILFree(pidlCommonStartMenu);
ILFree(pidlUserStartMenu);
return hr;
}
hr = pasf->AddNameSpace(NULL, psfUserStartMenu, pidlUserStartMenu, 0xFF00);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pasf->AddNameSpace(NULL, psfCommonStartMenu, pidlCommonStartMenu, 0);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pasf->QueryInterface(IID_PPV_ARG(IShellFolder, ppsfStartMenu));
pasf.Release();
ILFree(pidlCommonStartMenu);
ILFree(pidlUserStartMenu);
return hr;
}
extern "C"
HRESULT WINAPI
CStartMenu_Constructor(REFIID riid, void **ppv)
{
CComPtr<IShellMenu> pShellMenu;
CComPtr<IBandSite> pBandSite;
CComPtr<IDeskBar> pDeskBar;
HRESULT hr;
IShellFolder * psf;
LPITEMIDLIST pidlProgramsAbsolute;
LPITEMIDLIST pidlPrograms;
CComPtr<IShellFolder> psfPrograms;
#if USE_SYSTEM_MENUBAND
hr = CoCreateInstance(CLSID_MenuBand,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IShellMenu, &pShellMenu));
#else
hr = CMenuBand_Constructor(IID_PPV_ARG(IShellMenu, &pShellMenu));
#endif
if (FAILED_UNEXPECTEDLY(hr))
return hr;
#if USE_SYSTEM_MENUSITE
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_UNEXPECTEDLY(hr))
return hr;
#if USE_SYSTEM_MENUDESKBAR
hr = CoCreateInstance(CLSID_MenuDeskBar,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IDeskBar, &pDeskBar));
#else
hr = CMenuDeskBar_Constructor(IID_PPV_ARG(IDeskBar, &pDeskBar));
#endif
if (FAILED_UNEXPECTEDLY(hr))
return hr;
CComObject<CShellMenuCallback> *pCallback;
hr = CComObject<CShellMenuCallback>::CreateInstance(&pCallback);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
pCallback->AddRef(); // CreateInstance returns object with 0 ref count */
pCallback->Initialize(pShellMenu, pBandSite, pDeskBar);
pShellMenu->Initialize(pCallback, (UINT) -1, 0, SMINIT_TOPLEVEL | SMINIT_VERTICAL);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = GetStartMenuFolder(&psf);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &pidlProgramsAbsolute);
if (FAILED(hr))
{
WARN("USER Programs folder not found.");
hr = SHGetSpecialFolderLocation(NULL, CSIDL_COMMON_PROGRAMS, &pidlProgramsAbsolute);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
}
pidlPrograms = ILClone(ILFindLastID(pidlProgramsAbsolute));
ILFree(pidlProgramsAbsolute);
hr = psf->BindToObject(pidlPrograms, NULL, IID_PPV_ARG(IShellFolder, &psfPrograms));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pCallback->_SetProgramsFolder(psfPrograms, pidlPrograms);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pShellMenu->SetShellFolder(psf, NULL, NULL, 0);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pDeskBar->SetClient(pBandSite);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = pBandSite->AddBand(pShellMenu);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
return pDeskBar->QueryInterface(riid, ppv);
}

View File

@ -0,0 +1,408 @@
/*
* Shell DDE Handling
*
* Copyright 2004 Robert Shearman
*
* 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"
#include <ddeml.h>
#include <strsafe.h>
#include <shlwapi_undoc.h>
WINE_DEFAULT_DEBUG_CHANNEL(shelldde);
typedef DWORD(CALLBACK * pfnCommandHandler)(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS);
struct DDECommandHandler
{
WCHAR Command[32];
pfnCommandHandler Handler;
};
extern DDECommandHandler HandlerList [];
extern const int HandlerListLength;
/* DDE Instance ID */
static DWORD dwDDEInst;
/* String handles */
static HSZ hszProgmanTopic;
static HSZ hszProgmanService;
static HSZ hszShell;
static HSZ hszAppProperties;
static HSZ hszFolders;
static BOOL bInitialized;
static BOOL Dde_OnConnect(HSZ hszTopic, HSZ hszService)
{
WCHAR szTopic[MAX_PATH];
WCHAR szService[MAX_PATH];
DdeQueryStringW(dwDDEInst, hszTopic, szTopic, _countof(szTopic), CP_WINUNICODE);
DdeQueryStringW(dwDDEInst, hszService, szService, _countof(szService), CP_WINUNICODE);
DbgPrint("Dde_OnConnect: topic=%S, service=%S\n", szTopic, szService);
return TRUE;
}
static void Dde_OnConnectConfirm(HCONV hconv, HSZ hszTopic, HSZ hszService)
{
WCHAR szTopic[MAX_PATH];
WCHAR szService[MAX_PATH];
DdeQueryStringW(dwDDEInst, hszTopic, szTopic, _countof(szTopic), CP_WINUNICODE);
DdeQueryStringW(dwDDEInst, hszService, szService, _countof(szService), CP_WINUNICODE);
DbgPrint("Dde_OnConnectConfirm: hconv=%p, topic=%S, service=%S\n", hconv, szTopic, szService);
}
static BOOL Dde_OnWildConnect(HSZ hszTopic, HSZ hszService)
{
WCHAR szTopic[MAX_PATH];
WCHAR szService[MAX_PATH];
DdeQueryStringW(dwDDEInst, hszTopic, szTopic, _countof(szTopic), CP_WINUNICODE);
DdeQueryStringW(dwDDEInst, hszService, szService, _countof(szService), CP_WINUNICODE);
DbgPrint("Dde_OnWildConnect: topic=%S, service=%S\n", szTopic, szService);
return FALSE;
}
static HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic, HSZ hszItem)
{
WCHAR szTopic[MAX_PATH];
WCHAR szItem[MAX_PATH];
DdeQueryStringW(dwDDEInst, hszTopic, szTopic, _countof(szTopic), CP_WINUNICODE);
DdeQueryStringW(dwDDEInst, hszItem, szItem, _countof(szItem), CP_WINUNICODE);
DbgPrint("Dde_OnRequest: uFmt=%d, hconv=%p, topic=%S, item=%S\n", hconv, szTopic, szItem);
return NULL;
}
static LPITEMIDLIST _ILReadFromSharedMemory(PCWSTR strField)
{
LPITEMIDLIST ret = NULL;
// Ensure it really is an IDLIST-formatted parameter
// Format for IDLIST params: ":pid:shared"
if (*strField != L':')
return NULL;
HANDLE hData = (HANDLE) StrToIntW(strField + 1);
PWSTR strSecond = StrChrW(strField + 1, L':');
if (strSecond)
{
int pid = StrToIntW(strSecond + 1);
void* pvShared = SHLockShared(hData, pid);
if (pvShared)
{
ret = ILClone((LPCITEMIDLIST) pvShared);
SHUnlockShared(pvShared);
SHFreeShared(hData, pid);
}
}
return ret;
}
static DWORD Dde_OnExecute(HCONV hconv, HSZ hszTopic, HDDEDATA hdata)
{
WCHAR szTopic[MAX_PATH];
WCHAR szCommand[MAX_PATH];
WCHAR *pszCommand;
DdeQueryStringW(dwDDEInst, hszTopic, szTopic, _countof(szTopic), CP_WINUNICODE);
pszCommand = (WCHAR*) DdeAccessData(hdata, NULL);
if (!pszCommand)
return DDE_FNOTPROCESSED;
StringCchCopyW(szCommand, _countof(szCommand), pszCommand);
DdeUnaccessData(hdata);
DbgPrint("Dde_OnExecute: hconv=%p, topic=%S, command=%S\n", hconv, szTopic, pszCommand);
/*
[ViewFolder("%l", %I, %S)] -- Open a folder in standard mode
[ExploreFolder("%l", %I, %S)] -- Open a folder in "explore" mode (file tree is shown to the left by default)
[FindFolder("%l", %I)] -- Open a folder in "find" mode (search panel is shown to the left by default)
[ShellFile("%1","%1",%S)] -- Execute the contents of the specified .SCF file
Approximate grammar (Upper names define rules, <lower> names define terminals, single-quotes are literals):
Rules
Command = ('[' Function ']') | Function
Function = <identifier> '(' Parameters ')'
Parameters = (<quoted-string> (',' <idlist> (',' <number>)?)?)?
Terminals
<identifier> = [a-zA-Z]+
<quoted-string> = \"([^\"]|\\.)\"
<idlist> = \:[0-9]+\:[0-9]+
<number> = [0-9]+
*/
WCHAR Command[MAX_PATH] = L"";
WCHAR Path[MAX_PATH] = L"";
LPITEMIDLIST IdList = NULL;
INT UnknownParameter = 0;
// Simplified parsing (assumes the command will not be TOO broken):
PWSTR cmd = szCommand;
// 1. if starts with [, skip first char
if (*cmd == L'[')
cmd++;
if (*cmd == L']')
{
ERR("Empty command. Nothing to run.\n");
return DDE_FNOTPROCESSED;
}
// Read until first (, and take text before ( as command name
{
PWSTR cmdEnd = StrChrW(cmd, L'(');
if (!cmdEnd)
{
ERR("Could not find '('. Invalid command.\n");
return DDE_FNOTPROCESSED;
}
*cmdEnd = 0;
StringCchCopy(Command, _countof(Command), cmd);
cmd = cmdEnd + 1;
}
// Read first param after (, expecting quoted string
if (*cmd != L')')
{
// Copy unescaped string
PWSTR dst = Path;
BOOL isQuote = FALSE;
PWSTR arg = cmd;
while (*arg && (isQuote || *arg != L','))
{
if (*arg == L'"')
{
isQuote = !isQuote;
if (isQuote && arg != cmd) // do not copy the " at the beginning of the string
{
*(dst++) = L'"';
}
}
else
{
*(dst++) = *arg;
}
arg++;
}
cmd = arg + 1;
while (*cmd == L' ')
cmd++;
}
// Read second param, expecting an idlist in shared memory
if (*cmd != L')')
{
if (*cmd != ':')
{
ERR("Expected ':'. Invalid command.\n");
return DDE_FNOTPROCESSED;
}
PWSTR idlistEnd = StrChrW(cmd, L',');
if (!idlistEnd)
idlistEnd = StrChrW(cmd, L')');
if (!idlistEnd)
{
ERR("Expected ',' or ')'. Invalid command.\n");
return DDE_FNOTPROCESSED;
}
IdList = _ILReadFromSharedMemory(cmd);
cmd = idlistEnd + 1;
}
// Read third param, expecting an integer
if (*cmd != L')')
{
UnknownParameter = StrToIntW(cmd);
}
DbgPrint("Parse end: cmd=%S, S=%d, pidl=%p, path=%S\n", Command, UnknownParameter, IdList, Path);
// Find handler in list
for (int i = 0; i < HandlerListLength; i++)
{
DDECommandHandler & handler = HandlerList[i];
if (StrCmpW(handler.Command, Command) == 0)
{
return handler.Handler(Command, Path, IdList, UnknownParameter);
}
}
// No handler found
ERR("Unknown command %S\n", Command);
return DDE_FNOTPROCESSED;
}
static void Dde_OnDisconnect(HCONV hconv)
{
DbgPrint("Dde_OnDisconnect: hconv=%p\n", hconv);
}
static HDDEDATA CALLBACK DdeCallback(
UINT uType,
UINT uFmt,
HCONV hconv,
HSZ hsz1,
HSZ hsz2,
HDDEDATA hdata,
ULONG_PTR dwData1,
ULONG_PTR dwData2)
{
switch (uType)
{
case XTYP_CONNECT:
return (HDDEDATA) (DWORD_PTR) Dde_OnConnect(hsz1, hsz2);
case XTYP_CONNECT_CONFIRM:
Dde_OnConnectConfirm(hconv, hsz1, hsz2);
return NULL;
case XTYP_WILDCONNECT:
return (HDDEDATA) (DWORD_PTR) Dde_OnWildConnect(hsz1, hsz2);
case XTYP_REQUEST:
return Dde_OnRequest(uFmt, hconv, hsz1, hsz2);
case XTYP_EXECUTE:
return (HDDEDATA) (DWORD_PTR) Dde_OnExecute(hconv, hsz1, hdata);
case XTYP_DISCONNECT:
Dde_OnDisconnect(hconv);
return NULL;
case XTYP_REGISTER:
return NULL;
default:
DbgPrint("DdeCallback: unknown uType=%d\n", uType);
return NULL;
}
}
/*************************************************************************
* ShellDDEInit (SHELL32.@)
*
* Registers the Shell DDE services with the system so that applications
* can use them.
*
* PARAMS
* bInit [I] TRUE to initialize the services, FALSE to uninitialize.
*
* RETURNS
* Nothing.
*/
EXTERN_C void WINAPI ShellDDEInit(BOOL bInit)
{
DbgPrint("ShellDDEInit bInit = %s\n", bInit ? "TRUE" : "FALSE");
if (bInit && !bInitialized)
{
DdeInitializeW(&dwDDEInst, DdeCallback, CBF_FAIL_ADVISES | CBF_FAIL_POKES, 0);
hszProgmanTopic = DdeCreateStringHandleW(dwDDEInst, L"Progman", CP_WINUNICODE);
hszProgmanService = DdeCreateStringHandleW(dwDDEInst, L"Progman", CP_WINUNICODE);
hszShell = DdeCreateStringHandleW(dwDDEInst, L"Shell", CP_WINUNICODE);
hszAppProperties = DdeCreateStringHandleW(dwDDEInst, L"AppProperties", CP_WINUNICODE);
hszFolders = DdeCreateStringHandleW(dwDDEInst, L"Folders", CP_WINUNICODE);
if (hszProgmanTopic && hszProgmanService &&
hszShell && hszAppProperties && hszFolders &&
DdeNameService(dwDDEInst, hszFolders, 0, DNS_REGISTER) &&
DdeNameService(dwDDEInst, hszProgmanService, 0, DNS_REGISTER) &&
DdeNameService(dwDDEInst, hszShell, 0, DNS_REGISTER))
{
bInitialized = TRUE;
}
}
else if (!bInit && bInitialized)
{
/* unregister all services */
DdeNameService(dwDDEInst, 0, 0, DNS_UNREGISTER);
if (hszFolders)
DdeFreeStringHandle(dwDDEInst, hszFolders);
if (hszAppProperties)
DdeFreeStringHandle(dwDDEInst, hszAppProperties);
if (hszShell)
DdeFreeStringHandle(dwDDEInst, hszShell);
if (hszProgmanService)
DdeFreeStringHandle(dwDDEInst, hszProgmanService);
if (hszProgmanTopic)
DdeFreeStringHandle(dwDDEInst, hszProgmanTopic);
DdeUninitialize(dwDDEInst);
bInitialized = FALSE;
}
}
static DWORD CALLBACK DDE_OnViewFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
{
UNIMPLEMENTED;
return DDE_FACK;
}
static DWORD CALLBACK DDW_OnExploreFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
{
UNIMPLEMENTED;
return DDE_FACK;
}
static DWORD CALLBACK DDE_OnFindFolder(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
{
UNIMPLEMENTED;
return DDE_FNOTPROCESSED;
}
static DWORD CALLBACK DDE_OnShellFile(PWSTR strCommand, PWSTR strPath, LPITEMIDLIST pidl, INT unkS)
{
UNIMPLEMENTED;
return DDE_FNOTPROCESSED;
}
DDECommandHandler HandlerList [] = {
{ L"ViewFolder", DDE_OnViewFolder },
{ L"ExploreFolder", DDW_OnExploreFolder },
{ L"FindFolder", DDE_OnFindFolder },
{ L"ShellFile", DDE_OnShellFile }
};
const int HandlerListLength = _countof(HandlerList);

View File

@ -0,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;
}

View File

@ -0,0 +1,83 @@
#ifdef _MSC_VER
// Disabling spammy warnings when compiling with /W4 or /Wall
#pragma warning(disable:4100) // unreferenced formal parameter
#pragma warning(disable:4201) // nonstandard extension used
#pragma warning(disable:4265) // class has virtual functions, but destructor is not virtual
#pragma warning(disable:4365) // signed/unsigned mismatch
#pragma warning(disable:4514) // unreferenced inline function
#pragma warning(disable:4710) // function was not inlined
#pragma warning(disable:4820) // padding added
#pragma warning(disable:4946) // reinterpret_cast between related classes
// Disable some warnings in headers only
#pragma warning(push)
#pragma warning(disable:4244) // possible loss of data
#pragma warning(disable:4512) // assignment operator could not be gernerated
#endif
#define USE_SYSTEM_MENUDESKBAR 0
#define USE_SYSTEM_MENUSITE 0
#define USE_SYSTEM_MENUBAND 0
#define WRAP_MENUDESKBAR 0
#define WRAP_MENUSITE 0
#define WRAP_MENUBAND 0
#define WRAP_TRAYPRIV 0
#define MERGE_FOLDERS 1
#include <stdio.h>
#include <tchar.h>
#define WIN32_NO_STATUS
#define _INC_WINDOWS
#define COM_NO_WINDOWS_H
#define COBJMACROS
//#define DEBUG_CCOMOBJECT
#define DEBUG_CCOMOBJECT_CREATION 1
#define DEBUG_CCOMOBJECT_DESTRUCTION 1
#define DEBUG_CCOMOBJECT_REFCOUNTING 1
#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 <atlwin.h>
#include <undocshell.h>
#include <rosctrls.h>
#include <wine/debug.h>
#if _MSC_VER
// Restore warnings
#pragma warning(pop)
#endif
#define shell32_hInstance 0
extern "C" HRESULT WINAPI CStartMenu_Constructor(REFIID riid, void **ppv);
extern "C" HRESULT WINAPI CMenuDeskBar_Constructor(REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CMenuSite_Constructor(REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CMenuBand_Constructor(REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CMenuDeskBar_Wrapper(IDeskBar * db, REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CMenuSite_Wrapper(IBandSite * bs, REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CMenuBand_Wrapper(IShellMenu * sm, REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CMergedFolder_Constructor(REFIID riid, LPVOID *ppv);
extern "C" HRESULT WINAPI CStartMenuSite_Wrapper(ITrayPriv * trayPriv, REFIID riid, LPVOID *ppv);

View File

@ -0,0 +1,6 @@
@ stdcall CStartMenu_Constructor(ptr ptr)
@ stdcall CMenuDeskBar_Constructor(ptr ptr);
@ stdcall CMenuSite_Constructor(ptr ptr);
@ stdcall CMenuBand_Constructor(ptr ptr);
@ stdcall CMergedFolder_Constructor(ptr ptr);
@ stdcall ShellDDEInit(long);

View File

@ -109,6 +109,7 @@ HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Setup",,0x00000012
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Setup","DriverCachePath",0x00020002,"%SystemRoot%\Driver Cache"
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\SharedDlls",,0x00000012
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\Shell Extensions",,0x00000012
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\ShellServiceObjectDelayLoad",,0x00000012
; FIXME - usetup doesn't handle extra paths
HKLM,"SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce","",0x00000000,"cmd /c md ""%programfiles%\Internet Explorer\"" && move %windir%\iexplore.exe ""%programfiles%\Internet Explorer\"" && ""%programfiles%\Internet Explorer\iexplore.exe"" /RegServer"

View File

@ -4,3 +4,4 @@ add_subdirectory(deskmon)
add_subdirectory(devcpux)
add_subdirectory(fontext)
add_subdirectory(slayer)
add_subdirectory(stobject)

View File

@ -0,0 +1,40 @@
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}/lib/atl
${REACTOS_SOURCE_DIR})
spec2def(stobject.dll stobject.spec)
add_library(stobject SHARED
csystray.cpp
stobject.cpp
stobject.rc
volume.cpp
${CMAKE_CURRENT_BINARY_DIR}/stobject.def)
set_module_type(stobject win32dll UNICODE)
target_link_libraries(stobject uuid wine atlnew)
add_importlibs(stobject
advapi32
winmm
ole32
shlwapi
shell32
comctl32
msvcrt
gdi32
user32
kernel32
ntdll)
add_cd_file(TARGET stobject DESTINATION reactos/system32 FOR all)

View File

@ -0,0 +1,212 @@
/*
* PROJECT: ReactOS system libraries
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\stobject\csystray.cpp
* PURPOSE: Systray shell service object implementation
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/
#include "precomp.h"
WINE_DEFAULT_DEBUG_CHANNEL(stobject);
SysTrayIconHandlers_t g_IconHandlers [] = {
{ Volume_Init, Volume_Shutdown, Volume_Update, Volume_Message }
};
const int g_NumIcons = _countof(g_IconHandlers);
const GUID CLSID_SysTray = { 0x35CEC8A3, 0x2BE6, 0x11D2, { 0x87, 0x73, 0x92, 0xE2, 0x20, 0x52, 0x41, 0x53 } };
CSysTray::CSysTray() {}
CSysTray::~CSysTray() {}
HRESULT CSysTray::InitIcons()
{
TRACE("Initializing Notification icons...\n");
for (int i = 0; i < g_NumIcons; i++)
{
HRESULT hr = g_IconHandlers[i].pfnInit(this);
if (FAILED(hr))
return hr;
}
return S_OK;
}
HRESULT CSysTray::ShutdownIcons()
{
TRACE("Shutting down Notification icons...\n");
for (int i = 0; i < g_NumIcons; i++)
{
HRESULT hr = g_IconHandlers[i].pfnShutdown(this);
if (FAILED(hr))
return hr;
}
return S_OK;
}
HRESULT CSysTray::UpdateIcons()
{
TRACE("Updating Notification icons...\n");
for (int i = 0; i < g_NumIcons; i++)
{
HRESULT hr = g_IconHandlers[i].pfnUpdate(this);
if (FAILED(hr))
return hr;
}
return S_OK;
}
HRESULT CSysTray::ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
{
for (int i = 0; i < g_NumIcons; i++)
{
HRESULT hr = g_IconHandlers[i].pfnMessage(this, uMsg, wParam, lParam);
if (FAILED(hr))
return hr;
if (hr != S_FALSE)
return hr;
}
return S_OK;
}
HRESULT CSysTray::NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip)
{
NOTIFYICONDATA nim = { 0 };
TRACE("NotifyIcon code=%d, uId=%d, hIcon=%p, szTip=%S\n", code, uId, hIcon, szTip);
nim.cbSize = sizeof(NOTIFYICONDATA);
nim.uFlags = NIF_MESSAGE | NIF_ICON | NIF_STATE | NIF_TIP;
nim.hIcon = hIcon;
nim.uID = uId;
nim.uCallbackMessage = uId;
nim.dwState = 0;
nim.dwStateMask = 0;
nim.hWnd = m_hWnd;
nim.uVersion = NOTIFYICON_VERSION;
if (szTip)
StringCchCopy(nim.szTip, _countof(nim.szTip), szTip);
else
nim.szTip[0] = 0;
BOOL ret = Shell_NotifyIcon(code, &nim);
return ret ? S_OK : E_FAIL;
}
DWORD WINAPI CSysTray::s_SysTrayThreadProc(PVOID param)
{
CSysTray * st = (CSysTray*) param;
return st->SysTrayThreadProc();
}
HRESULT CSysTray::SysTrayMessageLoop()
{
BOOL ret;
MSG msg;
while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0)
{
if (ret < 0)
break;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return S_OK;
}
HRESULT CSysTray::SysTrayThreadProc()
{
WCHAR strFileName[MAX_PATH];
GetModuleFileNameW(g_hInstance, strFileName, MAX_PATH);
HMODULE hLib = LoadLibraryW(strFileName);
CoInitializeEx(NULL, COINIT_DISABLE_OLE1DDE | COINIT_APARTMENTTHREADED);
Create(NULL);
HRESULT ret = SysTrayMessageLoop();
CoUninitialize();
FreeLibraryAndExitThread(hLib, ret);
}
HRESULT CSysTray::CreateSysTrayThread()
{
TRACE("CSysTray Init TODO: Initialize tray icon handlers.\n");
HANDLE hThread = CreateThread(NULL, 0, s_SysTrayThreadProc, this, 0, NULL);
CloseHandle(hThread);
return S_OK;
}
HRESULT CSysTray::DestroySysTrayWindow()
{
DestroyWindow();
hwndSysTray = NULL;
return S_OK;
}
// *** IOleCommandTarget methods ***
HRESULT STDMETHODCALLTYPE CSysTray::QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText)
{
UNIMPLEMENTED;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CSysTray::Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut)
{
if (!IsEqualGUID(*pguidCmdGroup, CGID_ShellServiceObject))
return E_FAIL;
switch (nCmdID)
{
case OLECMDID_NEW: // init
return CreateSysTrayThread();
case OLECMDID_SAVE: // shutdown
return DestroySysTrayWindow();
}
return S_OK;
}
BOOL CSysTray::ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID)
{
HRESULT hr;
if (hWnd != m_hWnd)
return FALSE;
switch (uMsg)
{
case WM_CREATE:
InitIcons();
SetTimer(1, 2000, NULL);
return TRUE;
case WM_TIMER:
UpdateIcons();
return TRUE;
case WM_DESTROY:
KillTimer(1);
ShutdownIcons();
return TRUE;
}
TRACE("SysTray message received %u (%08p %08p)\n", uMsg, wParam, lParam);
hr = ProcessIconMessage(uMsg, wParam, lParam);
if (FAILED(hr))
return FALSE;
if (hr == S_FALSE)
return FALSE;
return TRUE;
}

View File

@ -0,0 +1,66 @@
/*
* PROJECT: ReactOS system libraries
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\stobject\stobject.cpp
* PURPOSE: Systray shell service object
* PROGRAMMERS: Robert Naumann
David Quintana <gigaherz@gmail.com>
*/
#pragma once
extern const GUID CLSID_SysTray;
typedef CWinTraits <
WS_POPUP | WS_DLGFRAME | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_PALETTEWINDOW
> CMessageWndClass;
class CSysTray :
public CComCoClass<CSysTray, &CLSID_SysTray>,
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl<CSysTray, CWindow, CMessageWndClass>,
public IOleCommandTarget
{
// TODO: keep icon handlers here
HWND hwndSysTray;
static DWORD WINAPI s_SysTrayThreadProc(PVOID param);
HRESULT SysTrayMessageLoop();
HRESULT SysTrayThreadProc();
HRESULT CreateSysTrayThread();
HRESULT DestroySysTrayWindow();
HRESULT InitIcons();
HRESULT ShutdownIcons();
HRESULT UpdateIcons();
HRESULT ProcessIconMessage(UINT uMsg, WPARAM wParam, LPARAM lParam);
public:
HRESULT NotifyIcon(INT code, UINT uId, HICON hIcon, LPCWSTR szTip);
HWND GetHWnd() { return m_hWnd; }
protected:
BOOL ProcessWindowMessage(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT &lResult, DWORD dwMsgMapID = 0);
public:
CSysTray();
virtual ~CSysTray();
// *** IOleCommandTarget methods ***
virtual HRESULT STDMETHODCALLTYPE QueryStatus(const GUID *pguidCmdGroup, ULONG cCmds, OLECMD prgCmds [], OLECMDTEXT *pCmdText);
virtual HRESULT STDMETHODCALLTYPE Exec(const GUID *pguidCmdGroup, DWORD nCmdID, DWORD nCmdexecopt, VARIANT *pvaIn, VARIANT *pvaOut);
DECLARE_WND_CLASS_EX(_T("SystemTray_Main"), CS_GLOBALCLASS, COLOR_3DFACE)
DECLARE_REGISTRY_RESOURCEID(IDR_SYSTRAY)
DECLARE_NOT_AGGREGATABLE(CSysTray)
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_COM_MAP(CSysTray)
COM_INTERFACE_ENTRY_IID(IID_IOleCommandTarget, IOleCommandTarget)
END_COM_MAP()
};

View File

@ -0,0 +1,51 @@
LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL
IDD_POWER_METER DIALOGEX 0, 0, 252, 218
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_CONTEXTHELP
CAPTION "Energieanzeige"
FONT 8, "Ms Shell Dlg"
BEGIN
CONTROL "Energiestand", 1001, BUTTON, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 9, 20, 234, 189
CONTROL "Symbol in der &Taskleiste anzeigen", 1002, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 6, 6, 123, 10
CONTROL "&Details für jede Batterie anzeigen", 1002, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 129, 6, 123, 10
CONTROL "", 1000, STATIC, SS_LEFT | WS_CHILD | WS_GROUP, 11, 29, 229, 178
END
STRINGTABLE
BEGIN
//Power related strings
IDS_PWR_PROPERTIES "&Energieverwaltungseigenschaften einstellen"
IDS_PWR_METER "Batterieanzeige ö&ffnen"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
IDS_PWR_PERCENT_REMAINING "%1!u!%% verbleibend"
IDS_PWR_CHARGING " (wird aufgeladen)"
IDS_PWR_UNKNOWN_REMAINING "Unbekannt verbleibend"
IDS_PWR_AC "Mit Wechselstrom"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! Stunden (%3!u!%%) verbleibend"
IDS_PWR_MINUTES_REMAINING "%1!u! Min. (%2!u!%%) verbleibend"
//Hotplug related strings
IDS_HOTPLUG_REMOVE_1 "Hardware sicher entfernen"
IDS_HOTPLUG_REMOVE_2 "&Hardware sicher entfernen"
IDS_HOTPLUG_REMOVE_3 "%s entfernen"
IDS_HOTPLUG_RUN "shell32.dll,Control_RunDLL hotplug.dll"
IDS_HOTPLUG_COMMA ", "
IDS_HOTPLUG_DRIVE " - Laufwerk (%s)"
IDS_HOTPLUG_DRIVES " - Laufwerke (%s)"
IDS_HOTPLUG_A "A:"
IDS_HOTPLUG_REQUIERES "Diese Hardware erfordert \"Sicheres Entfernen\""
IDS_HOTPLUG_CLICK "Klicken Sie auf dieses Symbol, und wählen Sie die zu entfernende Hardware, bevor Sie diese Hardware entfernen."
//Volume related strings
IDS_VOL_VOLUME "Lautstärke"
IDS_VOL_ADJUST "&Audioeigenschaften einstellen"
IDS_VOL_OPEN "&Lautstärkeregelung öffnen"
IDS_VOL_RUN "SNDVOL32.EXE"
IDS_VOL_MUTED "Lautstärke (ausgeschaltet)"
//Keyboard-Mouse related strings
IDS_KEYS_STICKY "Einrastfunktion"
IDS_KEYS_MOUSE "Tastaturmaus"
IDS_KEYS_FILTER "Anschlagverzögerung"
END

View File

@ -0,0 +1,52 @@
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
IDD_POWER_METER DIALOGEX 0, 0, 252, 218
STYLE DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_CONTEXTHELP
CAPTION "Power Meter"
FONT 8, "MS Shell Dlg"
BEGIN
CONTROL "Power status", 1001, BUTTON, BS_GROUPBOX | WS_CHILD | WS_VISIBLE, 9, 20, 234, 189
CONTROL "&Always show icon on the taskbar.", 1002, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 6, 6, 120, 10
CONTROL "Show details for each &battery.", 1003, BUTTON, BS_AUTOCHECKBOX | WS_CHILD | WS_VISIBLE | WS_GROUP | WS_TABSTOP, 135, 6, 120, 8
CONTROL "", 1000, STATIC, SS_LEFT | WS_CHILD | WS_GROUP, 11, 29, 229, 178
END
STRINGTABLE
BEGIN
//Power related strings
IDS_PWR_PROPERTIES "&Adjust Power Properties"
IDS_PWR_METER "&Open Power Meter"
IDS_PWR_RUN "shell32.dll,Control_RunDLL PowerCfg.cpl"
IDS_PWR_PERCENT_REMAINING "%1!u!%% remaining"
IDS_PWR_CHARGING " (charging)"
IDS_PWR_UNKNOWN_REMAINING "Unknown remaining"
IDS_PWR_AC "On AC power"
IDS_PWR_HOURS_REMAINING "%1!u!:%2!02u! hours (%3!u!%%) remaining"
IDS_PWR_MINUTES_REMAINING "%1!u! min (%2!u!%%) remaining"
//Hotplug related strings
IDS_HOTPLUG_REMOVE_1 "Safely Remove Hardware"
IDS_HOTPLUG_REMOVE_2 "&Safely Remove Hardware"
IDS_HOTPLUG_REMOVE_3 "Safely remove %s"
IDS_HOTPLUG_RUN "shell32.dll,Control_RunDLL hotplug.dll"
IDS_HOTPLUG_COMMA ", "
IDS_HOTPLUG_DRIVE " - Drive(%s)"
IDS_HOTPLUG_DRIVES " - Drives(%s)"
IDS_HOTPLUG_A "A:"
IDS_HOTPLUG_REQUIERES "This hardware requires \"Safe Removal\""
IDS_HOTPLUG_CLICK "Before removing this hardware, click on this icon and select the hardware you want to remove."
//Volume related strings
IDS_VOL_VOLUME "Volume"
IDS_VOL_ADJUST "&Adjust Audio Properties"
IDS_VOL_OPEN "&Open Volume Control"
IDS_VOL_RUN "SNDVOL32.EXE"
IDS_VOL_MUTED "Volume (muted)"
//Keyboard-Mouse related strings
IDS_KEYS_STICKY "StickyKeys"
IDS_KEYS_MOUSE "MouseKeys"
IDS_KEYS_FILTER "FilterKeys"
END

View File

@ -0,0 +1,107 @@
#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 <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 <shellapi.h>
#include <wine/debug.h>
#include <wine/unicode.h>
#include "resource.h"
extern HINSTANCE g_hInstance;
#define ID_ICON_VOLUME (WM_APP + 0x4CB)
#include "csystray.h"
typedef HRESULT(STDMETHODCALLTYPE * PFNSTINIT) (_In_ CSysTray * pSysTray);
typedef HRESULT(STDMETHODCALLTYPE * PFNSTSHUTDOWN) (_In_ CSysTray * pSysTray);
typedef HRESULT(STDMETHODCALLTYPE * PFNSTUPDATE) (_In_ CSysTray * pSysTray);
typedef HRESULT(STDMETHODCALLTYPE * PFNSTMESSAGE) (_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam);
struct SysTrayIconHandlers_t
{
PFNSTINIT pfnInit;
PFNSTSHUTDOWN pfnShutdown;
PFNSTUPDATE pfnUpdate;
PFNSTMESSAGE pfnMessage;
};
extern SysTrayIconHandlers_t g_IconHandlers[];
extern const int g_NumIcons;
/* --------------- Icon callbacks ------------------------------ */
extern HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray);
extern HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam);
/* --------------- Utils ------------------------------ */
static __inline ULONG
Win32DbgPrint(const char *filename, int line, const char *lpFormat, ...)
{
char szMsg[512];
char *szMsgStart;
const char *fname;
va_list vl;
ULONG uRet;
fname = strrchr(filename, '\\');
if (fname == NULL)
{
fname = strrchr(filename, '/');
}
if (fname == NULL)
fname = filename;
else
fname++;
szMsgStart = szMsg + sprintf(szMsg, "[%10lu] %s:%d: ", GetTickCount(), fname, line);
va_start(vl, lpFormat);
uRet = (ULONG) vsprintf(szMsgStart, lpFormat, vl);
va_end(vl);
OutputDebugStringA(szMsg);
return uRet;
}
#define DbgPrint(fmt, ...) \
Win32DbgPrint(__FILE__, __LINE__, fmt, ##__VA_ARGS__)
#if 1
#define FAILED_UNEXPECTEDLY(hr) (FAILED(hr) && (DbgPrint("Unexpected failure %08x.\n", hr), TRUE))
#else
#define FAILED_UNEXPECTEDLY(hr) FAILED(hr)
#endif

View File

@ -0,0 +1,42 @@
#pragma once
#define IDD_POWER_METER 100
#define IDS_PWR_PROPERTIES 152
#define IDS_PWR_METER 153
#define IDS_PWR_RUN 157
#define IDS_PWR_PERCENT_REMAINING 158
#define IDS_PWR_CHARGING 159
#define IDS_PWR_UNKNOWN_REMAINING 160
#define IDS_PWR_AC 161
#define IDS_PWR_HOURS_REMAINING 162
#define IDS_PWR_MINUTES_REMAINING 163
#define IDI_BATTERY 200
#define IDI_EXTRACT 210
#define IDS_HOTPLUG_REMOVE_1 211
#define IDS_HOTPLUG_REMOVE_2 215
#define IDS_HOTPLUG_REMOVE_3 216
#define IDS_HOTPLUG_RUN 217
#define IDS_HOTPLUG_COMMA 218
#define IDS_HOTPLUG_DRIVE 219
#define IDS_HOTPLUG_DRIVES 220
#define IDS_HOTPLUG_A 221
#define IDS_HOTPLUG_REQUIERES 222
#define IDS_HOTPLUG_CLICK 223
#define IDI_VOLUME 230
#define IDI_VOLMUTE 231
#define IDS_VOL_VOLUME 252
#define IDS_VOL_ADJUST 255
#define IDS_VOL_OPEN 256
#define IDS_VOL_RUN 257
#define IDS_VOL_MUTED 258
#define IDS_KEYS_STICKY 330
#define IDS_KEYS_MOUSE 331
#define IDS_KEYS_FILTER 332
#define IDR_SYSTRAY 11001

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@ -0,0 +1,32 @@
HKCR
{
NoRemove CLSID
{
ForceRemove {35CEC8A3-2BE6-11D2-8773-92E220524153} = s 'SysTray'
{
InprocServer32 = s '%MODULE%'
{
val ThreadingModel = s 'Both'
}
}
}
}
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove ShellServiceObjectDelayLoad
{
val SysTray = s '{35CEC8A3-2BE6-11D2-8773-92E220524153}'
}
}
}
}
}
}

View File

@ -0,0 +1,75 @@
/*
* PROJECT: ReactOS system libraries
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\stobject\stobject.cpp
* PURPOSE: COM registration services for STobject.dll
* PROGRAMMERS: Robert Naumann
David Quintana <gigaherz@gmail.com>
*/
#include "precomp.h"
#include <olectl.h>
#include <atlwin.h>
WINE_DEFAULT_DEBUG_CHANNEL(stobject);
BEGIN_OBJECT_MAP(ObjectMap)
OBJECT_ENTRY(CLSID_SysTray, CSysTray)
END_OBJECT_MAP()
HINSTANCE g_hInstance;
CComModule g_Module;
void *operator new (size_t, void *buf)
{
return buf;
}
STDAPI_(BOOL)
DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
{
if (fdwReason == DLL_PROCESS_ATTACH)
{
g_hInstance = hinstDLL;
DisableThreadLibraryCalls(g_hInstance);
/* HACK - the global constructors don't run, so I placement new them here */
new (&g_Module) CComModule;
new (&_AtlWinModule) CAtlWinModule;
new (&_AtlBaseModule) CAtlBaseModule;
new (&_AtlComModule) CAtlComModule;
g_Module.Init(ObjectMap, g_hInstance, NULL);
}
else if (fdwReason == DLL_PROCESS_DETACH)
{
g_hInstance = NULL;
g_Module.Term();
}
return TRUE;
}
STDAPI
DllRegisterServer(void)
{
return g_Module.DllRegisterServer(FALSE);
}
STDAPI
DllUnregisterServer(void)
{
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();
}

View File

@ -0,0 +1,26 @@
#include <windef.h>
#include <winuser.h>
#include <commctrl.h>
#include "resource.h"
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
IDI_BATTERY ICON "resources/1.ico"
IDI_EXTRACT ICON "resources/2.ico"
IDI_VOLUME ICON "resources/3.ico"
IDI_VOLMUTE ICON "resources/4.ico"
IDR_SYSTRAY REGISTRY "resources/rgs/systray.rgs"
/* UTF-8 */
#pragma code_page(65001)
#if 0
#ifdef LANGUAGE_DE_DE
#include "lang/de-DE.rc"
#endif
#ifdef LANGUAGE_EN_US
#include "lang/en-US.rc"
#endif
#endif

View File

@ -0,0 +1,4 @@
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
@ stdcall -private DllUnregisterServer()

View File

@ -0,0 +1,233 @@
/*
* PROJECT: ReactOS system libraries
* LICENSE: GPL - See COPYING in the top level directory
* FILE: dll\win32\stobject\volume.cpp
* PURPOSE: Volume notification icon handler
* PROGRAMMERS: David Quintana <gigaherz@gmail.com>
*/
#include "precomp.h"
#include <mmsystem.h>
#include <mmddk.h>
WINE_DEFAULT_DEBUG_CHANNEL(stobject);
HICON g_hIconVolume;
HICON g_hIconMute;
HMIXER g_hMixer;
UINT g_mixerId;
DWORD g_mixerLineID;
DWORD g_muteControlID;
UINT g_mmDeviceChange;
BOOL g_IsMute = FALSE;
static HRESULT __stdcall Volume_FindMixerControl(CSysTray * pSysTray)
{
MMRESULT result;
UINT mixerId = 0;
DWORD waveOutId = 0;
DWORD param2 = 0;
TRACE("Volume_FindDefaultMixerID\n");
result = waveOutMessage((HWAVEOUT) WAVE_MAPPER, DRVM_MAPPER_PREFERRED_GET, (DWORD_PTR) &waveOutId, (DWORD_PTR) &param2);
if (result)
return E_FAIL;
if (waveOutId == (DWORD)-1)
{
TRACE("WARNING: waveOut has no default device, trying with first available device...\n", waveOutId);
mixerId = 0;
}
else
{
TRACE("waveOut default device is %d\n", waveOutId);
result = mixerGetID((HMIXEROBJ) waveOutId, &mixerId, MIXER_OBJECTF_WAVEOUT);
if (result)
return E_FAIL;
TRACE("mixerId for waveOut default device is %d\n", mixerId);
}
g_mixerId = mixerId;
return S_OK;
MIXERCAPS mixerCaps;
MIXERLINE mixerLine;
MIXERCONTROL mixerControl;
MIXERLINECONTROLS mixerLineControls;
g_mixerLineID = -1;
g_muteControlID = -1;
if (mixerGetDevCapsW(g_mixerId, &mixerCaps, sizeof(mixerCaps)))
return E_FAIL;
if (mixerCaps.cDestinations == 0)
return S_FALSE;
TRACE("mixerCaps.cDestinations %d\n", mixerCaps.cDestinations);
DWORD idx;
for (idx = 0; idx < mixerCaps.cDestinations; idx++)
{
mixerLine.cbStruct = sizeof(mixerLine);
mixerLine.dwDestination = idx;
if (!mixerGetLineInfoW((HMIXEROBJ) g_mixerId, &mixerLine, 0))
{
if (mixerLine.dwComponentType >= MIXERLINE_COMPONENTTYPE_DST_SPEAKERS &&
mixerLine.dwComponentType <= MIXERLINE_COMPONENTTYPE_DST_HEADPHONES)
break;
TRACE("Destination %d was not speakers or headphones.\n");
}
}
if (idx >= mixerCaps.cDestinations)
return E_FAIL;
TRACE("Valid destination %d found.\n");
g_mixerLineID = mixerLine.dwLineID;
mixerLineControls.cbStruct = sizeof(mixerLineControls);
mixerLineControls.dwLineID = mixerLine.dwLineID;
mixerLineControls.cControls = 1;
mixerLineControls.dwControlType = MIXERCONTROL_CONTROLTYPE_MUTE;
mixerLineControls.pamxctrl = &mixerControl;
mixerLineControls.cbmxctrl = sizeof(mixerControl);
if (mixerGetLineControlsW((HMIXEROBJ) g_mixerId, &mixerLineControls, MIXER_GETLINECONTROLSF_ONEBYTYPE))
return E_FAIL;
TRACE("Found control id %d for mute: %d\n", mixerControl.dwControlID);
g_muteControlID = mixerControl.dwControlID;
return S_OK;
}
HRESULT Volume_IsMute()
{
#if 0
MIXERCONTROLDETAILS mixerControlDetails;
if (g_mixerId != (UINT)-1 && g_muteControlID != (DWORD)-1)
{
BOOL detailsResult = 0;
mixerControlDetails.cbStruct = sizeof(mixerControlDetails);
mixerControlDetails.hwndOwner = 0;
mixerControlDetails.dwControlID = g_muteControlID;
mixerControlDetails.cChannels = 1;
mixerControlDetails.paDetails = &detailsResult;
mixerControlDetails.cbDetails = sizeof(detailsResult);
if (mixerGetControlDetailsW((HMIXEROBJ) g_mixerId, &mixerControlDetails, 0))
return E_FAIL;
TRACE("Obtained mute status %d\n", detailsResult);
g_IsMute = detailsResult != 0;
}
#endif
return S_OK;
}
HRESULT STDMETHODCALLTYPE Volume_Init(_In_ CSysTray * pSysTray)
{
HRESULT hr;
TRACE("Volume_Init\n");
if (!g_hMixer)
{
hr = Volume_FindMixerControl(pSysTray);
if (FAILED(hr))
return hr;
g_mmDeviceChange = RegisterWindowMessageW(L"winmm_devicechange");
}
g_hIconVolume = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_VOLUME));
g_hIconMute = LoadIcon(g_hInstance, MAKEINTRESOURCE(IDI_VOLMUTE));
Volume_IsMute();
HICON icon;
if (g_IsMute)
icon = g_hIconMute;
else
icon = g_hIconVolume;
return pSysTray->NotifyIcon(NIM_ADD, ID_ICON_VOLUME, icon, L"Volume Control");
}
HRESULT STDMETHODCALLTYPE Volume_Update(_In_ CSysTray * pSysTray)
{
TRACE("Volume_Update\n");
Volume_IsMute();
HICON icon;
if (g_IsMute)
icon = g_hIconMute;
else
icon = g_hIconVolume;
return pSysTray->NotifyIcon(NIM_MODIFY, ID_ICON_VOLUME, icon, L"Placeholder");
}
HRESULT STDMETHODCALLTYPE Volume_Shutdown(_In_ CSysTray * pSysTray)
{
TRACE("Volume_Shutdown\n");
return pSysTray->NotifyIcon(NIM_DELETE, ID_ICON_VOLUME, NULL, NULL);
}
HRESULT Volume_OnDeviceChange(_In_ CSysTray * pSysTray, WPARAM wParam, LPARAM lParam)
{
return Volume_FindMixerControl(pSysTray);
}
HRESULT STDMETHODCALLTYPE Volume_Message(_In_ CSysTray * pSysTray, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
if (uMsg == g_mmDeviceChange)
return Volume_OnDeviceChange(pSysTray, wParam, lParam);
if (uMsg != ID_ICON_VOLUME)
{
TRACE("Volume_Message received for unknown ID %d, ignoring.\n");
return S_FALSE;
}
TRACE("Volume_Message uMsg=%d, w=%x, l=%x\n", uMsg, wParam, lParam);
Volume_Update(pSysTray);
switch (lParam)
{
case WM_LBUTTONDOWN:
break;
case WM_LBUTTONUP:
TRACE("TODO: display volume slider\n");
break;
case WM_LBUTTONDBLCLK:
// FIXME: ensure we are loading the right one
ShellExecute(NULL, NULL, L"sndvol32.exe", NULL, NULL, SW_SHOWNORMAL);
break;
case WM_RBUTTONDOWN:
break;
case WM_RBUTTONUP:
break;
case WM_RBUTTONDBLCLK:
break;
case WM_MOUSEMOVE:
break;
}
return S_OK;
}

View File

@ -1,3 +1,4 @@
PROJECT(SHELL)
set_cpp(WITH_RUNTIME)
@ -20,8 +21,10 @@ list(APPEND SOURCE
browseui.cpp
browseuiord.cpp
commonbrowser.cpp
desktopipc.cpp
globalfoldersettings.cpp
internettoolbar.cpp
parsecmdline.cpp
regtreeoptions.cpp
shellbrowser.cpp
toolsband.cpp
@ -51,3 +54,15 @@ if(NOT MSVC)
add_target_link_flags(browseui "-Wl,--allow-multiple-definition")
endif()
endif()
add_custom_command(TARGET browseui POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:browseui>"
"$<TARGET_FILE_DIR:filebrowser>/$<TARGET_FILE_NAME:browseui>"
COMMENT "Copying to output directory")
add_custom_command(TARGET browseui POST_BUILD
COMMAND "${CMAKE_COMMAND}" -E copy
"$<TARGET_FILE:browseui>"
"$<TARGET_FILE_DIR:filebrowser>/$<TARGET_FILE_NAME:browseui>"
COMMENT "Copying to output directory")

View File

@ -57,9 +57,9 @@ HRESULT STDMETHODCALLTYPE CACLMulti::Append(IUnknown *punk)
CoTaskMemRealloc(fObjects, sizeof(fObjects[0]) * (fObjectCount + 1)));
fObjects[fObjectCount].punk = punk;
punk->AddRef();
if (FAILED(punk->QueryInterface(IID_IEnumString, reinterpret_cast<void **>(&fObjects[fObjectCount].pEnum))))
if (FAILED_UNEXPECTEDLY(punk->QueryInterface(IID_PPV_ARG(IEnumString, &fObjects[fObjectCount].pEnum))))
fObjects[fObjectCount].pEnum = NULL;
if (FAILED(punk->QueryInterface(IID_IACList, reinterpret_cast<void **>(&fObjects[fObjectCount].pACL))))
if (FAILED_UNEXPECTEDLY(punk->QueryInterface(IID_PPV_ARG(IACList, &fObjects[fObjectCount].pACL))))
fObjects[fObjectCount].pACL = NULL;
fObjectCount++;
return S_OK;

View File

@ -23,6 +23,18 @@ Implements the navigation band of the cabinet window
*/
#include "precomp.h"
#include <commoncontrols.h>
#include <shlwapi_undoc.h>
#include <shellapi.h>
HRESULT CreateAddressEditBox(REFIID riid, void **ppv);
extern "C"
HRESULT WINAPI SHGetImageList(
_In_ int iImageList,
_In_ REFIID riid,
_Out_ void **ppv
);
/*
TODO:
@ -45,6 +57,7 @@ CAddressBand::CAddressBand()
fGoButton = NULL;
fComboBox = NULL;
fGoButtonShown = false;
fAdviseCookie = 0;
}
CAddressBand::~CAddressBand()
@ -97,43 +110,39 @@ HRESULT STDMETHODCALLTYPE CAddressBand::GetBandInfo(DWORD dwBandID, DWORD dwView
HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
{
CComPtr<IBrowserService> browserService;
CComPtr<IShellService> shellService;
CComPtr<IUnknown> offset34;
HWND parentWindow;
IOleWindow *oleWindow;
HWND toolbar;
static const TBBUTTON buttonInfo[] = { {0, 1, TBSTATE_ENABLED, 0} };
HIMAGELIST normalImagelist;
HIMAGELIST hotImageList;
HINSTANCE shellInstance;
HWND combobox;
HRESULT hResult;
fSite.Release();
if (pUnkSite == NULL)
{
hResult = AtlUnadvise(fSite, DIID_DWebBrowserEvents, fAdviseCookie);
fSite.Release();
return S_OK;
}
hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, reinterpret_cast<void **>(&fSite));
if (FAILED(hResult))
fSite.Release();
hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fSite));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
// get window handle of parent
parentWindow = NULL;
hResult = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
if (SUCCEEDED(hResult))
{
oleWindow->GetWindow(&parentWindow);
oleWindow->Release();
}
hResult = IUnknown_GetWindow(fSite, &parentWindow);
if (!::IsWindow(parentWindow))
return E_FAIL;
// create combo box ex
toolbar = CreateWindowEx(WS_EX_TOOLWINDOW, WC_COMBOBOXEXW, NULL, WS_CHILD | WS_VISIBLE |
WS_CLIPCHILDREN | WS_TABSTOP | CCS_NODIVIDER | CCS_NOMOVEY,
combobox = CreateWindowEx(WS_EX_TOOLWINDOW, WC_COMBOBOXEXW, NULL, WS_CHILD | WS_VISIBLE |
WS_CLIPCHILDREN | WS_TABSTOP | CCS_NODIVIDER | CCS_NOMOVEY | CBS_OWNERDRAWFIXED,
0, 0, 500, 250, parentWindow, (HMENU)0xa205, _AtlBaseModule.GetModuleInstance(), 0);
if (toolbar == NULL)
if (combobox == NULL)
return E_FAIL;
SubclassWindow(toolbar);
SubclassWindow(combobox);
SendMessage(CBEM_SETEXTENDEDSTYLE,
CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT, CBES_EX_CASESENSITIVE | CBES_EX_NOSIZELIMIT);
@ -142,43 +151,76 @@ HRESULT STDMETHODCALLTYPE CAddressBand::SetSite(IUnknown *pUnkSite)
fComboBox = reinterpret_cast<HWND>(SendMessage(CBEM_GETCOMBOCONTROL, 0, 0));
#if 1
hResult = CoCreateInstance(CLSID_AddressEditBox, NULL, CLSCTX_INPROC_SERVER,
IID_IAddressEditBox, reinterpret_cast<void **>(&fAddressEditBox));
if (FAILED(hResult))
return hResult;
IID_PPV_ARG(IAddressEditBox, &fAddressEditBox));
#else
// instantiate new version
hResult = E_FAIL;
#endif
if (FAILED_UNEXPECTEDLY(hResult))
{
// instantiate new version
hResult = CreateAddressEditBox(IID_PPV_ARG(IAddressEditBox, &fAddressEditBox));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
}
hResult = fAddressEditBox->QueryInterface(IID_IShellService, reinterpret_cast<void **>(&shellService));
if (FAILED(hResult))
hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IShellService, &shellService));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = fAddressEditBox->Init(toolbar, fEditControl, 8, pUnkSite /*(IAddressBand *)this*/ );
if (FAILED(hResult))
hResult = fAddressEditBox->Init(combobox, fEditControl, 8, fSite /*(IAddressBand *)this*/);
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = shellService->SetOwner(pUnkSite);
if (FAILED(hResult))
hResult = shellService->SetOwner(fSite);
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
// TODO: properly initialize this from registry
fGoButtonShown = true;
shellInstance = GetModuleHandle(_T("shell32.dll"));
normalImagelist = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCE(IDB_GOBUTTON_NORMAL),
20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
hotImageList = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCE(IDB_GOBUTTON_HOT),
20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
if (fGoButtonShown)
{
const TBBUTTON buttonInfo [] = { { 0, 1, TBSTATE_ENABLED, 0 } };
HIMAGELIST normalImagelist;
HIMAGELIST hotImageList;
HINSTANCE shellInstance;
fGoButton = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAMEW, 0, WS_CHILD | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NODIVIDER |
CCS_NOPARENTALIGN | CCS_NORESIZE,
0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
SendMessage(fGoButton, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
SendMessage(fGoButton, TB_SETMAXTEXTROWS, 1, 0);
SendMessage(fGoButton, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(normalImagelist));
SendMessage(fGoButton, TB_SETHOTIMAGELIST, 0, reinterpret_cast<LPARAM>(hotImageList));
SendMessage(fGoButton, TB_ADDSTRINGW,
reinterpret_cast<WPARAM>(_AtlBaseModule.GetResourceInstance()), IDS_GOBUTTONLABEL);
SendMessage(fGoButton, TB_ADDBUTTONSW, 1, (LPARAM)&buttonInfo);
shellInstance = GetModuleHandle(_T("shell32.dll"));
normalImagelist = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCE(IDB_GOBUTTON_NORMAL),
20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
hotImageList = ImageList_LoadImageW(shellInstance, MAKEINTRESOURCE(IDB_GOBUTTON_HOT),
20, 0, RGB(255, 0, 255), IMAGE_BITMAP, LR_CREATEDIBSECTION);
fGoButton = CreateWindowEx(WS_EX_TOOLWINDOW, TOOLBARCLASSNAMEW, 0, WS_CHILD | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | TBSTYLE_LIST | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS | CCS_NODIVIDER |
CCS_NOPARENTALIGN | CCS_NORESIZE,
0, 0, 0, 0, m_hWnd, NULL, _AtlBaseModule.GetModuleInstance(), NULL);
SendMessage(fGoButton, TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
SendMessage(fGoButton, TB_SETMAXTEXTROWS, 1, 0);
if (normalImagelist)
SendMessage(fGoButton, TB_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(normalImagelist));
if (hotImageList)
SendMessage(fGoButton, TB_SETHOTIMAGELIST, 0, reinterpret_cast<LPARAM>(hotImageList));
SendMessage(fGoButton, TB_ADDSTRINGW,
reinterpret_cast<WPARAM>(_AtlBaseModule.GetResourceInstance()), IDS_GOBUTTONLABEL);
SendMessage(fGoButton, TB_ADDBUTTONSW, 1, (LPARAM) &buttonInfo);
IImageList * piml;
HRESULT hr = SHGetImageList(SHIL_SMALL, IID_PPV_ARG(IImageList, &piml));
if (FAILED_UNEXPECTEDLY(hr))
{
SendMessageW(combobox, CBEM_SETIMAGELIST, 0, 0);
}
else
{
SendMessageW(combobox, CBEM_SETIMAGELIST, 0, reinterpret_cast<LPARAM>(piml));
}
}
// take advice to watch events
hResult = IUnknown_QueryService(pUnkSite, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
if (SUCCEEDED(hResult))
{
hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
}
return hResult;
}
@ -212,6 +254,11 @@ HRESULT STDMETHODCALLTYPE CAddressBand::CloseDW(DWORD dwReserved)
m_hWnd = NULL;
IUnknown_SetSite(fAddressEditBox, NULL);
if (fAddressEditBox) fAddressEditBox.Release();
if (fSite) fSite.Release();
return S_OK;
}
@ -239,8 +286,8 @@ HRESULT STDMETHODCALLTYPE CAddressBand::QueryStatus(
CComPtr<IOleCommandTarget> oleCommandTarget;
HRESULT hResult;
hResult = fAddressEditBox->QueryInterface(IID_IOleCommandTarget, reinterpret_cast<void **>(&oleCommandTarget));
if (FAILED(hResult))
hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IOleCommandTarget, &oleCommandTarget));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return oleCommandTarget->QueryStatus(pguidCmdGroup, cCmds, prgCmds, pCmdText);
}
@ -261,7 +308,22 @@ HRESULT STDMETHODCALLTYPE CAddressBand::HasFocusIO()
HRESULT STDMETHODCALLTYPE CAddressBand::TranslateAcceleratorIO(LPMSG lpMsg)
{
// incomplete
if (lpMsg->hwnd == fEditControl)
{
switch (lpMsg->message)
{
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCOMMAND:
case WM_SYSDEADCHAR:
case WM_SYSCHAR:
return S_FALSE;
}
TranslateMessage(lpMsg);
DispatchMessage(lpMsg);
return S_OK;
}
return S_FALSE;
}
@ -272,8 +334,8 @@ HRESULT STDMETHODCALLTYPE CAddressBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg
if (fActivate)
{
hResult = fSite->QueryInterface(IID_IInputObjectSite, reinterpret_cast<void **>(&inputObjectSite));
if (FAILED(hResult))
hResult = fSite->QueryInterface(IID_PPV_ARG(IInputObjectSite, &inputObjectSite));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = inputObjectSite->OnFocusChangeIS(static_cast<IDeskBand *>(this), fActivate);
SetFocus();
@ -287,6 +349,8 @@ HRESULT STDMETHODCALLTYPE CAddressBand::OnWinEvent(
CComPtr<IWinEventHandler> winEventHandler;
HRESULT hResult;
*theResult = 0;
switch (uMsg)
{
case WM_WININICHANGE:
@ -300,8 +364,8 @@ HRESULT STDMETHODCALLTYPE CAddressBand::OnWinEvent(
}
break;
}
hResult = fAddressEditBox->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
if (FAILED(hResult))
hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
}
@ -311,10 +375,14 @@ HRESULT STDMETHODCALLTYPE CAddressBand::IsWindowOwner(HWND hWnd)
CComPtr<IWinEventHandler> winEventHandler;
HRESULT hResult;
hResult = fAddressEditBox->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
if (FAILED(hResult))
return hResult;
return winEventHandler->IsWindowOwner(hWnd);
if (fAddressEditBox)
{
hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return winEventHandler->IsWindowOwner(hWnd);
}
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CAddressBand::FileSysChange(long param8, long paramC)
@ -322,8 +390,8 @@ HRESULT STDMETHODCALLTYPE CAddressBand::FileSysChange(long param8, long paramC)
CComPtr<IAddressBand> addressBand;
HRESULT hResult;
hResult = fAddressEditBox->QueryInterface(IID_IAddressBand, reinterpret_cast<void **>(&addressBand));
if (FAILED(hResult))
hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IAddressBand, &addressBand));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return addressBand->FileSysChange(param8, paramC);
}
@ -333,8 +401,8 @@ HRESULT STDMETHODCALLTYPE CAddressBand::Refresh(long param8)
CComPtr<IAddressBand> addressBand;
HRESULT hResult;
hResult = fAddressEditBox->QueryInterface(IID_IAddressBand, reinterpret_cast<void **>(&addressBand));
if (FAILED(hResult))
hResult = fAddressEditBox->QueryInterface(IID_PPV_ARG(IAddressBand, &addressBand));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return addressBand->Refresh(param8);
}
@ -380,12 +448,113 @@ HRESULT STDMETHODCALLTYPE CAddressBand::GetSizeMax(ULARGE_INTEGER *pcbSize)
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CAddressBand::GetTypeInfoCount(UINT *pctinfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CAddressBand::GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CAddressBand::GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames,
LCID lcid, DISPID *rgDispId)
{
return E_NOTIMPL;
}
HRESULT STDMETHODCALLTYPE CAddressBand::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags,
DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
CComPtr<IBrowserService> isb;
CComPtr<IShellFolder> sf;
HRESULT hr;
INT indexClosed, indexOpen, itemExists, oldIndex;
DWORD result;
COMBOBOXEXITEMW item;
PIDLIST_ABSOLUTE absolutePIDL;
LPCITEMIDLIST pidlChild;
LPITEMIDLIST pidlPrevious;
STRRET ret;
WCHAR buf[4096];
if (pDispParams == NULL)
return E_INVALIDARG;
switch (dispIdMember)
{
case DISPID_NAVIGATECOMPLETE2:
case DISPID_DOCUMENTCOMPLETE:
oldIndex = SendMessage(m_hWnd, CB_GETCURSEL, 0, 0);
itemExists = FALSE;
pidlPrevious = NULL;
ZeroMemory(&item, sizeof(item));
item.mask = CBEIF_LPARAM;
item.iItem = 0;
if (SendMessage(m_hWnd, CBEM_GETITEM, 0, reinterpret_cast<LPARAM>(&item)))
{
pidlPrevious = reinterpret_cast<LPITEMIDLIST>(item.lParam);
if (pidlPrevious)
itemExists = TRUE;
}
hr = IUnknown_QueryService(fSite, SID_STopLevelBrowser, IID_PPV_ARG(IBrowserService, &isb));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
isb->GetPidl(&absolutePIDL);
SHBindToParent(absolutePIDL, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
sf->GetDisplayNameOf(pidlChild, SHGDN_FORADDRESSBAR | SHGDN_FORPARSING, &ret);
StrRetToBufW(&ret, pidlChild, buf, 4095);
indexClosed = SHMapPIDLToSystemImageListIndex(sf, pidlChild, &indexOpen);
item.mask = CBEIF_IMAGE | CBEIF_SELECTEDIMAGE | CBEIF_TEXT | CBEIF_LPARAM;
item.iItem = 0;
item.iImage = indexClosed;
item.iSelectedImage = indexOpen;
item.pszText = buf;
item.lParam = reinterpret_cast<LPARAM>(absolutePIDL);
if (itemExists)
{
result = SendMessage(m_hWnd, CBEM_SETITEM, 0, reinterpret_cast<LPARAM>(&item));
oldIndex = 0;
if (result)
{
ILFree(pidlPrevious);
}
}
else
{
oldIndex = SendMessage(m_hWnd, CBEM_INSERTITEM, 0, reinterpret_cast<LPARAM>(&item));
if (oldIndex < 0)
DbgPrint("ERROR %d\n", GetLastError());
}
SendMessage(m_hWnd, CB_SETCURSEL, -1, 0);
SendMessage(m_hWnd, CB_SETCURSEL, oldIndex, 0);
//fAddressEditBox->SetCurrentDir(index);
break;
}
return S_OK;
}
LRESULT CAddressBand::OnNotifyClick(WPARAM wParam, NMHDR *notifyHeader, BOOL &bHandled)
{
if (notifyHeader->hwndFrom == fGoButton)
{
SendMessage(fEditControl, WM_KEYDOWN, 13, 0);
SendMessage(fEditControl, WM_KEYUP, 13, 0);
fAddressEditBox->Execute(0);
}
return 0;
}
@ -507,20 +676,5 @@ LRESULT CAddressBand::OnWindowPosChanging(UINT uMsg, WPARAM wParam, LPARAM lPara
HRESULT CreateAddressBand(REFIID riid, void **ppv)
{
CComObject<CAddressBand> *theMenuBar;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theMenuBar = new CComObject<CAddressBand>);
if (theMenuBar == NULL)
return E_OUTOFMEMORY;
hResult = theMenuBar->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theMenuBar;
return hResult;
}
return S_OK;
return ShellObjectCreator<CAddressBand>(riid, ppv);
}

View File

@ -32,7 +32,8 @@ class CAddressBand :
public IServiceProvider,
public IWinEventHandler,
public IAddressBand,
public IInputObjectSite
public IInputObjectSite,
public IDispatch
{
private:
CComPtr<IDockingWindowSite> fSite;
@ -41,9 +42,10 @@ private:
HWND fGoButton;
HWND fComboBox;
bool fGoButtonShown;
DWORD fAdviseCookie;
public:
CAddressBand();
~CAddressBand();
virtual ~CAddressBand();
private:
void FocusChange(BOOL bFocus);
public:
@ -95,6 +97,12 @@ public:
virtual HRESULT STDMETHODCALLTYPE Save(IStream *pStm, BOOL fClearDirty);
virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
// *** IDispatch methods ***
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(UINT *pctinfo);
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo **ppTInfo);
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(REFIID riid, LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId);
virtual HRESULT STDMETHODCALLTYPE Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr);
// message handlers
LRESULT OnNotifyClick(WPARAM wParam, NMHDR *notifyHeader, BOOL &bHandled);
LRESULT OnTipText(UINT idControl, NMHDR *notifyHeader, BOOL &bHandled);
@ -128,5 +136,6 @@ public:
COM_INTERFACE_ENTRY_IID(IID_IInputObjectSite, IInputObjectSite)
COM_INTERFACE_ENTRY_IID(IID_IPersist, IPersist)
COM_INTERFACE_ENTRY_IID(IID_IPersistStream, IPersistStream)
COM_INTERFACE_ENTRY_IID(IID_IDispatch, IDispatch)
END_COM_MAP()
};

View File

@ -40,8 +40,9 @@ TODO:
*/
CAddressEditBox::CAddressEditBox() :
fEditWindow(NULL, this, 1),
fComboBoxExWindow(NULL, this, 2)
fCombobox(NULL, this, 1),
fEditWindow(NULL, this, 1),
fSite(NULL)
{
}
@ -67,9 +68,22 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Refresh(long param8)
HRESULT STDMETHODCALLTYPE CAddressEditBox::Init(HWND comboboxEx, HWND editControl, long param14, IUnknown *param18)
{
fComboBoxExWindow.SubclassWindow(comboboxEx);
CComPtr<IBrowserService> browserService;
fCombobox.SubclassWindow(comboboxEx);
fEditWindow.SubclassWindow(editControl);
return S_OK;
fSite = param18;
SHAutoComplete(fEditWindow.m_hWnd, SHACF_FILESYSTEM | SHACF_URLALL | SHACF_USETAB);
// take advice to watch events
HRESULT hResult = IUnknown_QueryService(param18, SID_SShellBrowser, IID_PPV_ARG(IBrowserService, &browserService));
if (SUCCEEDED(hResult))
{
hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
}
return hResult;
}
HRESULT STDMETHODCALLTYPE CAddressEditBox::SetCurrentDir(long paramC)
@ -79,12 +93,129 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::SetCurrentDir(long paramC)
HRESULT STDMETHODCALLTYPE CAddressEditBox::ParseNow(long paramC)
{
return E_NOTIMPL;
ULONG eaten;
ULONG attributes;
HRESULT hr;
HWND topLevelWindow;
CComPtr<IShellBrowser> pisb;
hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pisb));
if (FAILED_UNEXPECTEDLY(hr))
return hr;
hr = IUnknown_GetWindow(pisb, &topLevelWindow);
if (FAILED_UNEXPECTEDLY(hr))
return hr;
LPWSTR input;
int inputLength = GetWindowTextLength(fCombobox.m_hWnd) + 2;
input = new WCHAR[inputLength];
GetWindowText(fCombobox.m_hWnd, input, inputLength);
LPWSTR address;
int addressLength = ExpandEnvironmentStrings(input, NULL, 0);
if (addressLength <= 0)
{
address = input;
}
else
{
addressLength += 2;
address = new WCHAR[addressLength];
if (!ExpandEnvironmentStrings(input, address, addressLength))
{
delete[] address;
address = input;
}
}
CComPtr<IShellFolder> psfDesktop;
hr = SHGetDesktopFolder(&psfDesktop);
if (SUCCEEDED(hr))
{
hr = psfDesktop->ParseDisplayName(topLevelWindow, NULL, address, &eaten, &pidlLastParsed, &attributes);
}
if (address != input)
delete [] address;
delete [] input;
return hr;
}
HRESULT STDMETHODCALLTYPE CAddressEditBox::Execute(long paramC)
{
return E_NOTIMPL;
HRESULT hr;
/*
* Parse the path is it wasn't parsed
*/
if (!pidlLastParsed)
ParseNow(0);
if (!pidlLastParsed)
return E_FAIL;
/*
* Get the IShellBrowser and IBrowserService interfaces of the shell browser
*/
CComPtr<IShellBrowser> pisb;
hr = IUnknown_QueryService(fSite, SID_SShellBrowser, IID_PPV_ARG(IShellBrowser, &pisb));
if (FAILED(hr))
return hr;
CComPtr<IBrowserService> pbs;
pisb->QueryInterface(IID_PPV_ARG(IBrowserService, &pbs));
if (FAILED(hr))
return hr;
/*
* Get the current pidl of the shellbrowser and check if it is the same with the parsed one
*/
PIDLIST_ABSOLUTE pidl;
hr = pbs->GetPidl(&pidl);
if (FAILED(hr))
return hr;
CComPtr<IShellFolder> psf;
hr = SHGetDesktopFolder(&psf);
if (FAILED(hr))
return hr;
hr = psf->CompareIDs(0, pidl, pidlLastParsed);
SHFree(pidl);
if (hr == 0)
return S_OK;
/*
* Attempt to browse to the parsed pidl
*/
hr = pisb->BrowseObject(pidlLastParsed, 0);
if (SUCCEEDED(hr))
return hr;
/*
* Browsing to the pidl failed so it's not a folder. So invoke its defaule command.
*/
HWND topLevelWindow;
hr = IUnknown_GetWindow(pisb, &topLevelWindow);
if (FAILED(hr))
return hr;
LPCITEMIDLIST pidlChild;
CComPtr<IShellFolder> sf;
hr = SHBindToParent(pidlLastParsed, IID_PPV_ARG(IShellFolder, &sf), &pidlChild);
if (FAILED(hr))
return hr;
hr = SHInvokeDefaultCommand(topLevelWindow, sf, pidlChild);
if (FAILED(hr))
return hr;
return hr;
}
HRESULT STDMETHODCALLTYPE CAddressEditBox::Save(long paramC)
@ -95,13 +226,38 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::Save(long paramC)
HRESULT STDMETHODCALLTYPE CAddressEditBox::OnWinEvent(
HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT *theResult)
{
// handle fill of listbox here
return E_NOTIMPL;
LPNMHDR hdr;
*theResult = 0;
switch (uMsg)
{
case WM_NOTIFY:
hdr = (LPNMHDR) lParam;
if (hdr->code == CBEN_ENDEDIT)
{
NMCBEENDEDITW *endEdit = (NMCBEENDEDITW*) lParam;
if (endEdit->iWhy == CBENF_RETURN)
{
Execute(0);
}
else if (endEdit->iWhy == CBENF_ESCAPE)
{
/* Reset the contents of the combo box */
}
}
break;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CAddressEditBox::IsWindowOwner(HWND hWnd)
{
return E_NOTIMPL;
if (fCombobox.m_hWnd == hWnd)
return S_OK;
if (fEditWindow.m_hWnd == hWnd)
return S_OK;
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CAddressEditBox::QueryStatus(
@ -135,8 +291,16 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::GetIDsOfNames(
HRESULT STDMETHODCALLTYPE CAddressEditBox::Invoke(DISPID dispIdMember, REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS *pDispParams, VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
// on navigate complete, change edit section of combobox
return E_NOTIMPL;
if (pDispParams == NULL)
return E_INVALIDARG;
switch (dispIdMember)
{
case DISPID_NAVIGATECOMPLETE2:
case DISPID_DOCUMENTCOMPLETE:
pidlLastParsed = NULL;
}
return S_OK;
}
HRESULT STDMETHODCALLTYPE CAddressEditBox::GetClassID(CLSID *pClassID)
@ -169,20 +333,5 @@ HRESULT STDMETHODCALLTYPE CAddressEditBox::GetSizeMax(ULARGE_INTEGER *pcbSize)
HRESULT CreateAddressEditBox(REFIID riid, void **ppv)
{
CComObject<CAddressEditBox> *theMenuBar;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theMenuBar = new CComObject<CAddressEditBox>);
if (theMenuBar == NULL)
return E_OUTOFMEMORY;
hResult = theMenuBar->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theMenuBar;
return hResult;
}
return S_OK;
return ShellObjectCreator<CAddressEditBox>(riid, ppv);
}

View File

@ -33,8 +33,11 @@ class CAddressEditBox :
public IShellService
{
private:
CContainedWindow fCombobox;
CContainedWindow fEditWindow;
CContainedWindow fComboBoxExWindow;
DWORD fAdviseCookie;
CComPtr<IUnknown> fSite;
LPITEMIDLIST pidlLastParsed;
public:
CAddressEditBox();
~CAddressEditBox();
@ -78,8 +81,6 @@ public:
virtual HRESULT STDMETHODCALLTYPE GetSizeMax(ULARGE_INTEGER *pcbSize);
// message handlers
// LRESULT OnSetFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
// LRESULT OnKillFocus(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
DECLARE_REGISTRY_RESOURCEID(IDR_ADDRESSEDITBOX)
DECLARE_NOT_AGGREGATABLE(CAddressEditBox)
@ -87,13 +88,6 @@ public:
DECLARE_PROTECT_FINAL_CONSTRUCT()
BEGIN_MSG_MAP(CAddressEditBox)
// MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
// MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocus)
// MESSAGE_HANDLER(WM_KILLFOCUS, OnKillFocus)
// ALT_MSG_MAP(1)
// MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocusSaveButton)
// ALT_MSG_MAP(2)
// MESSAGE_HANDLER(WM_SETFOCUS, OnSetFocusSelectButton)
END_MSG_MAP()
BEGIN_COM_MAP(CAddressEditBox)

View File

@ -43,12 +43,12 @@ HRESULT CBandProxy::FindBrowserWindow(IUnknown **browser)
if (browser == NULL)
return E_POINTER;
hResult = fSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
if (FAILED(hResult))
hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = serviceProvider->QueryService(
SID_IWebBrowserApp, IID_IWebBrowser2, reinterpret_cast<void **>(&webBrowser));
if (FAILED(hResult))
SID_IWebBrowserApp, IID_PPV_ARG(IWebBrowser2, &webBrowser));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
*browser = webBrowser.Detach();
return S_OK;
@ -78,7 +78,7 @@ HRESULT STDMETHODCALLTYPE CBandProxy::IsConnected()
HRESULT hResult;
hResult = FindBrowserWindow(&webBrowser);
if (FAILED(hResult) || webBrowser.p == NULL)
if (FAILED_UNEXPECTEDLY(hResult) || webBrowser.p == NULL)
return S_FALSE;
return S_OK;
}
@ -96,17 +96,17 @@ HRESULT STDMETHODCALLTYPE CBandProxy::NavigateToPIDL(LPCITEMIDLIST pidl)
HRESULT hResult;
hResult = FindBrowserWindow(&webBrowserUnknown);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = webBrowserUnknown->QueryInterface(IID_IWebBrowserApp, reinterpret_cast<void **>(&webBrowser));
if (FAILED(hResult))
hResult = webBrowserUnknown->QueryInterface(IID_PPV_ARG(IWebBrowser2, &webBrowser));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = webBrowser->put_Visible(TRUE);
hResult = webBrowser->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
hResult = webBrowser->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
if (SUCCEEDED(hResult))
{
hResult = serviceProvider->QueryService(SID_STopLevelBrowser,
IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
IID_PPV_ARG(IOleWindow, &oleWindow));
if (SUCCEEDED(hResult))
{
hResult = oleWindow->GetWindow(&browserWindow);
@ -121,7 +121,7 @@ HRESULT STDMETHODCALLTYPE CBandProxy::NavigateToPIDL(LPCITEMIDLIST pidl)
return E_OUTOFMEMORY;
memcpy(V_ARRAY(&args)->pvData, pidl, arraySize);
hResult = webBrowser->Navigate2(&args, &emptyVariant, &emptyVariant, &emptyVariant, &emptyVariant);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return S_OK;
}
@ -133,20 +133,5 @@ HRESULT STDMETHODCALLTYPE CBandProxy::NavigateToURL(long paramC, long param10)
HRESULT CreateBandProxy(REFIID riid, void **ppv)
{
CComObject<CBandProxy> *theBandProxy;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theBandProxy = new CComObject<CBandProxy>);
if (theBandProxy == NULL)
return E_OUTOFMEMORY;
hResult = theBandProxy->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theBandProxy;
return hResult;
}
return S_OK;
return ShellObjectCreator<CBandProxy>(riid, ppv);
}

View File

@ -202,7 +202,7 @@ HRESULT CBandSiteBase::UpdateAllBands()
if (fBands[i].DeskBand != NULL)
{
hRet = UpdateSingleBand(&fBands[i]);
if (FAILED(hRet))
if (FAILED_UNEXPECTEDLY(hRet))
return hRet;
}
}
@ -283,16 +283,16 @@ HRESULT STDMETHODCALLTYPE CBandSiteBase::AddBand(IUnknown *punk)
if (punk == NULL || fRebarWindow == NULL)
return E_FAIL;
hRet = punk->QueryInterface(IID_IDeskBand, reinterpret_cast<PVOID *>(&DeskBand));
hRet = punk->QueryInterface(IID_PPV_ARG(IDeskBand, &DeskBand));
if (!SUCCEEDED(hRet) || DeskBand == NULL)
goto Cleanup;
hRet = punk->QueryInterface(IID_IObjectWithSite, reinterpret_cast<PVOID *>(&ObjWithSite));
hRet = punk->QueryInterface(IID_PPV_ARG(IObjectWithSite, &ObjWithSite));
if (!SUCCEEDED(hRet) || ObjWithSite == NULL)
goto Cleanup;
hRet = punk->QueryInterface(IID_IOleWindow, reinterpret_cast<PVOID *>(&OleWindow));
hRet = punk->QueryInterface(IID_PPV_ARG(IOleWindow, &OleWindow));
if (!SUCCEEDED(hRet) || OleWindow == NULL)
goto Cleanup;
hRet = punk->QueryInterface(IID_IWinEventHandler, reinterpret_cast<PVOID *>(&WndEvtHandler));
hRet = punk->QueryInterface(IID_PPV_ARG(IWinEventHandler, &WndEvtHandler));
if (!SUCCEEDED(hRet) || WndEvtHandler == NULL)
goto Cleanup;
@ -337,7 +337,6 @@ HRESULT STDMETHODCALLTYPE CBandSiteBase::AddBand(IUnknown *punk)
/* Initialize the added bands */
memset(&NewBand[fBandsAllocated], 0, (NewAllocated - fBandsAllocated) * sizeof(struct BandObject));
NewBand = &fBands[fBandsAllocated];
fBandsAllocated = NewAllocated;
CoTaskMemFree(fBands);
fBands = NewBand;
@ -627,15 +626,15 @@ HRESULT STDMETHODCALLTYPE CBandSiteBase::SetDeskBarSite(IUnknown *pUnk)
fOleWindow.Release();
hRet = pUnk->QueryInterface(IID_IOleWindow, (PVOID *)&fOleWindow);
if (FAILED(hRet))
hRet = pUnk->QueryInterface(IID_PPV_ARG(IOleWindow, &fOleWindow));
if (FAILED_UNEXPECTEDLY(hRet))
return E_FAIL;
hRet = fOleWindow->GetWindow(&hWndParent);
if (FAILED(hRet))
if (FAILED_UNEXPECTEDLY(hRet))
return E_FAIL;
style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT |
style = WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | RBS_VARHEIGHT | RBS_AUTOSIZE |
RBS_BANDBORDERS | CCS_NODIVIDER | CCS_NORESIZE | CCS_NOPARENTALIGN;
fRebarWindow = CreateWindowExW(WS_EX_TOOLWINDOW,

View File

@ -144,7 +144,7 @@ class CBandSite :
public:
DECLARE_REGISTRY_RESOURCEID(IDR_BANDSITE)
DECLARE_NOT_AGGREGATABLE(CBandSite)
DECLARE_AGGREGATABLE(CBandSite)
DECLARE_PROTECT_FINAL_CONSTRUCT()
};

View File

@ -179,11 +179,11 @@ HRESULT CBaseBar::ReserveBorderSpace()
RECT neededBorderSpace;
HRESULT hResult;
hResult = fSite->QueryInterface(IID_IDockingWindowSite, reinterpret_cast<void **>(&dockingWindowSite));
if (FAILED(hResult))
hResult = fSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &dockingWindowSite));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = dockingWindowSite->GetBorderDW(static_cast<IDeskBar *>(this), &availableBorderSpace);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
memset(&neededBorderSpace, 0, sizeof(neededBorderSpace));
if (fVisible)
@ -194,7 +194,7 @@ HRESULT CBaseBar::ReserveBorderSpace()
neededBorderSpace.bottom = fNeededSize + GetSystemMetrics(SM_CXFRAME);
}
hResult = dockingWindowSite->SetBorderSpaceDW(static_cast<IDeskBar *>(this), &neededBorderSpace);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return S_OK;
}
@ -272,8 +272,8 @@ HRESULT STDMETHODCALLTYPE CBaseBar::QueryService(REFGUID guidService, REFIID rii
if (fSite == NULL)
return E_FAIL;
hResult = fSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
if (FAILED(hResult))
hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
// called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
// called for SID_IWebBrowserApp, IID_IConnectionPointContainer
@ -296,7 +296,7 @@ HRESULT STDMETHODCALLTYPE CBaseBar::HasFocusIO()
HRESULT STDMETHODCALLTYPE CBaseBar::TranslateAcceleratorIO(LPMSG lpMsg)
{
// forward to contained bar
return S_OK;
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CBaseBar::SetClient(IUnknown *punkClient)
@ -309,14 +309,14 @@ HRESULT STDMETHODCALLTYPE CBaseBar::SetClient(IUnknown *punkClient)
fClient.Release();
else
{
hResult = punkClient->QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&fClient));
if (FAILED(hResult))
hResult = punkClient->QueryInterface(IID_PPV_ARG(IUnknown, &fClient));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = fSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
if (FAILED(hResult))
hResult = fSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = oleWindow->GetWindow(&ownerWindow);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
Create(ownerWindow, 0, NULL,
WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_TOOLWINDOW);
@ -430,21 +430,6 @@ HRESULT STDMETHODCALLTYPE CBaseBar::Save(IPropertyBag *pPropBag, BOOL fClearDirt
LRESULT CBaseBar::OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled)
{
/* CComPtr<IOleWindow> oleWindow;
RECT clientRect;
HRESULT hResult;
if (fClientWindow == NULL && fClient.p != NULL)
{
hResult = fClient->QueryInterface(IID_IOleWindow, (void **)&oleWindow);
hResult = oleWindow->GetWindow(&fClientWindow);
}
if (fClientWindow != NULL)
{
GetClientRect(&clientRect);
::SetWindowPos(fClientWindow, NULL, clientRect.left, clientRect.top, clientRect.right - clientRect.left - GetSystemMetrics(SM_CXFRAME),
clientRect.bottom - clientRect.top, SWP_NOOWNERZORDER | SWP_NOZORDER);
}*/
return 0;
}
@ -471,7 +456,7 @@ LRESULT CBaseBar::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandl
result = 0;
if (fClient.p != NULL)
{
hResult = fClient->QueryInterface(IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
hResult = fClient->QueryInterface(IID_PPV_ARG(IWinEventHandler, &winEventHandler));
if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
hResult = winEventHandler->OnWinEvent(NULL, uMsg, wParam, lParam, &result);
}
@ -529,20 +514,5 @@ LRESULT CBaseBar::OnCaptureChanged(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL
HRESULT CreateBaseBar(REFIID riid, void **ppv)
{
CComObject<CBaseBar> *theBaseBar;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theBaseBar = new CComObject<CBaseBar>);
if (theBaseBar == NULL)
return E_OUTOFMEMORY;
hResult = theBaseBar->QueryInterface (riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theBaseBar;
return hResult;
}
return S_OK;
return ShellObjectCreator<CBaseBar>(riid, ppv);
}

View File

@ -170,23 +170,23 @@ HRESULT CBaseBarSite::InsertBar(IUnknown *newBar)
DWORD thisBandID;
HRESULT hResult;
hResult = newBar->QueryInterface(IID_IPersist, reinterpret_cast<void **>(&persist));
if (FAILED(hResult))
hResult = newBar->QueryInterface(IID_PPV_ARG(IPersist, &persist));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = newBar->QueryInterface(IID_IObjectWithSite, reinterpret_cast<void **>(&site));
if (FAILED(hResult))
hResult = newBar->QueryInterface(IID_PPV_ARG(IObjectWithSite, &site));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = newBar->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
if (FAILED(hResult))
hResult = newBar->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = newBar->QueryInterface(IID_IDeskBand, reinterpret_cast<void **>(&deskBand));
if (FAILED(hResult))
hResult = newBar->QueryInterface(IID_PPV_ARG(IDeskBand, &deskBand));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = newBar->QueryInterface(IID_IDockingWindow, reinterpret_cast<void **>(&dockingWindow));
if (FAILED(hResult))
hResult = newBar->QueryInterface(IID_PPV_ARG(IDockingWindow, &dockingWindow));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = site->SetSite(static_cast<IOleWindow *>(this));
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
ATLTRY(newInfo = new CBarInfo);
if (newInfo == NULL)
@ -224,7 +224,7 @@ HRESULT CBaseBarSite::InsertBar(IUnknown *newBar)
// this call is what makes the tree fill with contents
hResult = dockingWindow->ShowDW(TRUE);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
// for now
fCurrentActiveBar = newInfo;
@ -266,8 +266,8 @@ HRESULT STDMETHODCALLTYPE CBaseBarSite::QueryService(REFGUID guidService, REFIID
if (fDeskBarSite == NULL)
return E_FAIL;
hResult = fDeskBarSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
if (FAILED(hResult))
hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
// called for SID_STopLevelBrowser, IID_IBrowserService to find top level browser
// called for SID_IWebBrowserApp, IID_IConnectionPointContainer
@ -290,7 +290,7 @@ HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent(
notifyHeader = (NMHDR *)lParam;
if (notifyHeader->hwndFrom == m_hWnd && notifyHeader->code == RBN_AUTOSIZE)
{
hResult = fDeskBarSite->QueryInterface(IID_IDeskBar, reinterpret_cast<void **>(&deskBar));
hResult = fDeskBarSite->QueryInterface(IID_PPV_ARG(IDeskBar, &deskBar));
GetClientRect(&newBounds);
hResult = deskBar->OnPosRectChangeDB(&newBounds);
}
@ -298,7 +298,7 @@ HRESULT STDMETHODCALLTYPE CBaseBarSite::OnWinEvent(
if (fCurrentActiveBar != NULL)
{
hResult = fCurrentActiveBar->fTheBar->QueryInterface(
IID_IWinEventHandler, reinterpret_cast<void **>(&winEventHandler));
IID_PPV_ARG(IWinEventHandler, &winEventHandler));
if (SUCCEEDED(hResult) && winEventHandler.p != NULL)
hResult = winEventHandler->OnWinEvent(hWnd, uMsg, wParam, lParam, theResult);
}
@ -325,14 +325,14 @@ HRESULT STDMETHODCALLTYPE CBaseBarSite::SetDeskBarSite(IUnknown *punkSite)
fDeskBarSite.Release();
else
{
hResult = punkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
if (FAILED(hResult))
hResult = punkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = punkSite->QueryInterface(IID_IUnknown, reinterpret_cast<void **>(&fDeskBarSite));
if (FAILED(hResult))
hResult = punkSite->QueryInterface(IID_PPV_ARG(IUnknown, &fDeskBarSite));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = oleWindow->GetWindow(&ownerWindow);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
m_hWnd = CreateWindow(REBARCLASSNAMEW, NULL, WS_VISIBLE | WS_CHILDWINDOW | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN |
@ -477,20 +477,5 @@ LRESULT CBaseBarSite::OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bH
HRESULT CreateBaseBarSite(REFIID riid, void **ppv)
{
CComObject<CBaseBarSite> *theBaseBarSite;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theBaseBarSite = new CComObject<CBaseBarSite>);
if (theBaseBarSite == NULL)
return E_OUTOFMEMORY;
hResult = theBaseBarSite->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theBaseBarSite;
return hResult;
}
return S_OK;
return ShellObjectCreator<CBaseBarSite>(riid, ppv);
}

View File

@ -170,11 +170,11 @@ HRESULT STDMETHODCALLTYPE CBrandBand::SetSite(IUnknown* pUnkSite)
}
// get window handle of parent
hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, reinterpret_cast<void **>(&fSite));
if (FAILED(hResult))
hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fSite));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
parentWindow = NULL;
hResult = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
if (SUCCEEDED(hResult))
hResult = oleWindow->GetWindow(&parentWindow);
if (!::IsWindow(parentWindow))
@ -188,16 +188,16 @@ HRESULT STDMETHODCALLTYPE CBrandBand::SetSite(IUnknown* pUnkSite)
SubclassWindow(hwnd);
// take advice to watch events
hResult = pUnkSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
if (SUCCEEDED(hResult))
{
hResult = serviceProvider->QueryService(
SID_SBrandBand, IID_IProfferService, reinterpret_cast<void **>(&profferService));
SID_SBrandBand, IID_PPV_ARG(IProfferService, &profferService));
if (SUCCEEDED(hResult))
hResult = profferService->ProfferService(SID_SBrandBand,
static_cast<IServiceProvider *>(this), &fProfferCookie);
hResult = serviceProvider->QueryService(SID_SShellBrowser,
IID_IBrowserService, reinterpret_cast<void **>(&browserService));
IID_PPV_ARG(IBrowserService, &browserService));
if (SUCCEEDED(hResult))
hResult = AtlAdvise(browserService, static_cast<IDispatch *>(this), DIID_DWebBrowserEvents, &fAdviseCookie);
}
@ -355,8 +355,8 @@ HRESULT STDMETHODCALLTYPE CBrandBand::QueryService(REFGUID guidService, REFIID r
if (IsEqualIID(guidService, SID_SBrandBand))
return this->QueryInterface(riid, ppvObject);
hResult = fSite->QueryInterface(IID_IServiceProvider, reinterpret_cast<void **>(&serviceProvider));
if (FAILED(hResult))
hResult = fSite->QueryInterface(IID_PPV_ARG(IServiceProvider, &serviceProvider));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return serviceProvider->QueryService(guidService, riid, ppvObject);
}
@ -470,20 +470,5 @@ LRESULT CBrandBand::OnTimer(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHand
HRESULT CreateBrandBand(REFIID riid, void **ppv)
{
CComObject<CBrandBand> *theMenuBar;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theMenuBar = new CComObject<CBrandBand>);
if (theMenuBar == NULL)
return E_OUTOFMEMORY;
hResult = theMenuBar->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theMenuBar;
return hResult;
}
return S_OK;
return ShellObjectCreator<CBrandBand>(riid, ppv);
}

View File

@ -70,6 +70,8 @@ IDR_REGTREEOPTIONS REGISTRY "res/regtreeoptions.rgs"
//#include "lang/zh-TW.rc"
/* UTF-8 */
#pragma code_page(65001)
#ifdef LANGUAGE_BG_BG
#include "lang/bg-BG.rc"
#endif

View File

@ -20,8 +20,6 @@
#include "precomp.h"
extern DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter);
/*************************************************************************
* InitOCHostClass [BROWSEUI.101]
*/
@ -30,14 +28,6 @@ extern "C" void WINAPI InitOCHostClass(long param8)
// forwards to shdocvw
}
/*************************************************************************
* SHOpenFolderWindow [BROWSEUI.102]
*/
extern "C" long WINAPI SHOpenFolderWindow(IEThreadParamBlock *param8)
{
return 0;
}
/*************************************************************************
* SHCreateSavedWindows [BROWSEUI.105]
* Called to recreate explorer windows from previous session
@ -46,22 +36,10 @@ extern "C" void WINAPI SHCreateSavedWindows()
{
}
/*************************************************************************
* SHCreateFromDesktop [BROWSEUI.106]
* parameter is a FolderInfo
*/
extern "C" long WINAPI SHCreateFromDesktop(long param8)
{
return -1;
}
/*************************************************************************
* SHExplorerParseCmdLine [BROWSEUI.107]
*/
extern "C" long WINAPI SHExplorerParseCmdLine(LPCTSTR commandLine)
{
return -1;
}
/****** MOVED TO parsecmdline.cpp ******/
/*************************************************************************
* UEMRegisterNotify [BROWSEUI.118]
@ -94,54 +72,6 @@ extern "C" long WINAPI IDataObject_GetDeskBandState(long param8)
return -1;
}
/*************************************************************************
* SHCreateIETHREADPARAM [BROWSEUI.123]
*/
extern "C" IEThreadParamBlock *WINAPI SHCreateIETHREADPARAM(
long param8, long paramC, IUnknown *param10, IUnknown *param14)
{
IEThreadParamBlock *result;
result = (IEThreadParamBlock *)LocalAlloc(LMEM_ZEROINIT, 256);
if (result == NULL)
return NULL;
result->offset0 = param8;
result->offset8 = paramC;
result->offsetC = param10;
if (param10 != NULL)
param10->AddRef();
result->offset14 = param14;
if (param14 != NULL)
param14->AddRef();
return result;
}
/*************************************************************************
* SHCloneIETHREADPARAM [BROWSEUI.124]
*/
extern "C" IEThreadParamBlock *WINAPI SHCloneIETHREADPARAM(IEThreadParamBlock *param)
{
IEThreadParamBlock *result;
result = (IEThreadParamBlock *)LocalAlloc(LMEM_FIXED, 256);
if (result == NULL)
return NULL;
memcpy(result, param, 0x40 * 4);
if (result->directoryPIDL != NULL)
result->directoryPIDL = ILClone(result->directoryPIDL);
if (result->offset7C != NULL)
result->offset7C = ILClone(result->offset7C);
if (result->offset80 != NULL)
result->offset80 = ILClone(result->offset80);
if (result->offset70 != NULL)
result->offset70->AddRef();
#if 0
if (result->offsetC != NULL)
result->offsetC->Method2C();
#endif
return result;
}
/*************************************************************************
* SHParseIECommandLine [BROWSEUI.125]
*/
@ -150,40 +80,6 @@ extern "C" long WINAPI SHParseIECommandLine(long param8, long paramC)
return -1;
}
/*************************************************************************
* SHDestroyIETHREADPARAM [BROWSEUI.126]
*/
extern "C" void WINAPI SHDestroyIETHREADPARAM(IEThreadParamBlock *param)
{
if (param == NULL)
return;
if (param->directoryPIDL != NULL)
ILFree(param->directoryPIDL);
if (param->offset7C != NULL)
ILFree(param->offset7C);
if ((param->offset4 & 0x80000) == 0 && param->offset80 != NULL)
ILFree(param->offset80);
if (param->offset14 != NULL)
param->offset14->Release();
if (param->offset70 != NULL)
param->offset70->Release();
if (param->offset78 != NULL)
param->offset78->Release();
if (param->offsetC != NULL)
param->offsetC->Release();
if (param->offsetF8 != NULL)
param->offsetF8->Release();
LocalFree(param);
}
/*************************************************************************
* SHOnCWMCommandLine [BROWSEUI.127]
*/
extern "C" HRESULT WINAPI SHOnCWMCommandLine(long param8)
{
return E_NOTIMPL;
}
/*************************************************************************
* Channel_GetFolderPidl [BROWSEUI.128]
*/
@ -264,36 +160,3 @@ extern "C" BOOL WINAPI SHIsExplorerBrowser()
{
return TRUE;
}
// 75FA56C1h
// (pidl, 0, -1, 1)
// this function should handle creating a new process if needed, but I'm leaving that out for now
// this function always opens a new window - it does NOT check for duplicates
/*************************************************************************
* SHOpenNewFrame [BROWSEUI.103]
*/
extern "C" HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, long param14)
{
IEThreadParamBlock *parameters;
HANDLE threadHandle;
DWORD threadID;
parameters = SHCreateIETHREADPARAM(0, 1, paramC, NULL);
if (parameters == NULL)
{
ILFree(pidl);
return E_OUTOFMEMORY;
}
if (paramC != NULL)
parameters->offset10 = param10;
parameters->directoryPIDL = pidl;
parameters->offset4 = param14;
threadHandle = CreateThread(NULL, 0x10000, BrowserThreadProc, parameters, 0, &threadID);
if (threadHandle != NULL)
{
CloseHandle(threadHandle);
return S_OK;
}
SHDestroyIETHREADPARAM(parameters);
return E_FAIL;
}

View File

@ -0,0 +1,602 @@
#include "precomp.h"
#include <shlwapi.h>
#include <shlwapi_undoc.h>
#define PROXY_DESKTOP_CLASS L"Proxy Desktop"
BOOL g_SeparateFolders = FALSE;
// fields indented more are unknown ;P
struct HNFBlock
{
UINT cbSize;
DWORD offset4;
DWORD offset8;
DWORD offsetC;
DWORD offset10;
DWORD offset14;
DWORD offset18;
DWORD offset1C;
DWORD offset20;
DWORD offset24;
DWORD offset28;
DWORD offset2C;
DWORD offset30;
UINT directoryPidlLength;
UINT pidlSize7C;
UINT pidlSize80;
UINT pathLength;
};
extern DWORD WINAPI BrowserThreadProc(LPVOID lpThreadParameter);
class CProxyDesktop :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
public CWindowImpl < CProxyDesktop, CWindow, CFrameWinTraits >
{
IEThreadParamBlock * m_Parameters;
LPITEMIDLIST m_rootPidl;
public:
CProxyDesktop(IEThreadParamBlock * parameters) :
m_Parameters(parameters)
{
}
virtual ~CProxyDesktop()
{
}
LRESULT OnMessage1037(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DbgPrint("Proxy Desktop message 1037.\n");
bHandled = TRUE;
return TRUE;
}
LRESULT OnOpenNewWindow(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
DbgPrint("Proxy Desktop message 1035 received.\n");
bHandled = TRUE;
SHOnCWMCommandLine((HANDLE) lParam);
return 0;
}
DECLARE_WND_CLASS_EX(PROXY_DESKTOP_CLASS, CS_SAVEBITS | CS_DROPSHADOW, COLOR_3DFACE)
BEGIN_MSG_MAP(CProxyDesktop)
MESSAGE_HANDLER(WM_EXPLORER_1037, OnMessage1037)
MESSAGE_HANDLER(WM_EXPLORER_OPEN_NEW_WINDOW, OnOpenNewWindow)
END_MSG_MAP()
};
static CProxyDesktop * CreateProxyDesktop(IEThreadParamBlock * parameters)
{
return new CProxyDesktop(parameters);
}
HWND FindShellProxy(LPITEMIDLIST pidl)
{
if (!g_SeparateFolders)
{
HWND shell = GetShellWindow();
if (shell)
{
DbgPrint("Found main desktop.\n");
return shell;
}
}
else
{
DbgPrint("Separate folders setting enabled. Ignoring main desktop.\n");
}
HWND proxy = FindWindow(PROXY_DESKTOP_CLASS, NULL);
if (proxy)
{
DbgPrint("Found proxy desktop.\n");
return proxy;
}
return NULL;
}
HANDLE MakeSharedPacket(IEThreadParamBlock * threadParams, LPCWSTR strPath, int dwProcessId)
{
HNFBlock* hnfData;
UINT sharedBlockSize = sizeof(*hnfData);
UINT directoryPidlLength = 0;
UINT pidlSize7C = 0;
UINT pidlSize80 = 0;
UINT pathLength = 0;
LPITEMIDLIST pidl80 = threadParams->offset80;
// Count the total length of the message packet
// directory PIDL
if (threadParams->directoryPIDL)
{
directoryPidlLength = ILGetSize(threadParams->directoryPIDL);
sharedBlockSize += directoryPidlLength;
DbgPrint("directoryPidlLength=%d\n", directoryPidlLength);
}
// another PIDL
if (threadParams->offset7C)
{
pidlSize7C = ILGetSize(threadParams->offset7C);
sharedBlockSize += pidlSize7C;
DbgPrint("pidlSize7C=%d\n", pidlSize7C);
}
// This flag indicates the presence of another pidl?
if (!(threadParams->offset84 & 0x8000))
{
if (pidl80)
{
pidlSize80 = ILGetSize(pidl80);
sharedBlockSize += pidlSize80;
DbgPrint("pidlSize80=%d\n", pidlSize7C);
}
}
else
{
DbgPrint("pidl80 sent by value = %p\n", pidl80);
pidlSize80 = 4;
sharedBlockSize += pidlSize80;
}
// The path string
if (strPath)
{
pathLength = 2 * lstrlenW(strPath) + 2;
sharedBlockSize += pathLength;
DbgPrint("pathLength=%d\n", pidlSize7C);
}
DbgPrint("sharedBlockSize=%d\n", sharedBlockSize);
// Allocate and fill the shared section
HANDLE hShared = SHAllocShared(0, sharedBlockSize, dwProcessId);
if (!hShared)
{
DbgPrint("Shared section alloc error.\n");
return 0;
}
PBYTE target = (PBYTE) SHLockShared(hShared, dwProcessId);
if (!target)
{
DbgPrint("Shared section lock error. %d\n", GetLastError());
SHFreeShared(hShared, dwProcessId);
return 0;
}
// Basic information
hnfData = (HNFBlock*) target;
hnfData->cbSize = sharedBlockSize;
hnfData->offset4 = (DWORD) (threadParams->dwFlags);
hnfData->offset8 = (DWORD) (threadParams->offset8);
hnfData->offsetC = (DWORD) (threadParams->offset74);
hnfData->offset10 = (DWORD) (threadParams->offsetD8);
hnfData->offset14 = (DWORD) (threadParams->offset84);
hnfData->offset18 = (DWORD) (threadParams->offset88);
hnfData->offset1C = (DWORD) (threadParams->offset8C);
hnfData->offset20 = (DWORD) (threadParams->offset90);
hnfData->offset24 = (DWORD) (threadParams->offset94);
hnfData->offset28 = (DWORD) (threadParams->offset98);
hnfData->offset2C = (DWORD) (threadParams->offset9C);
hnfData->offset30 = (DWORD) (threadParams->offsetA0);
hnfData->directoryPidlLength = 0;
hnfData->pidlSize7C = 0;
hnfData->pidlSize80 = 0;
hnfData->pathLength = 0;
target += sizeof(*hnfData);
// Copy the directory pidl contents
if (threadParams->directoryPIDL)
{
memcpy(target, threadParams->directoryPIDL, directoryPidlLength);
target += directoryPidlLength;
hnfData->directoryPidlLength = directoryPidlLength;
}
// Copy the other pidl contents
if (threadParams->offset7C)
{
memcpy(target, threadParams->offset7C, pidlSize7C);
target += pidlSize7C;
hnfData->pidlSize7C = pidlSize7C;
}
// copy the third pidl
if (threadParams->offset84 & 0x8000)
{
*(LPITEMIDLIST*) target = pidl80;
target += pidlSize80;
hnfData->pidlSize80 = pidlSize80;
}
else if (pidl80)
{
memcpy(target, pidl80, pidlSize80);
target += pidlSize80;
hnfData->pidlSize80 = pidlSize80;
}
// and finally the path string
if (strPath)
{
memcpy(target, strPath, pathLength);
hnfData->pathLength = pathLength;
}
SHUnlockShared(hnfData);
return hShared;
}
PIE_THREAD_PARAM_BLOCK ParseSharedPacket(HANDLE hData)
{
HNFBlock * hnfData;
PBYTE block;
int pid;
PIE_THREAD_PARAM_BLOCK params = NULL;
if (!hData)
goto cleanup0;
pid = GetCurrentProcessId();
block = (PBYTE) SHLockShared(hData, pid);
hnfData = (HNFBlock *) block;
if (!block)
goto cleanup2;
if (hnfData->cbSize < sizeof(HNFBlock))
goto cleanup2;
params = SHCreateIETHREADPARAM(0, hnfData->offset8, 0, 0);
if (!params)
goto cleanup2;
params->dwFlags = hnfData->offset4;
params->offset8 = hnfData->offset8;
params->offset74 = hnfData->offsetC;
params->offsetD8 = hnfData->offset10;
params->offset84 = hnfData->offset14;
params->offset88 = hnfData->offset18;
params->offset8C = hnfData->offset1C;
params->offset90 = hnfData->offset20;
params->offset94 = hnfData->offset24;
params->offset98 = hnfData->offset28;
params->offset9C = hnfData->offset2C;
params->offsetA0 = hnfData->offset30;
block += sizeof(*hnfData);
if (hnfData->directoryPidlLength)
{
LPITEMIDLIST pidl = NULL;
if (*block)
pidl = ILClone((LPITEMIDLIST) block);
params->directoryPIDL = pidl;
block += hnfData->directoryPidlLength;
}
if (hnfData->pidlSize7C)
{
LPITEMIDLIST pidl = NULL;
if (*block)
pidl = ILClone((LPITEMIDLIST) block);
params->offset7C = pidl;
block += hnfData->pidlSize80;
}
if (hnfData->pidlSize80)
{
if (!(params->offset84 & 0x8000))
{
params->offset80 = *(LPITEMIDLIST *) block;
}
else
{
LPITEMIDLIST pidl = NULL;
if (*block)
pidl = ILClone((LPITEMIDLIST) block);
params->offset80 = pidl;
}
block += hnfData->pidlSize80;
}
if (hnfData->pathLength)
{
CComPtr<IShellFolder> psfDesktop;
PWSTR strPath = (PWSTR) block;
if (FAILED(SHGetDesktopFolder(&psfDesktop)))
{
params->directoryPIDL = NULL;
goto cleanup0;
}
if (FAILED(psfDesktop->ParseDisplayName(NULL, NULL, strPath, NULL, &params->directoryPIDL, NULL)))
{
params->directoryPIDL = NULL;
goto cleanup0;
}
}
cleanup2:
SHUnlockShared(hnfData);
SHFreeShared(hData, pid);
cleanup0:
if (!params->directoryPIDL)
{
SHDestroyIETHREADPARAM(params);
return NULL;
}
return params;
}
/*************************************************************************
* SHCreateIETHREADPARAM [BROWSEUI.123]
*/
extern "C" IEThreadParamBlock *WINAPI SHCreateIETHREADPARAM(
long param8, long paramC, IUnknown *param10, IUnknown *param14)
{
IEThreadParamBlock *result;
DbgPrint("SHCreateIETHREADPARAM\n");
result = (IEThreadParamBlock *) LocalAlloc(LMEM_ZEROINIT, 256);
if (result == NULL)
return NULL;
result->offset0 = param8;
result->offset8 = paramC;
result->offsetC = param10;
if (param10 != NULL)
param10->AddRef();
result->offset14 = param14;
if (param14 != NULL)
param14->AddRef();
return result;
}
/*************************************************************************
* SHCloneIETHREADPARAM [BROWSEUI.124]
*/
extern "C" IEThreadParamBlock *WINAPI SHCloneIETHREADPARAM(IEThreadParamBlock *param)
{
IEThreadParamBlock *result;
DbgPrint("SHCloneIETHREADPARAM\n");
result = (IEThreadParamBlock *) LocalAlloc(LMEM_FIXED, 256);
if (result == NULL)
return NULL;
memcpy(result, param, 0x40 * 4);
if (result->directoryPIDL != NULL)
result->directoryPIDL = ILClone(result->directoryPIDL);
if (result->offset7C != NULL)
result->offset7C = ILClone(result->offset7C);
if (result->offset80 != NULL)
result->offset80 = ILClone(result->offset80);
if (result->offset70 != NULL)
result->offset70->AddRef();
#if 0
if (result->offsetC != NULL)
result->offsetC->Method2C();
#endif
return result;
}
/*************************************************************************
* SHDestroyIETHREADPARAM [BROWSEUI.126]
*/
extern "C" void WINAPI SHDestroyIETHREADPARAM(IEThreadParamBlock *param)
{
DbgPrint("SHDestroyIETHREADPARAM\n");
if (param == NULL)
return;
if (param->directoryPIDL != NULL)
ILFree(param->directoryPIDL);
if (param->offset7C != NULL)
ILFree(param->offset7C);
if ((param->dwFlags & 0x80000) == 0 && param->offset80 != NULL)
ILFree(param->offset80);
if (param->offset14 != NULL)
param->offset14->Release();
if (param->offset70 != NULL)
param->offset70->Release();
if (param->offset78 != NULL)
param->offset78->Release();
if (param->offsetC != NULL)
param->offsetC->Release();
if (param->offsetF8 != NULL)
param->offsetF8->Release();
LocalFree(param);
}
/*************************************************************************
* SHOnCWMCommandLine [BROWSEUI.127]
*/
extern "C" BOOL WINAPI SHOnCWMCommandLine(HANDLE hSharedInfo)
{
DbgPrint("SHOnCWMCommandLine\n");
PIE_THREAD_PARAM_BLOCK params = ParseSharedPacket(hSharedInfo);
if (params)
return SHOpenFolderWindow(params);
SHDestroyIETHREADPARAM(params);
return FALSE;
}
/*************************************************************************
* SHOpenFolderWindow [BROWSEUI.102]
* see SHOpenNewFrame below for remarks
*/
extern "C" HRESULT WINAPI SHOpenFolderWindow(PIE_THREAD_PARAM_BLOCK parameters)
{
HANDLE threadHandle;
DWORD threadID;
WCHAR debugStr[MAX_PATH + 1];
SHGetPathFromIDListW(parameters->directoryPIDL, debugStr);
DbgPrint("SHOpenFolderWindow %p(%S)\n", parameters->directoryPIDL, debugStr);
PIE_THREAD_PARAM_BLOCK paramsCopy = SHCloneIETHREADPARAM(parameters);
SHGetInstanceExplorer(&(paramsCopy->offsetF8));
threadHandle = CreateThread(NULL, 0x10000, BrowserThreadProc, paramsCopy, 0, &threadID);
if (threadHandle != NULL)
{
CloseHandle(threadHandle);
return S_OK;
}
SHDestroyIETHREADPARAM(paramsCopy);
return E_FAIL;
}
// 75FA56C1h
// (pidl, 0, -1, 1)
// this function should handle creating a new process if needed, but I'm leaving that out for now
// this function always opens a new window - it does NOT check for duplicates
/*************************************************************************
* SHOpenNewFrame [BROWSEUI.103]
*/
extern "C" HRESULT WINAPI SHOpenNewFrame(LPITEMIDLIST pidl, IUnknown *paramC, long param10, DWORD dwFlags)
{
IEThreadParamBlock *parameters;
DbgPrint("SHOpenNewFrame\n");
parameters = SHCreateIETHREADPARAM(0, 1, paramC, NULL);
if (parameters == NULL)
{
ILFree(pidl);
return E_OUTOFMEMORY;
}
if (paramC != NULL)
parameters->offset10 = param10;
parameters->directoryPIDL = pidl;
parameters->dwFlags = dwFlags;
HRESULT hr = SHOpenFolderWindow(parameters);
SHDestroyIETHREADPARAM(parameters);
return hr;
}
/*************************************************************************
* SHCreateFromDesktop [BROWSEUI.106]
* parameter is a FolderInfo
*/
BOOL WINAPI SHCreateFromDesktop(ExplorerCommandLineParseResults * parseResults)
{
DbgPrint("SHCreateFromDesktop\n");
IEThreadParamBlock * parameters = SHCreateIETHREADPARAM(0, 0, 0, 0);
if (!parameters)
return FALSE;
PCWSTR strPath = NULL;
if (parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_STRING)
{
if (parseResults->pidlPath)
{
WARN("strPath and pidlPath are both assigned. This shouldn't happen.\n");
}
strPath = parseResults->strPath;
}
parameters->dwFlags = parseResults->dwFlags;
parameters->offset8 = parseResults->offsetC;
LPITEMIDLIST pidl = parseResults->pidlPath ? ILClone(parseResults->pidlPath) : NULL;
if (!pidl && parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_STRING)
{
if (parseResults->strPath && parseResults->strPath[0])
{
pidl = ILCreateFromPathW(parseResults->strPath);
}
}
parameters->directoryPIDL = pidl;
// Try to find the owner of the idlist, if we aren't running /SEPARATE
HWND desktop = NULL;
if (!(parseResults->dwFlags & SH_EXPLORER_CMDLINE_FLAG_SEPARATE))
desktop = FindShellProxy(parameters->directoryPIDL);
// If found, ask it to open the new window
if (desktop)
{
DbgPrint("Found desktop hwnd=%p\n", desktop);
DWORD dwProcessId;
GetWindowThreadProcessId(desktop, &dwProcessId);
AllowSetForegroundWindow(dwProcessId);
HANDLE hShared = MakeSharedPacket(parameters, strPath, dwProcessId);
if (hShared)
{
DbgPrint("Sending open message...\n");
PostMessageW(desktop, WM_EXPLORER_OPEN_NEW_WINDOW, 0, (LPARAM) hShared);
}
SHDestroyIETHREADPARAM(parameters);
return TRUE;
}
DbgPrint("Desktop not found or separate flag requested.\n");
// Else, start our own message loop!
HRESULT hr = CoInitialize(NULL);
CProxyDesktop * proxy = CreateProxyDesktop(parameters);
if (proxy)
{
LONG refCount;
CComPtr<IUnknown> thread;
if (SHCreateThreadRef(&refCount, &thread) >= 0)
{
SHSetInstanceExplorer(thread);
if (strPath)
parameters->directoryPIDL = ILCreateFromPath(strPath);
SHOpenFolderWindow(parameters);
parameters = NULL;
thread.Release();
}
MSG Msg;
while (GetMessageW(&Msg, 0, 0, 0) && refCount)
{
TranslateMessage(&Msg);
DispatchMessageW(&Msg);
}
delete proxy;
}
if (SUCCEEDED(hr))
CoUninitialize();
SHDestroyIETHREADPARAM(parameters);
return TRUE;
}

File diff suppressed because it is too large Load Diff

View File

@ -20,29 +20,22 @@
#pragma once
static const int gBackCommandID = 0xa121;
static const int gForwardCommandID = 0xa122;
static const int gUpLevelCommandID = 0xa022;
static const int gSearchCommandID = 1003;
static const int gFoldersCommandID = 1004;
static const int gMoveToCommandID = 0x701f;
static const int gCopyToCommandID = 0x701e;
static const int gDeleteCommandID = 0x7011;
static const int gUndoCommandID = 0x701b;
static const int gViewsCommandID = 0x7031;
static const int gMoveToCommandID = FCIDM_SHVIEW_MOVETO;
static const int gCopyToCommandID = FCIDM_SHVIEW_COPYTO;
static const int gDeleteCommandID = FCIDM_SHVIEW_DELETE;
static const int gUndoCommandID = FCIDM_SHVIEW_UNDO;
static const int gViewsCommandID = FCIDM_SHVIEW_AUTOARRANGE;
static const int gStopCommandID = 1010;
static const int gRefreshCommandID = 0xa220;
static const int gHomeCommandID = 1012;
static const int gMapDriveCommandID = 41089;
static const int gDisconnectCommandID = 41090;
static const int gFavoritesCommandID = 1015;
static const int gHistoryCommandID = 1016;
static const int gFullScreenCommandID = 1017;
static const int gPropertiesCommandID = 0x7013;
static const int gCutCommandID = 0x7018;
static const int gCopyCommandID = 0x7019;
static const int gPasteCommandID = 0x701a;
static const int gFolderOptionsCommandID = 41251;
static const int gPropertiesCommandID = FCIDM_SHVIEW_PROPERTIES;
static const int gCutCommandID = FCIDM_SHVIEW_CUT;
static const int gCopyCommandID = FCIDM_SHVIEW_COPY;
static const int gPasteCommandID = FCIDM_SHVIEW_INSERT;
class CMenuCallback :
public CComObjectRootEx<CComMultiThreadModelNoCS>,
@ -52,7 +45,7 @@ private:
CComPtr<IShellMenu> fFavoritesMenu;
public:
CMenuCallback();
~CMenuCallback();
virtual ~CMenuCallback();
HRESULT STDMETHODCALLTYPE GetObject(LPSMDATA psmd, REFIID riid, void **ppvObject);
public:
@ -96,11 +89,14 @@ public:
HWND fToolbarWindow;
DWORD fAdviseCookie;
CComPtr<IBandProxy> fBandProxy;
BOOL fSizing;
POINT fStartPosition;
LONG fStartHeight;
public:
CInternetToolbar();
~CInternetToolbar();
virtual ~CInternetToolbar();
void AddDockItem(IUnknown *newItem, int bandID, int flags);
HRESULT ReserveBorderSpace();
HRESULT ReserveBorderSpace(LONG maxHeight = -1);
HRESULT CreateMenuBar(IShellMenu **menuBar);
HRESULT CreateBrandBand(IUnknown **logoBar);
HRESULT CreateToolsBar(IUnknown **toolsBar);
@ -196,24 +192,31 @@ public:
LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnSetCursor(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnTipText(UINT idControl, NMHDR *pNMHDR, BOOL &bHandled);
LRESULT OnCommand(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnNotify(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnLDown(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnLUp(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
LRESULT OnMouseMove(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL &bHandled);
BEGIN_MSG_MAP(CInternetToolbar)
COMMAND_ID_HANDLER(gBackCommandID, OnTravelBack)
COMMAND_ID_HANDLER(gForwardCommandID, OnTravelForward)
COMMAND_ID_HANDLER(gUpLevelCommandID, OnUpLevel)
COMMAND_ID_HANDLER(IDM_GOTO_BACK, OnTravelBack)
COMMAND_ID_HANDLER(IDM_GOTO_FORWARD, OnTravelForward)
COMMAND_ID_HANDLER(IDM_GOTO_UPONELEVEL, OnUpLevel)
COMMAND_ID_HANDLER(gSearchCommandID, OnSearch)
COMMAND_ID_HANDLER(gFoldersCommandID, OnFolders)
COMMAND_RANGE_HANDLER(0x7000, 0x7fff, OnForwardToCommandTarget)
NOTIFY_HANDLER(0, TBN_DROPDOWN, OnMenuDropDown)
NOTIFY_HANDLER(0, TBN_QUERYINSERT, OnQueryInsert)
NOTIFY_HANDLER(0, TBN_QUERYDELETE, OnQueryDelete)
MESSAGE_HANDLER(WM_COMMAND, OnNavigateCommand)
MESSAGE_HANDLER(WM_COMMAND, OnCommand)
MESSAGE_HANDLER(WM_CONTEXTMENU, OnContextMenu)
MESSAGE_HANDLER(WM_SIZE, OnSize)
MESSAGE_HANDLER(WM_SETCURSOR, OnSetCursor)
NOTIFY_CODE_HANDLER(TTN_NEEDTEXTW, OnTipText)
MESSAGE_HANDLER(WM_NOTIFY, OnNotify)
MESSAGE_HANDLER(WM_LBUTTONDOWN, OnLDown)
MESSAGE_HANDLER(WM_LBUTTONUP, OnLUp)
MESSAGE_HANDLER(WM_MOUSEMOVE, OnMouseMove)
END_MSG_MAP()
DECLARE_REGISTRY_RESOURCEID(IDR_INTERNETTOOLBAR)

View File

@ -246,7 +246,7 @@ END
STRINGTABLE
BEGIN
IDS_UP "Aufwärts"
IDS_UP "Übergeordneter Ordner"
END
STRINGTABLE
@ -254,3 +254,10 @@ BEGIN
IDS_BACK "Zurück"
IDS_FORWARD "Vorwärts"
END
STRINGTABLE
BEGIN
IDS_STANDARD_TOOLBAR, "|Zurück|Vorwärts|Übergeordneter Ordner|Suchen|Ordner|Verschieben nach|Kopieren nach|Löschen|Rückgängig|Ansicht|Stop|Aktualisieren|Startseite|Netzlaufwerk verbinden|Netzlaufwerk trennen|Favoriten|Verlauf|Vollbild|Eigenschaften|Ausschneiden|Kopieren|Einfügen|Ordneroptionen||"
END

View File

@ -119,6 +119,7 @@ BEGIN
"B", IDM_FAVORITES_ORGANIZEFAVORITES, VIRTKEY, CONTROL, NOINVERT
VK_LEFT, IDM_GOTO_BACK, VIRTKEY, ALT
VK_RIGHT, IDM_GOTO_FORWARD, VIRTKEY, ALT
VK_BACK, 41010, NOINVERT, VIRTKEY
"W", IDM_FILE_CLOSE, VIRTKEY, CONTROL, NOINVERT
"E", IDM_EXPLORERBAR_SEARCH, VIRTKEY, CONTROL, NOINVERT
"I", IDM_EXPLORERBAR_FAVORITES, VIRTKEY, CONTROL, NOINVERT
@ -254,3 +255,9 @@ BEGIN
IDS_BACK "Back"
IDS_FORWARD "Forward"
END
STRINGTABLE
BEGIN
IDS_STANDARD_TOOLBAR, "|Back|Forward|Up|Search|Folders|Move To|Copy To|Delete|Undo|Views|Stop|Refresh|Home|Map Drive|Disconnect|Favorites|History|Full Screen|Properties|Cut|Copy|Paste|Folder Options||"
END

View File

@ -0,0 +1,417 @@
/*
* ReactOS browseui
*
* Copyright 2014 David Quintana <gigaherz@gmail.com>
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "precomp.h"
#include <strsafe.h>
extern "C"
BOOL WINAPI GUIDFromStringW(
_In_ PCWSTR psz,
_Out_ LPGUID pguid
);
static BOOL _CopyAndUnquoteText(LPCWSTR strFieldSource, LPWSTR strField, size_t cchField)
{
WCHAR cChar;
PWSTR tmpField = strField;
size_t lenField = 1;
BOOL inQuote = FALSE;
// Remove leading whitespace
cChar = *strFieldSource;
while (cChar == L' ' || cChar == L'\t' || cChar == L'\n' || cChar == L'\r')
{
strFieldSource = CharNextW(strFieldSource);
cChar = *strFieldSource;
}
while (cChar && cChar != L'=' && cChar != L',')
{
if (cChar == L'"')
{
// [1] is always valid read because of null-termination
if (inQuote && strFieldSource[1] == L'"')
{
if (lenField < cchField)
{
// Append
*(tmpField++) = L'"';
++lenField;
}
// Skip second quote
strFieldSource++;
}
else
{
inQuote = !inQuote;
}
}
else
{
if (inQuote || (cChar != L'=' && cChar != L','))
{
if (lenField < cchField)
{
// Append
*(tmpField++) = cChar;
++lenField;
}
}
}
strFieldSource = CharNextW(strFieldSource);
cChar = *strFieldSource;
}
// Remove trailing whitespace
while (tmpField > strField)
{
tmpField = CharPrevW(strField, tmpField);
cChar = *tmpField;
if (cChar != L' ' && cChar != L'\t' && cChar != L'\n' && cChar != L'\r')
{
tmpField = CharNextW(tmpField);
break;
}
}
// Terminate output string
*tmpField = 0;
return TRUE;
}
static BOOL _FindNextArg(PCWSTR * pstrFieldSource)
{
PCWSTR strFieldSource = *pstrFieldSource;
WCHAR cChar = *strFieldSource;
BOOL inQuote = FALSE;
while (cChar)
{
if (!inQuote && (cChar == L'=' || cChar == L','))
break;
if (cChar == L'"')
inQuote = !inQuote;
strFieldSource = CharNextW(strFieldSource);
cChar = *strFieldSource;
}
if (cChar == 0)
{
*pstrFieldSource = strFieldSource;
return FALSE;
}
*pstrFieldSource = CharNextW(strFieldSource);
return TRUE;
}
static PCWSTR _FindFirstField(PCWSTR strFieldSource)
{
//Find end of first arg, because
// behaviour is different if the first separator is an '='
BOOL inQuote = FALSE;
PCWSTR tmpArgs = strFieldSource;
WCHAR cChar = *tmpArgs;
while (cChar)
{
if (cChar == L'=')
break;
if (cChar == L',')
break;
if (cChar == L'\"')
inQuote = !inQuote;
tmpArgs = CharNextW(tmpArgs);
cChar = *tmpArgs;
}
// Skip the text before the first equal sign, if not quoted, unless the arg 0 was requested.
if (*tmpArgs == L'=' && !inQuote)
{
strFieldSource = ++tmpArgs;
TRACE("Skipped content before the first '=', remainder=%S\n", strFieldSource);
}
return strFieldSource;
}
static BOOL _ReadNextArg(PCWSTR * pstrFieldSource, PWSTR strField, size_t cchField)
{
// Copy and unquote text
_CopyAndUnquoteText(*pstrFieldSource, strField, cchField);
return _FindNextArg(pstrFieldSource);
}
static LPITEMIDLIST _ILReadFromSharedMemory(PCWSTR strField)
{
LPITEMIDLIST ret = NULL;
// Ensure it really is an IDLIST-formatted parameter
// Format for IDLIST params: ":pid:shared"
if (*strField != L':')
return NULL;
HANDLE hData = (HANDLE) StrToIntW(strField + 1);
PWSTR strSecond = StrChrW(strField + 1, L':');
if (strSecond)
{
int pid = StrToIntW(strSecond + 1);
void* pvShared = SHLockShared(hData, pid);
if (pvShared)
{
ret = ILClone((LPCITEMIDLIST) pvShared);
SHUnlockShared(pvShared);
SHFreeShared(hData, pid);
}
}
return ret;
}
static HRESULT _ParsePathToPidl(PWSTR strPath, LPITEMIDLIST * pidl)
{
CComPtr<IShellFolder> psfDesktop;
HRESULT hr = SHGetDesktopFolder(&psfDesktop);
if (FAILED(hr))
return hr;
return psfDesktop->ParseDisplayName(NULL, NULL, strPath, NULL, pidl, NULL);
}
static LPITEMIDLIST _GetDocumentsPidl()
{
CComPtr<IShellFolder> ppshf;
LPITEMIDLIST pidl;
WCHAR guid [] = L"::{450d8fba-ad25-11d0-98a8-0800361b1103}";
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_MYDOCUMENTS, &pidl)))
return pidl;
if (FAILED(SHGetDesktopFolder(&ppshf)))
return NULL;
if (FAILED(ppshf->ParseDisplayName(NULL, NULL, guid, NULL, &pidl, NULL)))
return NULL;
return pidl;
}
/*************************************************************************
* SHExplorerParseCmdLine [BROWSEUI.107]
*/
extern "C"
UINT
WINAPI
SHExplorerParseCmdLine(ExplorerCommandLineParseResults * pInfo)
{
WCHAR strField[MAX_PATH];
WCHAR strDir[MAX_PATH];
PCWSTR strCmdLine = GetCommandLineW();
PCWSTR strFieldArray = PathGetArgsW(strCmdLine);
if (!*strFieldArray)
{
pInfo->dwFlags = 9;
pInfo->pidlPath = _GetDocumentsPidl();
if (!pInfo->pidlPath)
{
GetWindowsDirectoryW(strDir, MAX_PATH);
PathStripToRootW(strDir);
pInfo->pidlPath = ILCreateFromPathW(strDir);
}
return (LONG) (pInfo->pidlPath);
}
PCWSTR strNextArg = _FindFirstField(strFieldArray);
BOOL hasNext = TRUE;
hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
while (TRUE)
{
// Basic flags-only params first
if (!StrCmpIW(strField, L"/N"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_N | SH_EXPLORER_CMDLINE_FLAG_ONE;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/S"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_S;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/E"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_E;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/SELECT"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_SELECT;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/NOUI"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_NOUI;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"-embedding"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_EMBED;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/SEPARATE"))
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_SEPARATE;
TRACE("CmdLine Parser: Parsed %S flag. dwFlags=%08lx\n", strField, pInfo->dwFlags);
}
else if (!StrCmpIW(strField, L"/INPROC"))
{
// No idea what Inproc is supposed to do, but it gets a GUID, and parses it.
TRACE("CmdLine Parser: Found %S flag\n", strField);
if (!hasNext)
return FALSE;
hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
if (!GUIDFromStringW(strField, &(pInfo->guidInproc)))
return FALSE;
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_INPROC;
TRACE("CmdLine Parser: Parsed /INPROC flag. dwFlags=%08lx, guidInproc=%S\n", pInfo->dwFlags, strField);
}
else if (!StrCmpIW(strField, L"/ROOT"))
{
LPITEMIDLIST pidlRoot = NULL;
// The window should be rooted
TRACE("CmdLine Parser: Found %S flag\n", strField);
if (!pInfo->pidlPath)
return FALSE;
if (!hasNext)
return FALSE;
hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
// Root may be a pidl
if (!StrCmpIW(strField, L"/IDLIST"))
{
if (hasNext)
{
hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
}
pidlRoot = _ILReadFromSharedMemory(strField);
}
else
{
// Or just a path string
_ParsePathToPidl(strField, &pidlRoot);
}
pInfo->pidlRoot = pidlRoot;
// The root defaults to the desktop
if (!pidlRoot)
{
if (FAILED(SHGetSpecialFolderLocation(0, CSIDL_DESKTOP, &(pInfo->pidlRoot))))
pInfo->pidlRoot = NULL;
}
// TODO: Create rooted PIDL from pInfo->pidlPath and pInfo->pidlRoot
TRACE("CmdLine Parser: Parsed /ROOT flag. dwFlags=%08lx, pidlRoot=%p\n", pInfo->dwFlags, pInfo->pidlRoot);
}
else
{
// Anything else is part of the target path to browse to
TRACE("CmdLine Parser: Found target path %S\n", strField);
// Which can be a shared-memory itemidlist
if (!StrCmpIW(strField, L"/IDLIST"))
{
LPITEMIDLIST pidlArg;
if (!hasNext)
return FALSE;
hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
pidlArg = _ILReadFromSharedMemory(strField);
if (!pidlArg)
return FALSE;
if (pInfo->pidlPath)
ILFree(pInfo->pidlPath);
pInfo->pidlPath = pidlArg;
TRACE("CmdLine Parser: Parsed target path. dwFlags=%08lx, pidlPath=%p\n", pInfo->dwFlags, pInfo->pidlPath);
}
else
{
// Or just a plain old string.
LPITEMIDLIST pidlPath = ILCreateFromPathW(strField);
pInfo->pidlPath = pidlPath;
if (pidlPath)
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_IDLIST;
TRACE("CmdLine Parser: Parsed target path. dwFlags=%08lx, pidlPath=%p\n", pInfo->dwFlags, pInfo->pidlPath);
}
else
{
// The path could not be parsed into an ID List,
// so pass it on as a plain string.
PWSTR field = StrDupW(strField);
pInfo->strPath = field;
if (field)
{
pInfo->dwFlags |= SH_EXPLORER_CMDLINE_FLAG_STRING;
TRACE("CmdLine Parser: Parsed target path. dwFlags=%08lx, strPath=%S\n", pInfo->dwFlags, field);
}
}
}
}
if (!hasNext)
break;
hasNext = _ReadNextArg(&strNextArg, strField, _countof(strField));
}
return TRUE;
}

View File

@ -23,6 +23,7 @@
#include <exdispid.h>
#include <shlwapi.h>
#include <shlwapi_undoc.h>
#include <undocshell.h>
#include <wine/debug.h>
#include "resource.h"
@ -38,6 +39,7 @@
#include "commonbrowser.h"
#include "globalfoldersettings.h"
#include "regtreeoptions.h"
#include <stdio.h>
WINE_DEFAULT_DEBUG_CHANNEL(browseui);

View File

@ -22,6 +22,7 @@
#define IDM_FILE_CLOSE 0xA021
#define IDM_FILE_EXPLORE_MENU 0xA027
#define IDM_BACKSPACE 0xA032
#define IDM_EXPLORE_ITEM_FIRST 0xA470
#define IDM_EXPLORE_ITEM_LAST 0xA570
#define IDM_FILE_EXPLORE_SEP 0xA028
@ -85,6 +86,7 @@
#define IDS_GOBUTTONLABEL 12656
#define IDS_GOBUTTONTIPTEMPLATE 12657
#define IDS_SEARCHLABEL 12897
#define IDS_STANDARD_TOOLBAR 12624
#define IDS_ADDRESSBANDLABEL 12902
#define IDS_FOLDERSLABEL 12919
#define IDS_HISTORYTEXT 13169

File diff suppressed because it is too large Load Diff

View File

@ -24,10 +24,9 @@ Implements the toolbar band of a cabinet window
#include "precomp.h"
/*
TODO:
**Fix GetBandInfo to calculate size correctly
*/
/* FIXME, I can't include windowsx because it conflicts with some #defines */
#define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp))
#define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp))
class CToolsBand :
public CWindowImpl<CToolsBand, CWindow, CControlWinTraits>,
@ -38,12 +37,12 @@ class CToolsBand :
public IPersistStream
{
private:
IDockingWindowSite *fDockSite;
CComPtr<IDockingWindowSite> fDockSite;
GUID fExecCommandCategory;
CComPtr<IOleCommandTarget> fExecCommandTarget;
public:
CToolsBand();
~CToolsBand();
virtual ~CToolsBand();
public:
// *** IDeskBand methods ***
virtual HRESULT STDMETHODCALLTYPE GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi);
@ -96,37 +95,53 @@ END_COM_MAP()
};
CToolsBand::CToolsBand()
: fDockSite(NULL)
{
fDockSite = NULL;
}
CToolsBand::~CToolsBand()
{
if (fDockSite)
fDockSite->Release();
}
HRESULT STDMETHODCALLTYPE CToolsBand::GetBandInfo(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
{
RECT actualRect;
POINTL actualSize;
POINTL idealSize;
POINTL maxSize;
POINTL itemSize;
::GetWindowRect(m_hWnd, &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 = 400;
pdbi->ptMinSize.y = 38;
pdbi->ptMinSize = idealSize;
}
if (pdbi->dwMask & DBIM_MAXSIZE)
{
pdbi->ptMaxSize.x = 0;
pdbi->ptMaxSize.y = 0;
pdbi->ptMaxSize = maxSize;
}
if (pdbi->dwMask & DBIM_INTEGRAL)
{
pdbi->ptIntegral.x = 0;
pdbi->ptIntegral.y = 0;
pdbi->ptIntegral = itemSize;
}
if (pdbi->dwMask & DBIM_ACTUAL)
{
pdbi->ptActual.x = 400;
pdbi->ptActual.y = 38;
pdbi->ptActual = actualSize;
}
if (pdbi->dwMask & DBIM_TITLE)
wcscpy(pdbi->wszTitle, L"");
@ -185,55 +200,80 @@ static const int moveToImageIndex = 44;
static const int copyToImageIndex = 45;
static const int folderOptionsImageIndex = 46;
enum StandardToolbarButtons {
BtnIdx_Back = 0,
BtnIdx_Forward,
BtnIdx_Up,
BtnIdx_Search,
BtnIdx_Folders,
BtnIdx_MoveTo,
BtnIdx_CopyTo,
BtnIdx_Delete,
BtnIdx_Undo,
BtnIdx_Views,
BtnIdx_Stop,
BtnIdx_Refresh,
BtnIdx_Home,
BtnIdx_MapDrive,
BtnIdx_Disconnect,
BtnIdx_Favorites,
BtnIdx_History,
BtnIdx_FullScreen,
BtnIdx_Properties,
BtnIdx_Cut,
BtnIdx_Copy,
BtnIdx_Paste,
BtnIdx_FolderOptions,
};
const int numShownButtons = 13;
const int numHiddenButtons = 13;
TBBUTTON tbButtonsAdd[numShownButtons + numHiddenButtons] =
{
{backImageIndex, gBackCommandID, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Back")},
{forwardImageIndex, gForwardCommandID, TBSTATE_ENABLED, BTNS_DROPDOWN, {0}, 0, (INT_PTR)_T("Forward")},
{upImageIndex, gUpLevelCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Up")},
{6, -1, TBSTATE_ENABLED, BTNS_SEP},
{searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Search")},
{foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Folders")},
{6, -1, TBSTATE_ENABLED, BTNS_SEP},
{moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Move To")},
{copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Copy To")},
{deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Delete")},
{undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Undo")},
{6, -1, TBSTATE_ENABLED, BTNS_SEP},
{viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, {0}, 0, (INT_PTR)_T("Views")},
{ backImageIndex, IDM_GOTO_BACK, TBSTATE_ENABLED, BTNS_DROPDOWN | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Back },
{ forwardImageIndex, IDM_GOTO_FORWARD, TBSTATE_ENABLED, BTNS_DROPDOWN, { 0 }, 0, BtnIdx_Forward },
{ upImageIndex, IDM_GOTO_UPONELEVEL, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Up },
{ 6, -1, TBSTATE_ENABLED, BTNS_SEP },
{ searchImageIndex, gSearchCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Search },
{ foldersImageIndex, gFoldersCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Folders },
{ 6, -1, TBSTATE_ENABLED, BTNS_SEP },
{ moveToImageIndex, gMoveToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MoveTo },
{ copyToImageIndex, gCopyToCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_CopyTo },
{ deleteImageIndex, gDeleteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Delete },
{ undoImageIndex, gUndoCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Undo },
{ 6, -1, TBSTATE_ENABLED, BTNS_SEP },
{ viewsImageIndex, gViewsCommandID, TBSTATE_ENABLED, BTNS_WHOLEDROPDOWN, { 0 }, 0, BtnIdx_Views },
{0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Stop")},
{0, gRefreshCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Refresh")},
{0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Home")},
{mapDriveImageIndex, gMapDriveCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Map Drive")},
{disconnectImageIndex, gDisconnectCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Disconnect")},
{favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, {0}, 0, (INT_PTR)_T("Favorites")},
{0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("History")},
{0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Full Screen")},
{propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Properties")},
{cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Cut")},
{copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Copy")},
{pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Paste")},
{folderOptionsImageIndex, gFolderOptionsCommandID, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, (INT_PTR)_T("Folder Options")},
{ 0, gStopCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Stop },
{ 0, IDM_VIEW_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Refresh },
{ 0, gHomeCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Home },
{ mapDriveImageIndex, IDM_TOOLS_MAPNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_MapDrive },
{ disconnectImageIndex, IDM_TOOLS_DISCONNECTNETWORKDRIVE, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Disconnect },
{ favoritesImageIndex, gFavoritesCommandID, TBSTATE_ENABLED, BTNS_BUTTON | BTNS_SHOWTEXT, { 0 }, 0, BtnIdx_Favorites },
{ 0, gHistoryCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_History },
{ 0, gFullScreenCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FullScreen },
{ propertiesImageIndex, gPropertiesCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Properties },
{ cutImageIndex, gCutCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Cut },
{ copyImageIndex, gCopyCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Copy },
{ pasteImageIndex, gPasteCommandID, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_Paste },
{ folderOptionsImageIndex, IDM_TOOLS_FOLDEROPTIONS, TBSTATE_ENABLED, BTNS_BUTTON, { 0 }, 0, BtnIdx_FolderOptions },
};
HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite)
{
HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite){
HWND parentWindow;
IOleWindow *oleWindow;
HWND toolbar;
HRESULT hResult;
if (fDockSite != NULL)
fDockSite->Release();
if(fDockSite) fDockSite.Release();
if (pUnkSite == NULL)
return S_OK;
hResult = pUnkSite->QueryInterface(IID_IDockingWindowSite, reinterpret_cast<void **>(&fDockSite));
if (FAILED(hResult))
hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IDockingWindowSite, &fDockSite));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
parentWindow = NULL;
hResult = pUnkSite->QueryInterface(IID_IOleWindow, reinterpret_cast<void **>(&oleWindow));
hResult = pUnkSite->QueryInterface(IID_PPV_ARG(IOleWindow, &oleWindow));
if (SUCCEEDED(hResult))
{
oleWindow->GetWindow(&parentWindow);
@ -242,36 +282,54 @@ HRESULT STDMETHODCALLTYPE CToolsBand::SetSite(IUnknown* pUnkSite)
if (!::IsWindow(parentWindow))
return E_FAIL;
toolbar = CreateWindowEx(TBSTYLE_EX_DOUBLEBUFFER, TOOLBARCLASSNAMEW, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |
WS_CLIPCHILDREN | TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP, 0, 0, 500, 20, parentWindow, NULL,
_AtlBaseModule.GetModuleInstance(), 0);
toolbar = CreateWindowEx(
TBSTYLE_EX_DOUBLEBUFFER,
TOOLBARCLASSNAMEW, NULL,
WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN |
TBSTYLE_TOOLTIPS | TBSTYLE_TRANSPARENT | TBSTYLE_REGISTERDROP | TBSTYLE_LIST | TBSTYLE_FLAT |
CCS_NODIVIDER | CCS_NOPARENTALIGN | CCS_NORESIZE | CCS_TOP,
0, 0, 500, 20, parentWindow, NULL, _AtlBaseModule.GetModuleInstance(), 0);
if (toolbar == NULL)
return E_FAIL;
SubclassWindow(toolbar);
SendMessage(TB_ADDSTRINGW, (WPARAM) GetModuleHandle(L"browseui.dll"), IDS_STANDARD_TOOLBAR);
SendMessage(WM_USER + 100, GetSystemMetrics(SM_CXEDGE) / 2, 0);
SendMessage(TB_BUTTONSTRUCTSIZE, sizeof(TBBUTTON), 0);
SendMessage(TB_SETMAXTEXTROWS, 1, 0);
SendMessage(TB_SETEXTENDEDSTYLE, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS,
TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
SendMessage(TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_HIDECLIPPEDBUTTONS | TBSTYLE_EX_MIXEDBUTTONS | TBSTYLE_EX_DRAWDDARROWS);
HINSTANCE shell32Instance = GetModuleHandle(_T("shell32.dll"));
HBITMAP imageBitmap = reinterpret_cast<HBITMAP>(
HBITMAP imgNormal = reinterpret_cast<HBITMAP>(
LoadImage(shell32Instance, MAKEINTRESOURCE(214),
IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION));
DIBSECTION bitmapInfo;
GetObjectW(imageBitmap, sizeof(bitmapInfo), &bitmapInfo);
HIMAGELIST imageList = ImageList_Create(bitmapInfo.dsBm.bmHeight, bitmapInfo.dsBm.bmHeight, ILC_COLOR32, 4, 4);
HBITMAP imgHot = reinterpret_cast<HBITMAP>(
LoadImage(shell32Instance, MAKEINTRESOURCE(215),
IMAGE_BITMAP, 0, 0, LR_DEFAULTSIZE | LR_CREATEDIBSECTION));
ImageList_Add(imageList, imageBitmap, NULL);
DeleteObject(imageBitmap);
if (imgNormal && imgHot)
{
BITMAP bitmapInfo;
GetObjectW(imgNormal, sizeof(bitmapInfo), &bitmapInfo);
HIMAGELIST himlNormal = ImageList_Create(bitmapInfo.bmHeight, bitmapInfo.bmHeight, ILC_COLOR32, 4, 4);
ImageList_Add(himlNormal, imgNormal, NULL);
SendMessage(TB_SETIMAGELIST, 0, (LPARAM)imageList);
GetObjectW(imgHot, sizeof(bitmapInfo), &bitmapInfo);
HIMAGELIST himlHot = ImageList_Create(bitmapInfo.bmHeight, bitmapInfo.bmHeight, ILC_COLOR32, 4, 4);
ImageList_Add(himlHot, imgHot, NULL);
SendMessage(TB_SETIMAGELIST, 0, (LPARAM) himlNormal);
SendMessage(TB_SETHOTIMAGELIST, 0, (LPARAM) himlHot);
}
SendMessage(TB_ADDBUTTONSW, numShownButtons, (LPARAM)&tbButtonsAdd);
if (imgNormal)
DeleteObject(imgNormal);
if (imgHot)
DeleteObject(imgHot);
return hResult;
}
@ -305,6 +363,8 @@ HRESULT STDMETHODCALLTYPE CToolsBand::CloseDW(DWORD dwReserved)
m_hWnd = NULL;
if (fDockSite) fDockSite.Release();
return S_OK;
}
@ -327,12 +387,12 @@ HRESULT STDMETHODCALLTYPE CToolsBand::ShowDW(BOOL fShow)
HRESULT STDMETHODCALLTYPE CToolsBand::HasFocusIO()
{
return E_NOTIMPL;
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CToolsBand::TranslateAcceleratorIO(LPMSG lpMsg)
{
return E_NOTIMPL;
return S_FALSE;
}
HRESULT STDMETHODCALLTYPE CToolsBand::UIActivateIO(BOOL fActivate, LPMSG lpMsg)
@ -381,21 +441,6 @@ LRESULT CToolsBand::OnGetButtonInfo(UINT idControl, NMHDR *pNMHDR, BOOL &bHandle
HRESULT CreateToolsBar(REFIID riid, void **ppv)
{
CComObject<CToolsBand> *theMenuBar;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theMenuBar = new CComObject<CToolsBand>);
if (theMenuBar == NULL)
return E_OUTOFMEMORY;
hResult = theMenuBar->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theMenuBar;
return hResult;
}
return S_OK;
return ShellObjectCreator<CToolsBand>(riid, ppv);
}

View File

@ -125,9 +125,10 @@ HRESULT CTravelEntry::GetToolTipText(IUnknown *punk, LPWSTR pwzText) const
{
HRESULT hResult;
hResult = ILGetDisplayNameEx(NULL, fPIDL, pwzText, ILGDN_NORMAL);
if (FAILED(hResult))
hResult = ILGetDisplayNameEx(NULL, fPIDL, pwzText, ILGDN_NORMAL) ? S_OK : S_FALSE;
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return S_OK;
}
@ -142,14 +143,16 @@ HRESULT STDMETHODCALLTYPE CTravelEntry::Invoke(IUnknown *punk)
CComPtr<IStream> globalStream;
HRESULT hResult;
hResult = punk->QueryInterface(IID_IPersistHistory, reinterpret_cast<void **>(&persistHistory));
if (FAILED(hResult))
TRACE("CTravelEntry::Invoke for IUnknown punk=%p\n", punk);
hResult = punk->QueryInterface(IID_PPV_ARG(IPersistHistory, &persistHistory));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = CreateStreamOnHGlobal(fPersistState, FALSE, &globalStream);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = persistHistory->LoadHistory(globalStream, NULL);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return S_OK;
}
@ -160,34 +163,43 @@ HRESULT STDMETHODCALLTYPE CTravelEntry::Update(IUnknown *punk, BOOL fIsLocalAnch
CComPtr<IPersistHistory> persistHistory;
CComPtr<IStream> globalStream;
WINDOWDATA windowData;
HGLOBAL globalStorage;
HRESULT hResult;
TRACE("CTravelEntry::Update for IUnknown punk=%p, fIsLocalAnchor=%s\n", punk, fIsLocalAnchor ? "TRUE" : "FALSE");
WCHAR wch[MAX_PATH * 2];
GetToolTipText(punk, wch);
TRACE("Updating entry with display name: %S\n", wch);
ILFree(fPIDL);
fPIDL = NULL;
GlobalFree(fPersistState);
fPersistState = NULL;
hResult = punk->QueryInterface(IID_ITravelLogClient, reinterpret_cast<void **>(&travelLogClient));
if (FAILED(hResult))
hResult = punk->QueryInterface(IID_PPV_ARG(ITravelLogClient, &travelLogClient));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = punk->QueryInterface(IID_IPersistHistory, reinterpret_cast<void **>(&persistHistory));
if (FAILED(hResult))
hResult = punk->QueryInterface(IID_PPV_ARG(IPersistHistory, &persistHistory));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
globalStorage = GlobalAlloc(GMEM_FIXED, 0);
hResult = CreateStreamOnHGlobal(globalStorage, FALSE, &globalStream);
if (FAILED(hResult))
hResult = CreateStreamOnHGlobal(NULL, FALSE, &globalStream);
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = persistHistory->SaveHistory(globalStream);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = travelLogClient->GetWindowData(globalStream, &windowData);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
fPIDL = windowData.pidl;
// TODO: Properly free the windowData
hResult = GetHGlobalFromStream(globalStream, &fPersistState);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
GetToolTipText(punk, wch);
TRACE("Updated entry display name is now: %S\n", wch);
return S_OK;
}
@ -198,6 +210,9 @@ HRESULT STDMETHODCALLTYPE CTravelEntry::GetPidl(LPITEMIDLIST *ppidl)
*ppidl = ILClone(fPIDL);
if (*ppidl == NULL)
return E_OUTOFMEMORY;
TRACE("CTravelEntry::GetPidl returning ppidl=%p\n", *ppidl);
return S_OK;
}
@ -209,6 +224,7 @@ CTravelLog::CTravelLog()
fMaximumSize = 0;
fCurrentSize = 0;
fEntryCount = 0;
TRACE("CTravelLog created\n");
}
CTravelLog::~CTravelLog()
@ -223,19 +239,25 @@ CTravelLog::~CTravelLog()
anEntry->Release();
anEntry = next;
}
TRACE("CTravelLog destroyed\n");
}
HRESULT CTravelLog::Initialize()
{
FIXME("CTravelLog::Initialize using hardcoded fMaximumSize.\n");
fMaximumSize = 1024 * 1024; // TODO: change to read this from registry
// Software\Microsoft\Windows\CurrentVersion\Explorer\TravelLog
// MaxSize
return S_OK;
}
HRESULT CTravelLog::FindRelativeEntry(int offset, CTravelEntry **foundEntry)
HRESULT CTravelLog::FindRelativeEntry(int _offset, CTravelEntry **foundEntry)
{
CTravelEntry *curEntry;
int offset = _offset;
if (foundEntry == NULL)
return E_INVALIDARG;
*foundEntry = NULL;
curEntry = fCurrentEntry;
@ -257,7 +279,11 @@ HRESULT CTravelLog::FindRelativeEntry(int offset, CTravelEntry **foundEntry)
}
if (curEntry == NULL)
return E_INVALIDARG;
*foundEntry = curEntry;
TRACE("CTravelLog::FindRelativeEntry for offset %d, returning %p\n", offset, *foundEntry);
return S_OK;
}
@ -266,6 +292,10 @@ void CTravelLog::DeleteChain(CTravelEntry *startHere)
CTravelEntry *saveNext;
long itemSize;
TRACE("CTravelLog::DeleteChain deleting chain starting at %p\n", startHere);
long startEntryCount = fEntryCount;
if (startHere->fPreviousEntry != NULL)
{
startHere->fPreviousEntry->fNextEntry = NULL;
@ -285,17 +315,21 @@ void CTravelLog::DeleteChain(CTravelEntry *startHere)
startHere = saveNext;
fEntryCount--;
}
TRACE("CTravelLog::DeleteChain chain of %d items deleted\n", startEntryCount - fEntryCount);
}
void CTravelLog::AppendEntry(CTravelEntry *afterEntry, CTravelEntry *newEntry)
{
if (afterEntry == NULL)
{
TRACE("CTravelLog::AppendEntry appending %p after NULL. Resetting head and tail\n", newEntry);
fListHead = newEntry;
fListTail = newEntry;
}
else
{
TRACE("CTravelLog::AppendEntry appending %p after %p\n", newEntry, afterEntry);
newEntry->fNextEntry = afterEntry->fNextEntry;
afterEntry->fNextEntry = newEntry;
newEntry->fPreviousEntry = afterEntry;
@ -312,6 +346,8 @@ HRESULT STDMETHODCALLTYPE CTravelLog::AddEntry(IUnknown *punk, BOOL fIsLocalAnch
CComObject<CTravelEntry> *newEntry;
long itemSize;
TRACE("CTravelLog::AddEntry for IUnknown punk=%p, fIsLocalAnchor=%s\n", punk, fIsLocalAnchor ? "TRUE" : "FALSE");
if (punk == NULL)
return E_INVALIDARG;
ATLTRY (newEntry = new CComObject<CTravelEntry>);
@ -346,12 +382,14 @@ HRESULT STDMETHODCALLTYPE CTravelLog::Travel(IUnknown *punk, int iOffset)
CTravelEntry *destinationEntry;
HRESULT hResult;
TRACE("CTravelLog::Travel for IUnknown punk=%p at offset=%d\n", punk, iOffset);
hResult = FindRelativeEntry(iOffset, &destinationEntry);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
fCurrentEntry = destinationEntry;
hResult = destinationEntry->Invoke(punk);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return S_OK;
}
@ -360,11 +398,17 @@ HRESULT STDMETHODCALLTYPE CTravelLog::GetTravelEntry(IUnknown *punk, int iOffset
{
CTravelEntry *destinationEntry;
HRESULT hResult;
hResult = FindRelativeEntry(iOffset, &destinationEntry);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
return destinationEntry->QueryInterface(IID_ITravelEntry, reinterpret_cast<void **>(ppte));
hResult = destinationEntry->QueryInterface(IID_PPV_ARG(ITravelEntry, ppte));
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
TRACE("CTravelLog::GetTravelEntry for IUnknown punk=%p at offset=%d returning %p\n", punk, iOffset, *ppte);
return hResult;
}
HRESULT STDMETHODCALLTYPE CTravelLog::FindTravelEntry(IUnknown *punk, LPCITEMIDLIST pidl, ITravelEntry **ppte)
@ -373,6 +417,9 @@ HRESULT STDMETHODCALLTYPE CTravelLog::FindTravelEntry(IUnknown *punk, LPCITEMIDL
return E_POINTER;
if (punk == NULL || pidl == NULL)
return E_INVALIDARG;
UNIMPLEMENTED;
return E_NOTIMPL;
}
@ -388,10 +435,10 @@ HRESULT STDMETHODCALLTYPE CTravelLog::GetToolTipText(IUnknown *punk, int iOffset
if (punk == NULL || cchText == 0)
return E_INVALIDARG;
hResult = FindRelativeEntry(iOffset, &destinationEntry);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
hResult = destinationEntry->GetToolTipText(punk, tempString);
if (FAILED(hResult))
if (FAILED_UNEXPECTEDLY(hResult))
return hResult;
if (iOffset < 0)
{
@ -402,6 +449,9 @@ HRESULT STDMETHODCALLTYPE CTravelLog::GetToolTipText(IUnknown *punk, int iOffset
wcscpy(templateString, L"Forward to %s");
}
_snwprintf(pwzText, cchText, templateString, tempString);
TRACE("CTravelLog::GetToolTipText for IUnknown punk=%p at offset=%d returning L\"%S\"\n", punk, iOffset, pwzText);
return S_OK;
}
@ -433,6 +483,8 @@ HRESULT STDMETHODCALLTYPE CTravelLog::InsertMenuEntries(IUnknown *punk, HMENU hm
wchar_t itemTextBuffer[MAX_PATH * 2];
HRESULT hResult;
TRACE("CTravelLog::InsertMenuEntries for IUnknown punk=%p, nPos=%d, idFirst=%d, idLast=%d\n", punk);
// TLMENUF_BACK - include back entries
// TLMENUF_INCLUDECURRENT - include current entry, if TLMENUF_CHECKCURRENT then check the entry
// TLMENUF_FORE - include next entries
@ -467,6 +519,7 @@ HRESULT STDMETHODCALLTYPE CTravelLog::InsertMenuEntries(IUnknown *punk, HMENU hm
if (SUCCEEDED(hResult))
{
FixAmpersands(itemTextBuffer);
TRACE("CTravelLog::InsertMenuEntries adding entry L\"%S\"/L\"%S\" with id %d\n", itemTextBuffer, menuItemInfo.dwTypeData, menuItemInfo.wID);
if (InsertMenuItem(hmenu, nPos, TRUE, &menuItemInfo))
{
nPos++;
@ -487,6 +540,7 @@ HRESULT STDMETHODCALLTYPE CTravelLog::InsertMenuEntries(IUnknown *punk, HMENU hm
if (SUCCEEDED(hResult))
{
FixAmpersands(itemTextBuffer);
TRACE("CTravelLog::InsertMenuEntries adding entry L\"%S\"/L\"%S\" with id %d\n", itemTextBuffer, menuItemInfo.dwTypeData, menuItemInfo.wID);
if (InsertMenuItem(hmenu, nPos, TRUE, &menuItemInfo))
{
nPos++;
@ -507,6 +561,7 @@ HRESULT STDMETHODCALLTYPE CTravelLog::InsertMenuEntries(IUnknown *punk, HMENU hm
FixAmpersands(itemTextBuffer);
if ((dwFlags & TLMENUF_CHECKCURRENT) != 0)
menuItemInfo.fState |= MFS_CHECKED;
TRACE("CTravelLog::InsertMenuEntries adding entry L\"%S\"/L\"%S\" with id %d\n", itemTextBuffer, menuItemInfo.dwTypeData, menuItemInfo.wID);
if (InsertMenuItem(hmenu, nPos, TRUE, &menuItemInfo))
{
nPos++;
@ -527,6 +582,7 @@ HRESULT STDMETHODCALLTYPE CTravelLog::InsertMenuEntries(IUnknown *punk, HMENU hm
if (SUCCEEDED(hResult))
{
FixAmpersands(itemTextBuffer);
TRACE("CTravelLog::InsertMenuEntries adding entry L\"%S\"/L\"%S\" with id %d\n", itemTextBuffer, menuItemInfo.dwTypeData, menuItemInfo.wID);
if (InsertMenuItem(hmenu, nPos, TRUE, &menuItemInfo))
{
nPos++;
@ -545,6 +601,7 @@ HRESULT STDMETHODCALLTYPE CTravelLog::Clone(ITravelLog **pptl)
return E_POINTER;
*pptl = NULL;
// duplicate the log
UNIMPLEMENTED;
return E_NOTIMPL;
}
@ -558,28 +615,11 @@ DWORD STDMETHODCALLTYPE CTravelLog::CountEntries(IUnknown *punk)
HRESULT STDMETHODCALLTYPE CTravelLog::Revert()
{
// remove the current entry?
UNIMPLEMENTED;
return E_NOTIMPL;
}
HRESULT CreateTravelLog(REFIID riid, void **ppv)
{
CComObject<CTravelLog> *theTravelLog;
HRESULT hResult;
if (ppv == NULL)
return E_POINTER;
*ppv = NULL;
ATLTRY (theTravelLog = new CComObject<CTravelLog>);
if (theTravelLog == NULL)
return E_OUTOFMEMORY;
hResult = theTravelLog->QueryInterface(riid, reinterpret_cast<void **>(ppv));
if (FAILED(hResult))
{
delete theTravelLog;
return hResult;
}
hResult = theTravelLog->Initialize();
if (FAILED(hResult))
return hResult;
return S_OK;
return ShellObjectCreatorInit<CTravelLog>(riid, ppv);
}

View File

@ -33,11 +33,9 @@
* - TBSTYLE_REGISTERDROP
* - TBSTYLE_EX_DOUBLEBUFFER
* - Messages:
* - TB_GETMETRICS
* - TB_GETOBJECT
* - TB_INSERTMARKHITTEST
* - TB_SAVERESTORE
* - TB_SETMETRICS
* - WM_WININICHANGE
* - Notifications:
* - NM_CHAR
@ -126,6 +124,8 @@ typedef struct
INT nOldHit;
INT nHotItem; /* index of the "hot" item */
SIZE szPadding; /* padding values around button */
SIZE szBarPadding; /* padding values around the toolbar (NOT USED BUT STORED) */
SIZE szSpacing; /* spacing values between buttons */
INT iTopMargin; /* the top margin */
INT iListGap; /* default gap between text and image for toolbar with list style */
HFONT hDefaultFont;
@ -191,12 +191,18 @@ typedef enum
#define ARROW_HEIGHT 3
#define INSERTMARK_WIDTH 2
/* default padding inside a button */
#define DEFPAD_CX 7
#define DEFPAD_CY 6
/* default space between buttons and between rows */
#define DEFSPACE_CX 7
#define DEFSPACE_CY 6
#define DEFLISTGAP 4
/* vertical padding used in list mode when image is present */
#define LISTPAD_CY 9
#define LISTPAD_CY 2
/* how wide to treat the bitmap if it isn't present */
#define NONLIST_NOTEXT_OFFSET 2
@ -848,14 +854,15 @@ TOOLBAR_DrawButton (const TOOLBAR_INFO *infoPtr, TBUTTON_INFO *btnPtr, HDC hdc,
InflateRect(&rcsep, -infoPtr->szPadding.cx, -infoPtr->szPadding.cy);
TOOLBAR_DrawFlatHorizontalSeparator (&rcsep, hdc, infoPtr);
}
else
TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
}
else if (btnPtr->fsStyle != BTNS_SEP) {
FIXME("Draw some kind of separator: fsStyle=%x\n",
btnPtr->fsStyle);
}
return;
else {
TOOLBAR_DrawFlatSeparator (&rc, hdc, infoPtr);
}
}
else if (btnPtr->fsStyle != BTNS_SEP) {
FIXME("Draw some kind of separator: fsStyle=%x\n",
btnPtr->fsStyle);
}
return;
}
/* get a pointer to the text */
@ -1275,11 +1282,11 @@ TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
/* When the toolbar window style is not TBSTYLE_WRAPABLE, */
/* no layout is necessary. Applications may use this style */
/* to perform their own layout on the toolbar. */
if( !(infoPtr->dwStyle & TBSTYLE_WRAPABLE) &&
!(infoPtr->dwExStyle & TBSTYLE_EX_VERTICAL) ) return;
if (!(infoPtr->dwStyle & TBSTYLE_WRAPABLE) &&
!(infoPtr->dwExStyle & TBSTYLE_EX_VERTICAL)) return;
btnPtr = infoPtr->buttons;
x = infoPtr->nIndent;
x = infoPtr->nIndent;
if (GetParent(infoPtr->hwndSelf))
{
@ -1287,144 +1294,145 @@ TOOLBAR_WrapToolbar(TOOLBAR_INFO *infoPtr)
* this toolbar. We cannot use its height, as there may be multiple
* toolbars in a rebar control
*/
GetClientRect( GetParent(infoPtr->hwndSelf), &rc );
GetClientRect(GetParent(infoPtr->hwndSelf), &rc);
infoPtr->nWidth = rc.right - rc.left;
}
else
{
GetWindowRect( infoPtr->hwndSelf, &rc );
GetWindowRect(infoPtr->hwndSelf, &rc);
infoPtr->nWidth = rc.right - rc.left;
}
bButtonWrap = FALSE;
TRACE("start ButtonWidth=%d, BitmapWidth=%d, nWidth=%d, nIndent=%d\n",
infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
infoPtr->nIndent);
infoPtr->nButtonWidth, infoPtr->nBitmapWidth, infoPtr->nWidth,
infoPtr->nIndent);
for (i = 0; i < infoPtr->nNumButtons; i++ )
for (i = 0; i < infoPtr->nNumButtons; i++)
{
btnPtr[i].fsState &= ~TBSTATE_WRAP;
btnPtr[i].fsState &= ~TBSTATE_WRAP;
if (btnPtr[i].fsState & TBSTATE_HIDDEN)
continue;
if (btnPtr[i].fsState & TBSTATE_HIDDEN)
continue;
if (btnPtr[i].cx > 0)
cx = btnPtr[i].cx;
/* horizontal separators are treated as buttons for width */
else if ((btnPtr[i].fsStyle & BTNS_SEP) &&
!(infoPtr->dwStyle & CCS_VERT))
else if ((btnPtr[i].fsStyle & BTNS_SEP) &&
!(infoPtr->dwStyle & CCS_VERT))
cx = (btnPtr[i].iBitmap > 0) ? btnPtr[i].iBitmap : SEPARATOR_WIDTH;
else
cx = infoPtr->nButtonWidth;
else
cx = infoPtr->nButtonWidth;
/* Two or more adjacent separators form a separator group. */
/* The first separator in a group should be wrapped to the */
/* next row if the previous wrapping is on a button. */
if( bButtonWrap &&
(btnPtr[i].fsStyle & BTNS_SEP) &&
(i + 1 < infoPtr->nNumButtons ) &&
(btnPtr[i + 1].fsStyle & BTNS_SEP) )
{
TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle);
btnPtr[i].fsState |= TBSTATE_WRAP;
x = infoPtr->nIndent;
i++;
bButtonWrap = FALSE;
continue;
}
/* Two or more adjacent separators form a separator group. */
/* The first separator in a group should be wrapped to the */
/* next row if the previous wrapping is on a button. */
if (bButtonWrap &&
(btnPtr[i].fsStyle & BTNS_SEP) &&
(i + 1 < infoPtr->nNumButtons) &&
(btnPtr[i + 1].fsStyle & BTNS_SEP))
{
TRACE("wrap point 1 btn %d style %02x\n", i, btnPtr[i].fsStyle);
btnPtr[i].fsState |= TBSTATE_WRAP;
x = infoPtr->nIndent;
i++;
bButtonWrap = FALSE;
continue;
}
/* The layout makes sure the bitmap is visible, but not the button. */
/* Test added to also wrap after a button that starts a row but */
/* is bigger than the area. - GA 8/01 */
if (( x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
> infoPtr->nWidth ) ||
((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
{
BOOL bFound = FALSE;
/* The layout makes sure the bitmap is visible, but not the button. */
/* Test added to also wrap after a button that starts a row but */
/* is bigger than the area. - GA 8/01 */
if ((x + cx - (infoPtr->nButtonWidth - infoPtr->nBitmapWidth) / 2
> infoPtr->nWidth) ||
((x == infoPtr->nIndent) && (cx > infoPtr->nWidth)))
{
BOOL bFound = FALSE;
/* If the current button is a separator and not hidden, */
/* go to the next until it reaches a non separator. */
/* Wrap the last separator if it is before a button. */
while( ( ((btnPtr[i].fsStyle & BTNS_SEP) &&
!(btnPtr[i].fsStyle & BTNS_DROPDOWN)) ||
(btnPtr[i].fsState & TBSTATE_HIDDEN) ) &&
i < infoPtr->nNumButtons )
{
i++;
bFound = TRUE;
}
/* If the current button is a separator and not hidden, */
/* go to the next until it reaches a non separator. */
/* Wrap the last separator if it is before a button. */
while ((((btnPtr[i].fsStyle & BTNS_SEP) &&
!(btnPtr[i].fsStyle & BTNS_DROPDOWN)) ||
(btnPtr[i].fsState & TBSTATE_HIDDEN)) &&
i < infoPtr->nNumButtons)
{
i++;
bFound = TRUE;
}
if( bFound && i < infoPtr->nNumButtons )
{
i--;
TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
btnPtr[i].fsState |= TBSTATE_WRAP;
x = infoPtr->nIndent;
bButtonWrap = FALSE;
continue;
}
else if ( i >= infoPtr->nNumButtons)
break;
if (bFound && i < infoPtr->nNumButtons)
{
i--;
TRACE("wrap point 2 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
btnPtr[i].fsState |= TBSTATE_WRAP;
x = infoPtr->nIndent;
bButtonWrap = FALSE;
continue;
}
else if (i >= infoPtr->nNumButtons)
break;
/* If the current button is not a separator, find the last */
/* separator and wrap it. */
for ( j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
{
if ((btnPtr[j].fsStyle & BTNS_SEP) &&
!(btnPtr[j].fsState & TBSTATE_HIDDEN))
{
bFound = TRUE;
i = j;
TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
x = infoPtr->nIndent;
btnPtr[j].fsState |= TBSTATE_WRAP;
bButtonWrap = FALSE;
break;
}
}
/* If the current button is not a separator, find the last */
/* separator and wrap it. */
for (j = i - 1; j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
{
if ((btnPtr[j].fsStyle & BTNS_SEP) &&
!(btnPtr[j].fsState & TBSTATE_HIDDEN))
{
bFound = TRUE;
i = j;
TRACE("wrap point 3 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
x = infoPtr->nIndent;
btnPtr[j].fsState |= TBSTATE_WRAP;
bButtonWrap = FALSE;
break;
}
}
/* If no separator available for wrapping, wrap one of */
/* non-hidden previous button. */
if (!bFound)
{
for ( j = i - 1;
j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
{
if (btnPtr[j].fsState & TBSTATE_HIDDEN)
continue;
/* If no separator available for wrapping, wrap one of */
/* non-hidden previous button. */
if (!bFound)
{
for (j = i - 1;
j >= 0 && !(btnPtr[j].fsState & TBSTATE_WRAP); j--)
{
if (btnPtr[j].fsState & TBSTATE_HIDDEN)
continue;
bFound = TRUE;
i = j;
TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
x = infoPtr->nIndent;
btnPtr[j].fsState |= TBSTATE_WRAP;
bButtonWrap = TRUE;
break;
}
}
bFound = TRUE;
i = j;
TRACE("wrap point 4 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
x = infoPtr->nIndent;
btnPtr[j].fsState |= TBSTATE_WRAP;
bButtonWrap = TRUE;
break;
}
}
/* If all above failed, wrap the current button. */
if (!bFound)
{
TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
btnPtr[i].fsState |= TBSTATE_WRAP;
x = infoPtr->nIndent;
if (btnPtr[i].fsStyle & BTNS_SEP )
bButtonWrap = FALSE;
else
bButtonWrap = TRUE;
}
}
else {
TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
x += cx;
}
/* If all above failed, wrap the current button. */
if (!bFound)
{
TRACE("wrap point 5 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
btnPtr[i].fsState |= TBSTATE_WRAP;
x = infoPtr->nIndent;
if (btnPtr[i].fsStyle & BTNS_SEP)
bButtonWrap = FALSE;
else
bButtonWrap = TRUE;
}
}
else
{
TRACE("wrap point 6 btn %d style %02x, x=%d, cx=%d\n",
i, btnPtr[i].fsStyle, x, cx);
x += cx;
}
}
}
@ -1550,9 +1558,8 @@ static inline SIZE TOOLBAR_MeasureButton(const TOOLBAR_INFO *infoPtr, SIZE sizeS
/* ... add on the necessary padding */
if (bValidImageList)
{
if (bHasBitmap)
sizeButton.cy += DEFPAD_CY;
else
sizeButton.cy += infoPtr->szPadding.cy;
if (!bHasBitmap)
sizeButton.cy += LISTPAD_CY;
}
else
@ -1569,7 +1576,7 @@ static inline SIZE TOOLBAR_MeasureButton(const TOOLBAR_INFO *infoPtr, SIZE sizeS
{
if (bHasBitmap)
{
sizeButton.cy = infoPtr->nBitmapHeight + DEFPAD_CY;
sizeButton.cy = infoPtr->nBitmapHeight + infoPtr->szPadding.cy;
if (sizeString.cy > 0)
sizeButton.cy += 1 + sizeString.cy;
sizeButton.cx = infoPtr->szPadding.cx +
@ -1626,17 +1633,17 @@ static void
TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
{
TBUTTON_INFO *btnPtr;
SIZE sizeButton;
INT i, nRows, nSepRows;
INT x, y, cx, cy;
BOOL bWrap;
BOOL validImageList = TOOLBAR_IsValidImageList(infoPtr, 0);
BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
SIZE sizeButton;
INT i, nRows, nSepRows;
INT x, y, cx, cy;
BOOL bWrap;
BOOL validImageList = TOOLBAR_IsValidImageList(infoPtr, 0);
BOOL hasDropDownArrows = TOOLBAR_HasDropDownArrows(infoPtr->dwExStyle);
TOOLBAR_WrapToolbar(infoPtr);
x = infoPtr->nIndent;
y = infoPtr->iTopMargin;
x = infoPtr->nIndent;
y = infoPtr->iTopMargin;
cx = infoPtr->nButtonWidth;
cy = infoPtr->nButtonHeight;
@ -1651,106 +1658,112 @@ TOOLBAR_LayoutToolbar(TOOLBAR_INFO *infoPtr)
TRACE("cy=%d\n", cy);
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++ )
for (i = 0; i < infoPtr->nNumButtons; i++, btnPtr++)
{
bWrap = FALSE;
if (btnPtr->fsState & TBSTATE_HIDDEN)
{
SetRectEmpty (&btnPtr->rect);
continue;
}
bWrap = FALSE;
if (btnPtr->fsState & TBSTATE_HIDDEN)
{
SetRectEmpty(&btnPtr->rect);
continue;
}
cy = infoPtr->nButtonHeight;
cy = infoPtr->nButtonHeight;
if (btnPtr->fsStyle & BTNS_SEP) {
if (infoPtr->dwStyle & CCS_VERT) {
if (btnPtr->fsStyle & BTNS_SEP)
{
if (infoPtr->dwStyle & CCS_VERT)
{
cy = (btnPtr->iBitmap > 0) ? btnPtr->iBitmap : SEPARATOR_WIDTH;
cx = (btnPtr->cx > 0) ? btnPtr->cx : infoPtr->nButtonWidth;
}
else
cx = (btnPtr->cx > 0) ? btnPtr->cx :
(btnPtr->iBitmap > 0) ? btnPtr->iBitmap : SEPARATOR_WIDTH;
}
else
{
if (btnPtr->cx)
cx = btnPtr->cx;
else if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||
(btnPtr->fsStyle & BTNS_AUTOSIZE))
{
SIZE sz;
HDC hdc;
HFONT hOldFont;
hdc = GetDC (infoPtr->hwndSelf);
hOldFont = SelectObject (hdc, infoPtr->hFont);
TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
SelectObject (hdc, hOldFont);
ReleaseDC (infoPtr->hwndSelf, hdc);
sizeButton = TOOLBAR_MeasureButton(infoPtr, sz,
TOOLBAR_IsValidBitmapIndex(infoPtr, infoPtr->buttons[i].iBitmap),
validImageList);
cx = sizeButton.cx;
}
else
cx = infoPtr->nButtonWidth;
{
cx = (btnPtr->cx > 0) ? btnPtr->cx :
(btnPtr->iBitmap > 0) ? btnPtr->iBitmap : SEPARATOR_WIDTH;
}
}
else
{
if (btnPtr->cx)
{
cx = btnPtr->cx;
}
else if ((infoPtr->dwExStyle & TBSTYLE_EX_MIXEDBUTTONS) ||
(btnPtr->fsStyle & BTNS_AUTOSIZE))
{
SIZE sz;
HDC hdc;
HFONT hOldFont;
hdc = GetDC(infoPtr->hwndSelf);
hOldFont = SelectObject(hdc, infoPtr->hFont);
TOOLBAR_MeasureString(infoPtr, btnPtr, hdc, &sz);
SelectObject(hdc, hOldFont);
ReleaseDC(infoPtr->hwndSelf, hdc);
sizeButton = TOOLBAR_MeasureButton(infoPtr, sz,
TOOLBAR_IsValidBitmapIndex(infoPtr, infoPtr->buttons[i].iBitmap),
validImageList);
cx = sizeButton.cx;
}
else
cx = infoPtr->nButtonWidth;
/* if size has been set manually then don't add on extra space
* for the drop down arrow */
if (!btnPtr->cx && hasDropDownArrows &&
if (!btnPtr->cx && hasDropDownArrows &&
((btnPtr->fsStyle & BTNS_DROPDOWN) || (btnPtr->fsStyle & BTNS_WHOLEDROPDOWN)))
cx += DDARROW_WIDTH;
}
if (btnPtr->fsState & TBSTATE_WRAP )
bWrap = TRUE;
cx += DDARROW_WIDTH;
}
if (btnPtr->fsState & TBSTATE_WRAP)
bWrap = TRUE;
SetRect (&btnPtr->rect, x, y, x + cx, y + cy);
SetRect(&btnPtr->rect, x, y, x + cx, y + cy);
if (infoPtr->rcBound.left > x)
infoPtr->rcBound.left = x;
if (infoPtr->rcBound.right < x + cx)
infoPtr->rcBound.right = x + cx;
if (infoPtr->rcBound.bottom < y + cy)
infoPtr->rcBound.bottom = y + cy;
if (infoPtr->rcBound.left > x)
infoPtr->rcBound.left = x;
if (infoPtr->rcBound.right < x + cx)
infoPtr->rcBound.right = x + cx;
if (infoPtr->rcBound.bottom < y + cy)
infoPtr->rcBound.bottom = y + cy;
TOOLBAR_TooltipSetRect(infoPtr, btnPtr);
/* btnPtr->nRow is zero based. The space between the rows is */
/* also considered as a row. */
btnPtr->nRow = nRows + nSepRows;
/* btnPtr->nRow is zero based. The space between the rows is */
/* also considered as a row. */
btnPtr->nRow = nRows + nSepRows;
TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow,
x, y, x+cx, y+cy);
TRACE("button %d style=%x, bWrap=%d, nRows=%d, nSepRows=%d, btnrow=%d, (%d,%d)-(%d,%d)\n",
i, btnPtr->fsStyle, bWrap, nRows, nSepRows, btnPtr->nRow,
x, y, x + cx, y + cy);
if( bWrap )
{
if ( !(btnPtr->fsStyle & BTNS_SEP) )
y += cy;
else
{
if ( !(infoPtr->dwStyle & CCS_VERT))
y += cy + ( (btnPtr->cx > 0 ) ?
btnPtr->cx : SEPARATOR_WIDTH) * 2 /3;
else
y += cy;
if (bWrap)
{
if (!(btnPtr->fsStyle & BTNS_SEP))
y += cy;
else
{
if (!(infoPtr->dwStyle & CCS_VERT))
y += cy + ((btnPtr->cx > 0) ?
btnPtr->cx : SEPARATOR_WIDTH) * 2 / 3;
else
y += cy;
/* nSepRows is used to calculate the extra height following */
/* the last row. */
nSepRows++;
}
x = infoPtr->nIndent;
/* nSepRows is used to calculate the extra height following */
/* the last row. */
nSepRows++;
}
x = infoPtr->nIndent;
/* Increment row number unless this is the last button */
/* and it has Wrap set. */
if (i != infoPtr->nNumButtons-1)
nRows++;
}
else
x += cx;
/* Increment row number unless this is the last button */
/* and it has Wrap set. */
if (i != infoPtr->nNumButtons - 1)
nRows++;
}
else
x += cx;
}
/* infoPtr->nRows is the number of rows on the toolbar */
@ -1940,6 +1953,16 @@ TOOLBAR_RelayEvent (HWND hwndTip, HWND hwndMsg, UINT uMsg,
SendMessageW (hwndTip, TTM_RELAYEVENT, 0, (LPARAM)&msg);
}
static LRESULT
TOOLBAR_ThemeChanged(HWND hwnd)
{
HTHEME theme = GetWindowTheme(hwnd);
CloseThemeData(theme);
OpenThemeData(hwnd, themeClass);
return 0;
}
static void
TOOLBAR_TooltipAddTool(const TOOLBAR_INFO *infoPtr, const TBUTTON_INFO *button)
{
@ -3529,6 +3552,36 @@ TOOLBAR_GetMaxSize (const TOOLBAR_INFO *infoPtr, LPSIZE lpSize)
}
static LRESULT
TOOLBAR_GetMetrics (const TOOLBAR_INFO *infoPtr, TBMETRICS *pMetrics)
{
if (pMetrics == NULL)
return FALSE;
/* TODO: check if cbSize is a valid value */
if (pMetrics->dwMask & TBMF_PAD)
{
pMetrics->cxPad = infoPtr->szPadding.cx;
pMetrics->cyPad = infoPtr->szPadding.cy;
}
if (pMetrics->dwMask & TBMF_BARPAD)
{
pMetrics->cxBarPad = infoPtr->szBarPadding.cx;
pMetrics->cyBarPad = infoPtr->szBarPadding.cy;
}
if (pMetrics->dwMask & TBMF_BUTTONSPACING)
{
pMetrics->cxButtonSpacing = infoPtr->szSpacing.cx;
pMetrics->cyButtonSpacing = infoPtr->szSpacing.cy;
}
return TRUE;
}
/* << TOOLBAR_GetObject >> */
@ -4710,6 +4763,43 @@ TOOLBAR_SetMaxTextRows (TOOLBAR_INFO *infoPtr, INT nMaxRows)
}
static LRESULT
TOOLBAR_SetMetrics (TOOLBAR_INFO *infoPtr, TBMETRICS *pMetrics)
{
BOOL changed = FALSE;
if (!pMetrics)
return FALSE;
/* TODO: check if cbSize is a valid value */
if (pMetrics->dwMask & TBMF_PAD)
{
infoPtr->szPadding.cx = pMetrics->cxPad;
infoPtr->szPadding.cy = pMetrics->cyPad;
changed = TRUE;
}
if (pMetrics->dwMask & TBMF_PAD)
{
infoPtr->szBarPadding.cx = pMetrics->cxBarPad;
infoPtr->szBarPadding.cy = pMetrics->cyBarPad;
changed = TRUE;
}
if (pMetrics->dwMask & TBMF_BUTTONSPACING)
{
infoPtr->szSpacing.cx = pMetrics->cxButtonSpacing;
infoPtr->szSpacing.cy = pMetrics->cyButtonSpacing;
changed = TRUE;
}
if (changed)
TOOLBAR_CalcToolbar(infoPtr);
return TRUE;
}
/* MSDN gives slightly wrong info on padding.
* 1. It is not only used on buttons with the BTNS_AUTOSIZE style
* 2. It is not used to create a blank area between the edge of the button
@ -5925,6 +6015,8 @@ TOOLBAR_NCCreate (HWND hwnd, WPARAM wParam, const CREATESTRUCTW *lpcs)
infoPtr->clrBtnShadow = CLR_DEFAULT;
infoPtr->szPadding.cx = DEFPAD_CX;
infoPtr->szPadding.cy = DEFPAD_CY;
infoPtr->szSpacing.cx = DEFSPACE_CX;
infoPtr->szSpacing.cy = DEFSPACE_CY;
infoPtr->iListGap = DEFLISTGAP;
infoPtr->iTopMargin = default_top_margin(infoPtr);
infoPtr->dwStyle = lpcs->style;
@ -6358,16 +6450,6 @@ TOOLBAR_SysColorChange (void)
}
/* update theme after a WM_THEMECHANGED message */
static LRESULT theme_changed (HWND hwnd)
{
HTHEME theme = GetWindowTheme (hwnd);
CloseThemeData (theme);
OpenThemeData (hwnd, themeClass);
return 0;
}
static LRESULT WINAPI
ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
@ -6471,6 +6553,9 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case TB_GETMAXSIZE:
return TOOLBAR_GetMaxSize (infoPtr, (LPSIZE)lParam);
case TB_GETMETRICS:
return TOOLBAR_GetMetrics (infoPtr, (TBMETRICS*)lParam);
/* case TB_GETOBJECT: */ /* 4.71 */
@ -6487,7 +6572,7 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return TOOLBAR_GetState (infoPtr, wParam);
case TB_GETSTRINGA:
return TOOLBAR_GetStringA (infoPtr, wParam, (LPSTR)lParam);
return TOOLBAR_GetStringA (infoPtr, wParam, (LPSTR)lParam);
case TB_GETSTRINGW:
return TOOLBAR_GetStringW (infoPtr, wParam, (LPWSTR)lParam);
@ -6612,6 +6697,9 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case TB_SETMAXTEXTROWS:
return TOOLBAR_SetMaxTextRows (infoPtr, wParam);
case TB_SETMETRICS:
return TOOLBAR_SetMetrics (infoPtr, (TBMETRICS*)lParam);
case TB_SETPADDING:
return TOOLBAR_SetPadding (infoPtr, lParam);
@ -6737,7 +6825,7 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
return TOOLBAR_SetFocus (infoPtr);
case WM_SETFONT:
return TOOLBAR_SetFont(infoPtr, (HFONT)wParam, (WORD)lParam);
return TOOLBAR_SetFont(infoPtr, (HFONT)wParam, (WORD)lParam);
case WM_SETREDRAW:
return TOOLBAR_SetRedraw (infoPtr, wParam);
@ -6751,8 +6839,8 @@ ToolbarWindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
case WM_SYSCOLORCHANGE:
return TOOLBAR_SysColorChange ();
case WM_THEMECHANGED:
return theme_changed (hwnd);
case WM_THEMECHANGED:
return TOOLBAR_ThemeChanged(hwnd);
/* case WM_WININICHANGE: */

View File

@ -9,6 +9,7 @@ list(APPEND SOURCE
gui.c
lsa.c
msgina.c
shutdown.c
stubs.c
tui.c
msgina.h)
@ -21,7 +22,7 @@ add_library(msgina SHARED
set_module_type(msgina win32dll)
target_link_libraries(msgina wine)
add_importlibs(msgina advapi32 user32 gdi32 userenv msvcrt kernel32 ntdll)
add_importlibs(msgina advapi32 user32 gdi32 powrprof userenv msvcrt kernel32 ntdll)
add_delay_importlibs(msgina secur32)
add_pch(msgina msgina.h SOURCE)
add_cd_file(TARGET msgina DESTINATION reactos/system32 FOR all)

Some files were not shown because too many files have changed in this diff Show More