How to populate context menu for multiple shell items (rather than a single IShellItem)
See the question and my original answer on StackOverflowYou need to use the IShellItemArray interface so, something like that for two items:
// get two Shell Items and get their respective absolute PIDLs
CComPtr<IShellItem> item1;
HRCHECK(SHCreateItemFromParsingName(L"c:\\myPath1\\myFile1.myExt1", NULL, IID_PPV_ARGS(&item1)));
CComQIPtr<IPersistIDList> idl1(item1);
CComHeapPtr<ITEMIDLIST_ABSOLUTE> spidl1;
HRCHECK(idl1->GetIDList(&spidl1));
CComPtr<IShellItem> item2;
HRCHECK(SHCreateItemFromParsingName(L"c:\\myPath2\\myFile2.myExt2", NULL, IID_PPV_ARGS(&item2)));
CComQIPtr<IPersistIDList> idl2(item2);
CComHeapPtr<ITEMIDLIST_ABSOLUTE> spidl2;
HRCHECK(idl2->GetIDList(&spidl2));
// build a Shell Item Array from them
LPCITEMIDLIST list[2];
list[0] = spidl1;
list[1] = spidl2;
CComPtr<IShellItemArray> array;
HRCHECK(SHCreateShellItemArrayFromIDLists(2, list, &array));
// get the menu object
CComPtr<IContextMenu> menu;
HRCHECK(array->BindToHandler(NULL, BHID_SFUIObject, IID_PPV_ARGS(&menu)));
// ... etc ...
HMENU hMenu= CreatePopupMenu();
HRCHECK(menu->QueryContextMenu(hMenu, 0, 1, 0x7FFF, CMF_EXPLORE || CMF_ITEMMENU));
Usually, you don't have to create arrays, as in copy-paste or drag-and-drop operations, or context menu open calls (namespace extensions, etc.), an array is present in the clipboard or in the data object that's passed in.