integrate replacement function for SHBindToParent()
Modified: trunk/reactos/subsys/system/explorer/shell/entries.cpp
_____
Modified: trunk/reactos/subsys/system/explorer/shell/entries.cpp
--- trunk/reactos/subsys/system/explorer/shell/entries.cpp
2005-11-29 13:34:24 UTC (rev 19750)
+++ trunk/reactos/subsys/system/explorer/shell/entries.cpp
2005-11-29 13:35:11 UTC (rev 19751)
@@ -1,5 +1,5 @@
/*
- * Copyright 2003, 2004 Martin Fuchs
+ * Copyright 2003, 2004, 2005 Martin Fuchs
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -334,7 +334,7 @@
unsigned flags;
int idx;
- if
(SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, MAX_PATH, &idx,
&flags))) {
+ if
(SUCCEEDED(pExtract->GetIconLocation(GIL_FORSHELL, path, COUNTOF(path),
&idx, &flags))) {
if (flags & GIL_NOTFILENAME)
icon_id =
g_Globals._icon_cache.extract(pExtract, path, idx, big_icons);
else {
@@ -403,6 +403,67 @@
}
+ // local replacement implementation for SHBindToParent()
+ // (derived from
http://www.geocities.com/SiliconValley/2060/articles/shell-helpers.html)
+static HRESULT my_SHBindToParent(LPCITEMIDLIST pidl, REFIID riid,
VOID** ppv, LPCITEMIDLIST* ppidlLast)
+{
+ HRESULT hr;
+
+ if (!ppv)
+ return E_POINTER;
+
+ // There must be at least one item ID.
+ if (!pidl || !pidl->mkid.cb)
+ return E_INVALIDARG;
+
+ // Get the desktop folder as root.
+ ShellFolder desktop;
+/* IShellFolderPtr desktop;
+ hr = SHGetDesktopFolder(&desktop);
+ if (FAILED(hr))
+ return hr; */
+
+ // Walk to the penultimate item ID.
+ LPCITEMIDLIST marker = pidl;
+ for (;;)
+ {
+ LPCITEMIDLIST next = reinterpret_cast<LPCITEMIDLIST>(
+ marker->mkid.abID - sizeof(marker->mkid.cb) +
marker->mkid.cb);
+ if (!next->mkid.cb)
+ break;
+ marker = next;
+ }
+
+ if (marker == pidl)
+ {
+ // There was only a single item ID, so bind to the root
folder.
+ hr = desktop->QueryInterface(riid, ppv);
+ }
+ else
+ {
+ // Copy the ID list, truncating the last item.
+ int length = marker->mkid.abID - pidl->mkid.abID;
+ if (LPITEMIDLIST parent_id =
reinterpret_cast<LPITEMIDLIST>(
+ malloc(length + sizeof(pidl->mkid.cb))))
+ {
+ LPBYTE raw_data =
reinterpret_cast<LPBYTE>(parent_id);
+ memcpy(raw_data, pidl, length);
+ memset(raw_data + length, 0,
sizeof(pidl->mkid.cb));
+ hr = desktop->BindToObject(parent_id, 0, riid,
ppv);
+ free(parent_id);
+ }
+ else
+ return E_OUTOFMEMORY;
+ }
+
+ // Return a pointer to the last item ID.
+ if (ppidlLast)
+ *ppidlLast = marker;
+
+ return hr;
+}
+#define USE_MY_SHBINDTOPARENT
+
HRESULT Entry::do_context_menu(HWND hwnd, const POINT& pos,
CtxMenuInterfaces& cm_ifs)
{
ShellPath shell_path = create_absolute_pidl();
@@ -411,6 +472,21 @@
if (!pidl_abs)
return S_FALSE; // no action for registry entries, etc.
+#ifdef USE_MY_SHBINDTOPARENT
+ IShellFolder* parentFolder;
+ LPCITEMIDLIST pidlLast;
+
+ // get and use the parent folder to display correct context
menu in all cases -> correct "Properties" dialog for directories, ...
+ HRESULT hr = my_SHBindToParent(pidl_abs, IID_IShellFolder,
(LPVOID*)&parentFolder, &pidlLast);
+
+ if (SUCCEEDED(hr)) {
+ hr = ShellFolderContextMenu(parentFolder, hwnd, 1,
&pidlLast, pos.x, pos.y, cm_ifs);
+
+ parentFolder->Release();
+ }
+
+ return hr;
+#else
static DynamicFct<HRESULT(WINAPI*)(LPCITEMIDLIST, REFIID,
LPVOID*, LPCITEMIDLIST*)> SHBindToParent(TEXT("SHELL32"),
"SHBindToParent");
if (SHBindToParent) {
@@ -446,6 +522,7 @@
*/
return ShellFolderContextMenu(GetDesktopFolder(), hwnd,
1, &pidl_abs, pos.x, pos.y, cm_ifs);
}
+#endif
}
@@ -489,7 +566,7 @@
LPWSTR wname = _data.cFileName;
#else
WCHAR wname[MAX_PATH];
- MultiByteToWideChar(CP_ACP, 0, _data.cFileName, -1, wname,
MAX_PATH);
+ MultiByteToWideChar(CP_ACP, 0, _data.cFileName, -1, wname,
COUNTOF(wname));
#endif
LPITEMIDLIST pidl_last = NULL;