private static IntPtr CreateMenuCallbackWnd(WinAPI.IContextMenu2 contextMenu)
        {
            string icmCallbackWnd = "ICMCALLBACKWND";

            WinAPI.WNDCLASS wclass = new WinAPI.WNDCLASS();
            wclass.lpszClassName = icmCallbackWnd;
            wclass.lpfnWndProc   = Marshal.GetFunctionPointerForDelegate(MenuCallbackDelegate);
            wclass.hInstance     = IntPtr.Zero;
            int    r      = WinAPI.RegisterClassW(ref wclass);
            IntPtr result = WinAPI.CreateWindowEx(0, icmCallbackWnd, icmCallbackWnd, WinAPI.WindowStyles.WS_POPUPWINDOW,
                                                  0, 0, 0, 0, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, Marshal.GetIUnknownForObject(contextMenu));

            return(result);
        }
        private static void ShowShellContextMenu(IEnumerable <string> paths, IntPtr windowHandle, IntVector2 mousePos)
        {
            WinAPI.IShellFolder desktop = null;
            var pathPIDL = IntPtr.Zero;

            WinAPI.IShellFolder shellFolder = null;
            uint pchEaten = 0;

            WinAPI.SFGAO attr = 0;
            IntPtr       ppv;
            var          filePIDL = IntPtr.Zero;

            WinAPI.IContextMenu iCMenu = null;
            var shellContextMenu       = IntPtr.Zero;
            var callbackWnd            = IntPtr.Zero;

            WinAPI.IContextMenu2 iCMenu2 = null;
            Action Finalize = () => {
                if (iCMenu2 != null)
                {
                    Marshal.FinalReleaseComObject(iCMenu2);
                }
                if (iCMenu != null)
                {
                    Marshal.FinalReleaseComObject(iCMenu);
                }
                if (shellFolder != null)
                {
                    Marshal.FinalReleaseComObject(shellFolder);
                }
                if (desktop != null)
                {
                    Marshal.FinalReleaseComObject(desktop);
                }
                if (filePIDL != IntPtr.Zero)
                {
                    WinAPI.CoTaskMemFree(filePIDL);
                }
                if (pathPIDL != IntPtr.Zero)
                {
                    WinAPI.CoTaskMemFree(pathPIDL);
                }
                if (shellContextMenu != IntPtr.Zero)
                {
                    WinAPI.DestroyMenu(shellContextMenu);
                }
                if (callbackWnd != IntPtr.Zero)
                {
                    WinAPI.DestroyWindow(callbackWnd);
                }
            };
            Action <int> checkHResult = (result) => {
                if (result != 0)
                {
                    Finalize();
                    Marshal.ThrowExceptionForHR(result);
                }
            };
            int r     = 0;
            var pidls = new List <IntPtr>();

            foreach (var path in paths)
            {
                string dir      = Path.GetDirectoryName(path) ?? "";
                string filename = Path.GetFileNameWithoutExtension(path);
                string fileExt  = Path.GetExtension(path);
                string pathRoot = Path.GetPathRoot(path);
                if (!dir.StartsWith(pathRoot))
                {
                    dir = Path.Combine(pathRoot, dir);
                }
                if (!string.IsNullOrEmpty(filename) && !string.IsNullOrEmpty(fileExt))
                {
                    filename += fileExt;
                }
                r = WinAPI.SHGetDesktopFolder(out desktop);
                checkHResult(r);
                if (string.IsNullOrEmpty(filename))
                {
                    r = WinAPI.SHGetSpecialFolderLocation(IntPtr.Zero, WinAPI.CSIDL.CSIDL_DRIVES, ref pathPIDL);
                    checkHResult(r);
                    r = desktop.BindToObject(pathPIDL, IntPtr.Zero, ref WinAPI.Guid_IShellFolder.IID_IShellFolder, out ppv);
                    checkHResult(r);
                    shellFolder = (WinAPI.IShellFolder)Marshal.GetObjectForIUnknown(ppv);
                    r           = shellFolder.ParseDisplayName(windowHandle, IntPtr.Zero, dir, ref pchEaten, out filePIDL, ref attr);
                    checkHResult(r);
                }
                else
                {
                    r = desktop.ParseDisplayName(windowHandle, IntPtr.Zero, dir, ref pchEaten, out pathPIDL, ref attr);
                    checkHResult(r);
                    r = desktop.BindToObject(pathPIDL, IntPtr.Zero, ref WinAPI.IID_IShellFolder, out ppv);
                    checkHResult(r);
                    shellFolder = (WinAPI.IShellFolder)Marshal.GetObjectForIUnknown(ppv);
                    r           = shellFolder.ParseDisplayName(windowHandle, IntPtr.Zero, filename, ref pchEaten, out filePIDL, ref attr);
                    checkHResult(r);
                }
                pidls.Add(filePIDL);
            }
            r = shellFolder.GetUIObjectOf(windowHandle, (uint)pidls.Count, ref pidls.ToArray()[0], ref WinAPI.IID_IContextMenu, 0, out ppv);
            checkHResult(r);
            iCMenu           = (WinAPI.IContextMenu)Marshal.GetObjectForIUnknown(ppv);
            shellContextMenu = WinAPI.CreatePopupMenu();
            r = iCMenu.QueryContextMenu(shellContextMenu, 0, 1, 0x7FFF, WinAPI.CMF.CMF_EXPLORE);
            if ((r & 0x80000000) == 0)
            {
                var ppv2 = IntPtr.Zero;
                Marshal.QueryInterface(ppv, ref WinAPI.IID_IContextMenu2, out ppv2);
                iCMenu2     = (WinAPI.IContextMenu2)Marshal.GetObjectForIUnknown(ppv2);
                callbackWnd = CreateMenuCallbackWnd(iCMenu2);
                var popupMenuResult = WinAPI.TrackPopupMenuEx(shellContextMenu,
                                                              WinAPI.TPM_LEFTALIGN | WinAPI.TPM_LEFTBUTTON | WinAPI.TPM_RIGHTBUTTON | WinAPI.TPM_RETURNCMD,
                                                              mousePos.X, mousePos.Y, callbackWnd, IntPtr.Zero);
                if (popupMenuResult > 0)
                {
                    var iCmd = popupMenuResult - 1;
                    var CMD  = new WinAPI.CMINVOKECOMMANDINFO {
                        cbSize = (uint)Marshal.SizeOf(typeof(WinAPI.CMINVOKECOMMANDINFO)),
                        hwnd   = windowHandle,
                        verb   = (IntPtr)iCmd,
                        nShow  = 1,                        // SW_SHOWNORMAL
                    };
                    r = iCMenu.InvokeCommand(ref CMD);
                    checkHResult(r);
                }
            }
            Finalize();
        }