annotate kdiff3/src-QT4/kreplacements/ShellContextMenu.cpp @ 112:0180c7f92563

Build fixes
author Chris Cannam
date Fri, 07 Dec 2018 13:40:01 +0000
parents 1184fc843210
children
rev   line source
joachim99@77 1 /***************************************************************************
joachim99@77 2 ShellContextMenu.cpp - description
joachim99@77 3 -------------------
joachim99@77 4 begin : Sat Mar 4 2006
joachim99@77 5 copyright : (C) 2005-2007 by Joachim Eibl
joachim99@77 6 email : joachim dot eibl at gmx dot de
joachim99@77 7 ***************************************************************************/
joachim99@77 8
joachim99@77 9 /***************************************************************************
joachim99@77 10 * *
joachim99@77 11 * This program is free software; you can redistribute it and/or modify *
joachim99@77 12 * it under the terms of the GNU General Public License as published by *
joachim99@77 13 * the Free Software Foundation; either version 2 of the License, or *
joachim99@77 14 * (at your option) any later version. *
joachim99@77 15 * *
joachim99@77 16 ***************************************************************************/
joachim99@69 17 // ShellContextMenu.cpp: Implementierung der Klasse CShellContextMenu.
joachim99@69 18 //
joachim99@69 19 //////////////////////////////////////////////////////////////////////
joachim99@69 20 #ifdef _WIN32
joachim99@69 21 #include <windows.h>
joachim99@69 22 #include <shlobj.h>
joachim99@69 23 #include <malloc.h>
joachim99@69 24 #include <qstring.h>
joachim99@69 25 #include <qstringlist.h>
joachim99@69 26 #include <qwidget.h>
joachim99@69 27 #include <qdir.h>
joachim99@70 28 #include <QMenu>
joachim99@69 29 #include "ShellContextMenu.h"
joachim99@69 30
joachim99@69 31 #ifdef _DEBUG
joachim99@69 32 #undef THIS_FILE
joachim99@69 33 static char THIS_FILE[]=__FILE__;
joachim99@69 34 #define new DEBUG_NEW
joachim99@69 35 #endif
joachim99@69 36
joachim99@69 37 //////////////////////////////////////////////////////////////////////
joachim99@69 38 // Konstruktion/Destruktion
joachim99@69 39 //////////////////////////////////////////////////////////////////////
joachim99@69 40
joachim99@69 41 #define MIN_ID 100
joachim99@69 42 #define MAX_ID 10000
joachim99@69 43
joachim99@69 44
joachim99@70 45 void showShellContextMenu( const QString& itemPath, QPoint pt, QWidget* pParentWidget, QMenu* pMenu )
joachim99@69 46 {
joachim99@69 47 CShellContextMenu scm;
joachim99@77 48 scm.SetObjects(QDir::toNativeSeparators(QDir::cleanPath(itemPath)));
joachim99@69 49 int id = scm.ShowContextMenu (pParentWidget, pt, pMenu);
joachim99@69 50 if (id>=1)
joachim99@75 51 pMenu->actions().value(id-1)->trigger();
joachim99@69 52 }
joachim99@69 53
joachim99@69 54 IContextMenu2 * g_IContext2 = NULL;
joachim99@69 55 IContextMenu3 * g_IContext3 = NULL;
joachim99@69 56
joachim99@69 57 CShellContextMenu::CShellContextMenu()
joachim99@69 58 {
joachim99@69 59 m_psfFolder = NULL;
joachim99@69 60 m_pidlArray = NULL;
joachim99@69 61 m_hMenu = NULL;
joachim99@69 62 }
joachim99@69 63
joachim99@69 64 CShellContextMenu::~CShellContextMenu()
joachim99@69 65 {
joachim99@69 66 // free all allocated datas
joachim99@69 67 if (m_psfFolder && bDelete)
joachim99@69 68 m_psfFolder->Release ();
joachim99@69 69 m_psfFolder = NULL;
joachim99@69 70 FreePIDLArray (m_pidlArray);
joachim99@69 71 m_pidlArray = NULL;
joachim99@69 72
joachim99@69 73 if (m_hMenu)
joachim99@69 74 DestroyMenu( m_hMenu );
joachim99@69 75 }
joachim99@69 76
joachim99@69 77
joachim99@69 78
joachim99@69 79 // this functions determines which version of IContextMenu is avaibale for those objects (always the highest one)
joachim99@69 80 // and returns that interface
joachim99@69 81 BOOL CShellContextMenu::GetContextMenu (void ** ppContextMenu, int & iMenuType)
joachim99@69 82 {
joachim99@69 83 *ppContextMenu = NULL;
joachim99@69 84 LPCONTEXTMENU icm1 = NULL;
joachim99@77 85
joachim99@77 86 if ( m_psfFolder==0 )
joachim99@77 87 return FALSE;
joachim99@69 88
joachim99@69 89 // first we retrieve the normal IContextMenu interface (every object should have it)
joachim99@69 90 m_psfFolder->GetUIObjectOf (NULL, nItems, (LPCITEMIDLIST *) m_pidlArray, IID_IContextMenu, NULL, (void**) &icm1);
joachim99@69 91
joachim99@69 92 if (icm1)
joachim99@69 93 { // since we got an IContextMenu interface we can now obtain the higher version interfaces via that
joachim99@69 94 if (icm1->QueryInterface (IID_IContextMenu3, ppContextMenu) == NOERROR)
joachim99@69 95 iMenuType = 3;
joachim99@69 96 else if (icm1->QueryInterface (IID_IContextMenu2, ppContextMenu) == NOERROR)
joachim99@69 97 iMenuType = 2;
joachim99@69 98
joachim99@69 99 if (*ppContextMenu)
joachim99@69 100 icm1->Release(); // we can now release version 1 interface, cause we got a higher one
joachim99@69 101 else
joachim99@69 102 {
joachim99@69 103 iMenuType = 1;
joachim99@69 104 *ppContextMenu = icm1; // since no higher versions were found
joachim99@69 105 } // redirect ppContextMenu to version 1 interface
joachim99@69 106 }
joachim99@69 107 else
joachim99@69 108 return (FALSE); // something went wrong
joachim99@69 109
joachim99@69 110 return (TRUE); // success
joachim99@69 111 }
joachim99@69 112
joachim99@69 113
joachim99@69 114 LRESULT CALLBACK CShellContextMenu::HookWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
joachim99@69 115 {
joachim99@69 116 switch (message)
joachim99@69 117 {
joachim99@69 118 case WM_MENUCHAR: // only supported by IContextMenu3
joachim99@69 119 if (g_IContext3)
joachim99@69 120 {
joachim99@69 121 LRESULT lResult = 0;
joachim99@69 122 g_IContext3->HandleMenuMsg2 (message, wParam, lParam, &lResult);
joachim99@69 123 return (lResult);
joachim99@69 124 }
joachim99@69 125 break;
joachim99@69 126
joachim99@69 127 case WM_DRAWITEM:
joachim99@69 128 case WM_MEASUREITEM:
joachim99@69 129 if (wParam)
joachim99@69 130 break; // if wParam != 0 then the message is not menu-related
joachim99@69 131
joachim99@69 132 case WM_INITMENUPOPUP:
joachim99@69 133 if (g_IContext2)
joachim99@69 134 g_IContext2->HandleMenuMsg (message, wParam, lParam);
joachim99@69 135 else // version 3
joachim99@69 136 g_IContext3->HandleMenuMsg (message, wParam, lParam);
joachim99@69 137 return (message == WM_INITMENUPOPUP ? 0 : TRUE); // inform caller that we handled WM_INITPOPUPMENU by ourself
joachim99@69 138 break;
joachim99@69 139
joachim99@69 140 default:
joachim99@69 141 break;
joachim99@69 142 }
joachim99@69 143
joachim99@69 144 // call original WndProc of window to prevent undefined bevhaviour of window
joachim99@69 145 return ::CallWindowProc ((WNDPROC) GetProp ( hWnd, TEXT ("OldWndProc")), hWnd, message, wParam, lParam);
joachim99@69 146 }
joachim99@69 147
joachim99@69 148
joachim99@70 149 UINT CShellContextMenu::ShowContextMenu(QWidget * pParentWidget, QPoint pt, QMenu* pMenu )
joachim99@69 150 {
Chris@112 151 HWND hWnd = (HWND)pParentWidget->winId();
joachim99@69 152 int iMenuType = 0; // to know which version of IContextMenu is supported
joachim99@69 153 LPCONTEXTMENU pContextMenu; // common pointer to IContextMenu and higher version interface
joachim99@69 154
joachim99@69 155 if (!GetContextMenu ((void**) &pContextMenu, iMenuType))
joachim99@69 156 return (0); // something went wrong
joachim99@69 157
joachim99@69 158 if (!m_hMenu)
joachim99@69 159 {
joachim99@69 160 DestroyMenu( m_hMenu );
joachim99@69 161 m_hMenu = CreatePopupMenu ();
joachim99@69 162 }
joachim99@69 163
joachim99@75 164 int i;
joachim99@75 165 QList<QAction*> actionList = pMenu->actions();
joachim99@75 166 for( i=0; i<actionList.count(); ++i )
joachim99@69 167 {
joachim99@75 168 QString s = actionList.at(i)->text();
joachim99@69 169 if (!s.isEmpty())
joachim99@75 170 AppendMenuW( m_hMenu, MF_STRING, i+1, (LPCWSTR)s.utf16() );
joachim99@69 171 }
joachim99@69 172 AppendMenuW( m_hMenu, MF_SEPARATOR, i+1, L"" );
joachim99@69 173
joachim99@69 174 // lets fill the our popupmenu
joachim99@69 175 pContextMenu->QueryContextMenu (m_hMenu, GetMenuItemCount (m_hMenu), MIN_ID, MAX_ID, CMF_NORMAL | CMF_EXPLORE);
joachim99@69 176
joachim99@69 177 // subclass window to handle menurelated messages in CShellContextMenu
joachim99@69 178 WNDPROC OldWndProc;
joachim99@69 179 if (iMenuType > 1) // only subclass if its version 2 or 3
joachim99@69 180 {
joachim99@69 181 OldWndProc = (WNDPROC) SetWindowLong (hWnd, GWL_WNDPROC, (DWORD) HookWndProc);
joachim99@69 182 if (iMenuType == 2)
joachim99@69 183 g_IContext2 = (LPCONTEXTMENU2) pContextMenu;
joachim99@69 184 else // version 3
joachim99@69 185 g_IContext3 = (LPCONTEXTMENU3) pContextMenu;
joachim99@69 186 }
joachim99@69 187 else
joachim99@69 188 OldWndProc = NULL;
joachim99@69 189
Chris@112 190 UINT idCommand = TrackPopupMenu (m_hMenu,TPM_RETURNCMD | TPM_LEFTALIGN, pt.x(), pt.y(), 0, (HWND)pParentWidget->winId(), 0);
joachim99@69 191
joachim99@69 192 if (OldWndProc) // unsubclass
joachim99@69 193 SetWindowLong (hWnd, GWL_WNDPROC, (DWORD) OldWndProc);
joachim99@69 194
joachim99@69 195 if (idCommand >= MIN_ID && idCommand <= MAX_ID) // see if returned idCommand belongs to shell menu entries
joachim99@69 196 {
joachim99@69 197 InvokeCommand (pContextMenu, idCommand - MIN_ID); // execute related command
joachim99@69 198 idCommand = 0;
joachim99@69 199 }
joachim99@69 200
joachim99@69 201 pContextMenu->Release();
joachim99@69 202 g_IContext2 = NULL;
joachim99@69 203 g_IContext3 = NULL;
joachim99@69 204
joachim99@69 205 return (idCommand);
joachim99@69 206 }
joachim99@69 207
joachim99@69 208
joachim99@69 209 void CShellContextMenu::InvokeCommand (LPCONTEXTMENU pContextMenu, UINT idCommand)
joachim99@69 210 {
joachim99@69 211 CMINVOKECOMMANDINFO cmi = {0};
joachim99@69 212 cmi.cbSize = sizeof (CMINVOKECOMMANDINFO);
joachim99@69 213 cmi.lpVerb = (LPSTR) MAKEINTRESOURCE (idCommand);
joachim99@69 214 cmi.nShow = SW_SHOWNORMAL;
joachim99@69 215
joachim99@69 216 pContextMenu->InvokeCommand (&cmi);
joachim99@69 217 }
joachim99@69 218
joachim99@69 219
joachim99@69 220 void CShellContextMenu::SetObjects(const QString& strObject)
joachim99@69 221 {
joachim99@69 222 // only one object is passed
joachim99@69 223 QStringList strArray;
joachim99@69 224 strArray << strObject; // create a CStringArray with one element
joachim99@69 225
joachim99@69 226 SetObjects (strArray); // and pass it to SetObjects (CStringArray &strArray)
joachim99@69 227 // for further processing
joachim99@69 228 }
joachim99@69 229
joachim99@69 230
joachim99@69 231 void CShellContextMenu::SetObjects(const QStringList &strList)
joachim99@69 232 {
joachim99@69 233 // free all allocated datas
joachim99@69 234 if (m_psfFolder && bDelete)
joachim99@69 235 m_psfFolder->Release ();
joachim99@69 236 m_psfFolder = NULL;
joachim99@69 237 FreePIDLArray (m_pidlArray);
joachim99@69 238 m_pidlArray = NULL;
joachim99@69 239
joachim99@69 240 // get IShellFolder interface of Desktop (root of shell namespace)
joachim99@69 241 IShellFolder * psfDesktop = NULL;
joachim99@69 242 SHGetDesktopFolder (&psfDesktop); // needed to obtain full qualified pidl
joachim99@69 243
joachim99@69 244 // ParseDisplayName creates a PIDL from a file system path relative to the IShellFolder interface
joachim99@69 245 // but since we use the Desktop as our interface and the Desktop is the namespace root
joachim99@69 246 // that means that it's a fully qualified PIDL, which is what we need
joachim99@69 247 LPITEMIDLIST pidl = NULL;
joachim99@69 248
joachim99@75 249 psfDesktop->ParseDisplayName (NULL, 0, (LPOLESTR)strList[0].utf16(), NULL, &pidl, NULL);
joachim99@69 250
joachim99@69 251 // now we need the parent IShellFolder interface of pidl, and the relative PIDL to that interface
joachim99@69 252 LPITEMIDLIST pidlItem = NULL; // relative pidl
joachim99@69 253 SHBindToParentEx (pidl, IID_IShellFolder, (void **) &m_psfFolder, NULL);
joachim99@69 254 free (pidlItem);
joachim99@69 255 // get interface to IMalloc (need to free the PIDLs allocated by the shell functions)
joachim99@69 256 LPMALLOC lpMalloc = NULL;
joachim99@69 257 SHGetMalloc (&lpMalloc);
joachim99@69 258 lpMalloc->Free (pidl);
joachim99@69 259
joachim99@69 260 // now we have the IShellFolder interface to the parent folder specified in the first element in strArray
joachim99@69 261 // since we assume that all objects are in the same folder (as it's stated in the MSDN)
joachim99@69 262 // we now have the IShellFolder interface to every objects parent folder
joachim99@69 263
joachim99@69 264 IShellFolder * psfFolder = NULL;
joachim99@69 265 nItems = strList.size ();
joachim99@69 266 for (int i = 0; i < nItems; i++)
joachim99@69 267 {
joachim99@69 268 pidl=0;
joachim99@75 269 psfDesktop->ParseDisplayName (NULL, 0, (LPOLESTR)strList[i].utf16(), NULL, &pidl, NULL);
joachim99@69 270 if (pidl)
joachim99@69 271 {
joachim99@69 272 m_pidlArray = (LPITEMIDLIST *) realloc (m_pidlArray, (i + 1) * sizeof (LPITEMIDLIST));
joachim99@69 273 // get relative pidl via SHBindToParent
joachim99@69 274 SHBindToParentEx (pidl, IID_IShellFolder, (void **) &psfFolder, (LPCITEMIDLIST *) &pidlItem);
joachim99@69 275 m_pidlArray[i] = CopyPIDL (pidlItem); // copy relative pidl to pidlArray
joachim99@69 276 free (pidlItem);
joachim99@69 277 lpMalloc->Free (pidl); // free pidl allocated by ParseDisplayName
joachim99@69 278 psfFolder->Release ();
joachim99@69 279 }
joachim99@69 280 }
joachim99@69 281 lpMalloc->Release ();
joachim99@69 282 psfDesktop->Release ();
joachim99@69 283
joachim99@69 284 bDelete = TRUE; // indicates that m_psfFolder should be deleted by CShellContextMenu
joachim99@69 285 }
joachim99@69 286
joachim99@69 287
joachim99@69 288 // only one full qualified PIDL has been passed
joachim99@69 289 void CShellContextMenu::SetObjects(LPITEMIDLIST /*pidl*/)
joachim99@69 290 {
joachim99@69 291 /*
joachim99@69 292 // free all allocated datas
joachim99@69 293 if (m_psfFolder && bDelete)
joachim99@69 294 m_psfFolder->Release ();
joachim99@69 295 m_psfFolder = NULL;
joachim99@69 296 FreePIDLArray (m_pidlArray);
joachim99@69 297 m_pidlArray = NULL;
joachim99@69 298
joachim99@69 299 // full qualified PIDL is passed so we need
joachim99@69 300 // its parent IShellFolder interface and its relative PIDL to that
joachim99@69 301 LPITEMIDLIST pidlItem = NULL;
joachim99@69 302 SHBindToParent ((LPCITEMIDLIST) pidl, IID_IShellFolder, (void **) &m_psfFolder, (LPCITEMIDLIST *) &pidlItem);
joachim99@69 303
joachim99@69 304 m_pidlArray = (LPITEMIDLIST *) malloc (sizeof (LPITEMIDLIST)); // allocate ony for one elemnt
joachim99@69 305 m_pidlArray[0] = CopyPIDL (pidlItem);
joachim99@69 306
joachim99@69 307
joachim99@69 308 // now free pidlItem via IMalloc interface (but not m_psfFolder, that we need later
joachim99@69 309 LPMALLOC lpMalloc = NULL;
joachim99@69 310 SHGetMalloc (&lpMalloc);
joachim99@69 311 lpMalloc->Free (pidlItem);
joachim99@69 312 lpMalloc->Release();
joachim99@69 313
joachim99@69 314 nItems = 1;
joachim99@69 315 bDelete = TRUE; // indicates that m_psfFolder should be deleted by CShellContextMenu
joachim99@69 316 */
joachim99@69 317 }
joachim99@69 318
joachim99@69 319
joachim99@69 320 // IShellFolder interface with a relative pidl has been passed
joachim99@69 321 void CShellContextMenu::SetObjects(IShellFolder *psfFolder, LPITEMIDLIST pidlItem)
joachim99@69 322 {
joachim99@69 323 // free all allocated datas
joachim99@69 324 if (m_psfFolder && bDelete)
joachim99@69 325 m_psfFolder->Release ();
joachim99@69 326 m_psfFolder = NULL;
joachim99@69 327 FreePIDLArray (m_pidlArray);
joachim99@69 328 m_pidlArray = NULL;
joachim99@69 329
joachim99@69 330 m_psfFolder = psfFolder;
joachim99@69 331
joachim99@69 332 m_pidlArray = (LPITEMIDLIST *) malloc (sizeof (LPITEMIDLIST));
joachim99@69 333 m_pidlArray[0] = CopyPIDL (pidlItem);
joachim99@69 334
joachim99@69 335 nItems = 1;
joachim99@69 336 bDelete = FALSE; // indicates wheter m_psfFolder should be deleted by CShellContextMenu
joachim99@69 337 }
joachim99@69 338
joachim99@69 339 void CShellContextMenu::SetObjects(IShellFolder * psfFolder, LPITEMIDLIST *pidlArray, int nItemCount)
joachim99@69 340 {
joachim99@69 341 // free all allocated datas
joachim99@69 342 if (m_psfFolder && bDelete)
joachim99@69 343 m_psfFolder->Release ();
joachim99@69 344 m_psfFolder = NULL;
joachim99@69 345 FreePIDLArray (m_pidlArray);
joachim99@69 346 m_pidlArray = NULL;
joachim99@69 347
joachim99@69 348 m_psfFolder = psfFolder;
joachim99@69 349
joachim99@69 350 m_pidlArray = (LPITEMIDLIST *) malloc (nItemCount * sizeof (LPITEMIDLIST));
joachim99@69 351
joachim99@69 352 for (int i = 0; i < nItemCount; i++)
joachim99@69 353 m_pidlArray[i] = CopyPIDL (pidlArray[i]);
joachim99@69 354
joachim99@69 355 nItems = nItemCount;
joachim99@69 356 bDelete = FALSE; // indicates wheter m_psfFolder should be deleted by CShellContextMenu
joachim99@69 357 }
joachim99@69 358
joachim99@69 359
joachim99@69 360 void CShellContextMenu::FreePIDLArray(LPITEMIDLIST *pidlArray)
joachim99@69 361 {
joachim99@69 362 if (!pidlArray)
joachim99@69 363 return;
joachim99@69 364
joachim99@69 365 int iSize = _msize (pidlArray) / sizeof (LPITEMIDLIST);
joachim99@69 366
joachim99@69 367 for (int i = 0; i < iSize; i++)
joachim99@69 368 free (pidlArray[i]);
joachim99@69 369 free (pidlArray);
joachim99@69 370 }
joachim99@69 371
joachim99@69 372
joachim99@69 373 LPITEMIDLIST CShellContextMenu::CopyPIDL (LPCITEMIDLIST pidl, int cb)
joachim99@69 374 {
joachim99@69 375 if (cb == -1)
joachim99@69 376 cb = GetPIDLSize (pidl); // Calculate size of list.
joachim99@69 377
joachim99@69 378 LPITEMIDLIST pidlRet = (LPITEMIDLIST) calloc (cb + sizeof (USHORT), sizeof (BYTE));
joachim99@69 379 if (pidlRet)
joachim99@69 380 CopyMemory(pidlRet, pidl, cb);
joachim99@69 381
joachim99@69 382 return (pidlRet);
joachim99@69 383 }
joachim99@69 384
joachim99@69 385
joachim99@69 386 UINT CShellContextMenu::GetPIDLSize (LPCITEMIDLIST pidl)
joachim99@69 387 {
joachim99@69 388 if (!pidl)
joachim99@69 389 return 0;
joachim99@69 390 int nSize = 0;
joachim99@69 391 LPITEMIDLIST pidlTemp = (LPITEMIDLIST) pidl;
joachim99@69 392 while (pidlTemp->mkid.cb)
joachim99@69 393 {
joachim99@69 394 nSize += pidlTemp->mkid.cb;
joachim99@69 395 pidlTemp = (LPITEMIDLIST) (((LPBYTE) pidlTemp) + pidlTemp->mkid.cb);
joachim99@69 396 }
joachim99@69 397 return nSize;
joachim99@69 398 }
joachim99@69 399
joachim99@69 400 HMENU CShellContextMenu::GetMenu()
joachim99@69 401 {
joachim99@69 402 if (!m_hMenu)
joachim99@69 403 {
joachim99@69 404 m_hMenu = CreatePopupMenu(); // create the popupmenu (its empty)
joachim99@69 405 }
joachim99@69 406 return (m_hMenu);
joachim99@69 407 }
joachim99@69 408
joachim99@69 409
joachim99@69 410 // this is workaround function for the Shell API Function SHBindToParent
joachim99@69 411 // SHBindToParent is not available under Win95/98
joachim99@69 412 HRESULT CShellContextMenu::SHBindToParentEx (LPCITEMIDLIST pidl, REFIID riid, VOID **ppv, LPCITEMIDLIST *ppidlLast)
joachim99@69 413 {
joachim99@69 414 HRESULT hr = 0;
joachim99@69 415 if (!pidl || !ppv)
joachim99@69 416 return E_POINTER;
joachim99@69 417
joachim99@69 418 int nCount = GetPIDLCount (pidl);
joachim99@69 419 if (nCount == 0) // desktop pidl of invalid pidl
joachim99@69 420 return E_POINTER;
joachim99@69 421
joachim99@69 422 IShellFolder * psfDesktop = NULL;
joachim99@69 423 SHGetDesktopFolder (&psfDesktop);
joachim99@69 424 if (nCount == 1) // desktop pidl
joachim99@69 425 {
joachim99@69 426 if ((hr = psfDesktop->QueryInterface(riid, ppv)) == S_OK)
joachim99@69 427 {
joachim99@69 428 if (ppidlLast)
joachim99@69 429 *ppidlLast = CopyPIDL (pidl);
joachim99@69 430 }
joachim99@69 431 psfDesktop->Release ();
joachim99@69 432 return hr;
joachim99@69 433 }
joachim99@69 434
joachim99@69 435 LPBYTE pRel = GetPIDLPos (pidl, nCount - 1);
joachim99@69 436 LPITEMIDLIST pidlParent = NULL;
joachim99@69 437 pidlParent = CopyPIDL (pidl, pRel - (LPBYTE) pidl);
joachim99@69 438 IShellFolder * psfFolder = NULL;
joachim99@69 439
joachim99@69 440 if ((hr = psfDesktop->BindToObject (pidlParent, NULL, IID_IShellFolder, (void **) &psfFolder)) != S_OK)
joachim99@69 441 {
joachim99@69 442 free (pidlParent);
joachim99@69 443 psfDesktop->Release ();
joachim99@69 444 return hr;
joachim99@69 445 }
joachim99@69 446 if ((hr = psfFolder->QueryInterface (riid, ppv)) == S_OK)
joachim99@69 447 {
joachim99@69 448 if (ppidlLast)
joachim99@69 449 *ppidlLast = CopyPIDL ((LPCITEMIDLIST) pRel);
joachim99@69 450 }
joachim99@69 451 free (pidlParent);
joachim99@69 452 psfFolder->Release ();
joachim99@69 453 psfDesktop->Release ();
joachim99@69 454 return hr;
joachim99@69 455 }
joachim99@69 456
joachim99@69 457
joachim99@69 458 LPBYTE CShellContextMenu::GetPIDLPos (LPCITEMIDLIST pidl, int nPos)
joachim99@69 459 {
joachim99@69 460 if (!pidl)
joachim99@69 461 return 0;
joachim99@69 462 int nCount = 0;
joachim99@69 463
joachim99@69 464 BYTE * pCur = (BYTE *) pidl;
joachim99@69 465 while (((LPCITEMIDLIST) pCur)->mkid.cb)
joachim99@69 466 {
joachim99@69 467 if (nCount == nPos)
joachim99@69 468 return pCur;
joachim99@69 469 nCount++;
joachim99@69 470 pCur += ((LPCITEMIDLIST) pCur)->mkid.cb; // + sizeof(pidl->mkid.cb);
joachim99@69 471 }
joachim99@69 472 if (nCount == nPos)
joachim99@69 473 return pCur;
joachim99@69 474 return NULL;
joachim99@69 475 }
joachim99@69 476
joachim99@69 477
joachim99@69 478 int CShellContextMenu::GetPIDLCount (LPCITEMIDLIST pidl)
joachim99@69 479 {
joachim99@69 480 if (!pidl)
joachim99@69 481 return 0;
joachim99@69 482
joachim99@69 483 int nCount = 0;
joachim99@69 484 BYTE* pCur = (BYTE *) pidl;
joachim99@69 485 while (((LPCITEMIDLIST) pCur)->mkid.cb)
joachim99@69 486 {
joachim99@69 487 nCount++;
joachim99@69 488 pCur += ((LPCITEMIDLIST) pCur)->mkid.cb;
joachim99@69 489 }
joachim99@69 490 return nCount;
joachim99@69 491 }
joachim99@69 492
joachim99@69 493 #endif
joachim99@69 494