/****************************** Module Header ******************************\
Module Name:  FileContextMenuExt.h
Project:      CppShellExtContextMenuHandler
Copyright (c) Microsoft Corporation.

The code sample demonstrates creating a Shell context menu handler with C++.

A context menu handler is a shell extension handler that adds commands to an
existing context menu. Context menu handlers are associated with a particular
file class and are called any time a context menu is displayed for a member
of the class. While you can add items to a file class context menu with the
registry, the items will be the same for all members of the class. By
implementing and registering such a handler, you can dynamically add items to
an object's context menu, customized for the particular object.

The example context menu handler adds the menu item "Display File Name (C++)"
to the context menu when you right-click a .cpp file in the Windows Explorer.
Clicking the menu item brings up a message box that displays the full path
of the .cpp file.

This source is subject to the Microsoft Public License.
See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
All other rights reserved.

THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

#ifndef CONTEXTMENUEXT_H
#define CONTEXTMENUEXT_H

#include "ContextMenuData.h"

// clang-format off
#include <windows.h>
#include <shellapi.h>
#include <shlobj.h>
#include <uxtheme.h>
// clang-format on

typedef HRESULT(WINAPI* pGetBufferedPaintBits)(HPAINTBUFFER hBufferedPaint,
                                               RGBQUAD** ppbBuffer,
                                               int* pcxRow);
typedef HPAINTBUFFER(WINAPI* pBeginBufferedPaint)(HDC hdcTarget,
                                                  const RECT* prcTarget,
                                                  BP_BUFFERFORMAT dwFormat,
                                                  BP_PAINTPARAMS* pPaintParams,
                                                  HDC* phdc);
typedef HRESULT(WINAPI* pEndBufferedPaint)(HPAINTBUFFER hBufferedPaint, BOOL fUpdateTarget);

class ContextMenuExt: public IShellExtInit, public IContextMenu3, public ContextMenuData
{
public:
    // IUnknown
    IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv);
    IFACEMETHODIMP_(ULONG) AddRef();
    IFACEMETHODIMP_(ULONG) Release();

    // IShellExtInit
    IFACEMETHODIMP Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID);

    // IContextMenu
    IFACEMETHODIMP
    QueryContextMenu(HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags);
    IFACEMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
    IFACEMETHODIMP GetCommandString(UINT_PTR idCommand,
                                    UINT uFlags,
                                    UINT* pwReserved,
                                    LPSTR pszName,
                                    UINT cchMax);

    IFACEMETHODIMP HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam);
    IFACEMETHODIMP HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* plResult);

    ContextMenuExt(void);

protected:
    ~ContextMenuExt(void);
    void processFile(HDROP hDrop, int i);

private:
    // Reference count of component.
    long m_cRef;

    HBITMAP getBitmap(HICON icon);
    HBITMAP getBitmapLegacy(HICON hIcon);
    bool legacyIcon;

    bool createAndAddMenuItem(MegaInterface::StringID request,
                              UINT IDM,
                              HMENU hMenu,
                              UINT indexMenu,
                              UINT idCmdFirst);

    pGetBufferedPaintBits GetBufferedPaintBits;
    pBeginBufferedPaint BeginBufferedPaint;
    pEndBufferedPaint EndBufferedPaint;

    HBITMAP m_hMenuBmp;
    HICON hIcon;

    PCWSTR m_pszUploadMenuText;
    PCSTR m_pszUploadVerb;
    PCWSTR m_pwszUploadVerb;
    PCSTR m_pszUploadVerbCanonicalName;
    PCWSTR m_pwszUploadVerbCanonicalName;
    PCSTR m_pszUploadVerbHelpText;
    PCWSTR m_pwszUploadVerbHelpText;

    PCWSTR m_pszGetLinkMenuText;
    PCSTR m_pszGetLinkVerb;
    PCWSTR m_pwszGetLinkVerb;
    PCSTR m_pszGetLinkVerbCanonicalName;
    PCWSTR m_pwszGetLinkVerbCanonicalName;
    PCSTR m_pszGetLinkVerbHelpText;
    PCWSTR m_pwszGetLinkVerbHelpText;

    PCWSTR m_pszRemoveFromLeftPaneMenuText;
    PCSTR m_pszRemoveFromLeftPaneVerb;
    PCWSTR m_pwszRemoveFromLeftPaneVerb;
    PCSTR m_pszRemoveFromLeftPaneVerbCanonicalName;
    PCWSTR m_pwszRemoveFromLeftPaneVerbCanonicalName;
    PCSTR m_pszRemoveFromLeftPaneVerbHelpText;
    PCWSTR m_pwszRemoveFromLeftPaneVerbHelpText;

    PCWSTR m_pszViewOnMEGAMenuText;
    PCSTR m_pszViewOnMEGAVerb;
    PCWSTR m_pwszViewOnMEGAVerb;
    PCSTR m_pszViewOnMEGAVerbCanonicalName;
    PCWSTR m_pwszViewOnMEGAVerbCanonicalName;
    PCSTR m_pszViewOnMEGAVerbHelpText;
    PCWSTR m_pwszViewOnMEGAVerbHelpText;

    PCWSTR m_pszViewVersionsMenuText;
    PCSTR m_pszViewVersionsVerb;
    PCWSTR m_pwszViewVersionsVerb;
    PCSTR m_pszViewVersionsVerbCanonicalName;
    PCWSTR m_pwszViewVersionsVerbCanonicalName;
    PCSTR m_pszViewVersionsVerbHelpText;
    PCWSTR m_pwszViewVersionsVerbHelpText;

    PCWSTR m_pszSyncMenuText;
    PCSTR m_pszSyncVerb;
    PCWSTR m_pwszSyncVerb;
    PCSTR m_pszSyncVerbCanonicalName;
    PCWSTR m_pwszSyncVerbCanonicalName;
    PCSTR m_pszSyncVerbHelpText;
    PCWSTR m_pwszSyncVerbHelpText;

    PCWSTR m_pszBackupMenuText;
    PCSTR m_pszBackupVerb;
    PCWSTR m_pwszBackupVerb;
    PCSTR m_pszBackupVerbCanonicalName;
    PCWSTR m_pwszBackupVerbCanonicalName;
    PCSTR m_pszBackupVerbHelpText;
    PCWSTR m_pwszBackupVerbHelpText;
};

#endif
