mirror of
https://github.com/Alukym/VMProtect-Source.git
synced 2025-06-23 21:27:53 -05:00
Initial commit
This commit is contained in:
320
shellext/context_menu.cc
Normal file
320
shellext/context_menu.cc
Normal file
@ -0,0 +1,320 @@
|
||||
#include "context_menu.h"
|
||||
#include "resource.h"
|
||||
|
||||
extern HINSTANCE instance;
|
||||
extern long dll_ref_count;
|
||||
|
||||
#define IDM_PROTECT 0
|
||||
|
||||
/**
|
||||
* ContextMenuExt
|
||||
*/
|
||||
|
||||
ContextMenuExt::ContextMenuExt(void) : ref_count_(1)
|
||||
{
|
||||
InterlockedIncrement(&dll_ref_count);
|
||||
}
|
||||
|
||||
ContextMenuExt::~ContextMenuExt(void)
|
||||
{
|
||||
InterlockedDecrement(&dll_ref_count);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::QueryInterface(REFIID riid, void **ppv)
|
||||
{
|
||||
static const QITAB qit[] =
|
||||
{
|
||||
QITABENT(ContextMenuExt, IContextMenu), //-V221
|
||||
QITABENT(ContextMenuExt, IContextMenu2), //-V221
|
||||
QITABENT(ContextMenuExt, IContextMenu3), //-V221
|
||||
QITABENT(ContextMenuExt, IShellExtInit), //-V221
|
||||
{ 0 },
|
||||
#pragma warning( push )
|
||||
#pragma warning( disable: 4838 )
|
||||
};
|
||||
#pragma warning( pop )
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ContextMenuExt::AddRef()
|
||||
{
|
||||
return InterlockedIncrement(&ref_count_);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) ContextMenuExt::Release()
|
||||
{
|
||||
ULONG res = InterlockedDecrement(&ref_count_);
|
||||
if (!res)
|
||||
delete this;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define GetPIDLFolder(pida) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[0])
|
||||
#define GetPIDLItem(pida, i) (LPCITEMIDLIST)(((LPBYTE)pida)+(pida)->aoffset[i+1])
|
||||
|
||||
std::wstring PathName(LPCITEMIDLIST parent, LPCITEMIDLIST child)
|
||||
{
|
||||
IShellFolder *shellFolder = NULL;
|
||||
IShellFolder *parentFolder = NULL;
|
||||
STRRET name;
|
||||
TCHAR * szDisplayName = NULL;
|
||||
std::wstring ret;
|
||||
HRESULT hr;
|
||||
|
||||
hr = ::SHGetDesktopFolder(&shellFolder);
|
||||
if (!SUCCEEDED(hr) || shellFolder == NULL)
|
||||
return ret;
|
||||
if (parent)
|
||||
{
|
||||
hr = shellFolder->BindToObject(parent, 0, IID_IShellFolder, (void**) &parentFolder);
|
||||
if (!SUCCEEDED(hr) || parentFolder == NULL)
|
||||
parentFolder = shellFolder;
|
||||
}
|
||||
else
|
||||
{
|
||||
parentFolder = shellFolder;
|
||||
}
|
||||
|
||||
if ((parentFolder != 0)&&(child != 0))
|
||||
{
|
||||
hr = parentFolder->GetDisplayNameOf(child, SHGDN_NORMAL | SHGDN_FORPARSING, &name);
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
parentFolder->Release();
|
||||
return ret;
|
||||
}
|
||||
hr = StrRetToStr (&name, child, &szDisplayName);
|
||||
if (!SUCCEEDED(hr))
|
||||
return ret;
|
||||
}
|
||||
parentFolder->Release();
|
||||
if (szDisplayName == NULL)
|
||||
{
|
||||
CoTaskMemFree(szDisplayName);
|
||||
return ret;
|
||||
}
|
||||
ret = szDisplayName;
|
||||
CoTaskMemFree(szDisplayName);
|
||||
return ret;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::Initialize(
|
||||
LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hKeyProgID)
|
||||
{
|
||||
file_names_.clear();
|
||||
if (!pDataObj)
|
||||
return E_INVALIDARG;
|
||||
|
||||
static int g_shellidlist = RegisterClipboardFormat(CFSTR_SHELLIDLIST);
|
||||
|
||||
// get selected files/folders
|
||||
if (pDataObj)
|
||||
{
|
||||
STGMEDIUM medium;
|
||||
FORMATETC fmte = {(CLIPFORMAT)g_shellidlist,
|
||||
(DVTARGETDEVICE FAR *)NULL,
|
||||
DVASPECT_CONTENT,
|
||||
-1,
|
||||
TYMED_HGLOBAL};
|
||||
HRESULT hres = pDataObj->GetData(&fmte, &medium);
|
||||
|
||||
if (SUCCEEDED(hres) && medium.hGlobal)
|
||||
{
|
||||
if (pidlFolder)
|
||||
{
|
||||
FORMATETC etc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
|
||||
STGMEDIUM stg = { TYMED_HGLOBAL };
|
||||
if ( FAILED( pDataObj->GetData ( &etc, &stg )))
|
||||
{
|
||||
ReleaseStgMedium ( &medium );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
|
||||
HDROP drop = (HDROP)GlobalLock(stg.hGlobal);
|
||||
if ( NULL == drop )
|
||||
{
|
||||
ReleaseStgMedium ( &stg );
|
||||
ReleaseStgMedium ( &medium );
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
int count = DragQueryFile(drop, (UINT)-1, NULL, 0);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
// find the path length in chars
|
||||
UINT len = DragQueryFile(drop, i, NULL, 0);
|
||||
if (len == 0)
|
||||
continue;
|
||||
TCHAR * szFileName = new TCHAR[len+1];
|
||||
if (0 == DragQueryFile(drop, i, szFileName, len+1))
|
||||
{
|
||||
delete [] szFileName;
|
||||
continue;
|
||||
}
|
||||
file_names_.push_back(szFileName);
|
||||
delete [] szFileName;
|
||||
} // for (int i = 0; i < count; i++)
|
||||
GlobalUnlock ( drop );
|
||||
ReleaseStgMedium ( &stg );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Enumerate PIDLs which the user has selected
|
||||
CIDA* cida = (CIDA*)GlobalLock(medium.hGlobal);
|
||||
LPCITEMIDLIST parent( GetPIDLFolder (cida));
|
||||
|
||||
int count = cida->cidl;
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
LPCITEMIDLIST child (GetPIDLItem (cida, i));
|
||||
file_names_.push_back(PathName(parent, child));
|
||||
} // for (int i = 0; i < count; ++i)
|
||||
GlobalUnlock(medium.hGlobal);
|
||||
}
|
||||
|
||||
ReleaseStgMedium ( &medium );
|
||||
if (medium.pUnkForRelease)
|
||||
{
|
||||
IUnknown* relInterface = (IUnknown*)medium.pUnkForRelease;
|
||||
relInterface->Release();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return file_names_.empty() ? E_FAIL : S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::QueryContextMenu(
|
||||
HMENU hMenu, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast, UINT uFlags)
|
||||
{
|
||||
if (CMF_DEFAULTONLY & uFlags)
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
|
||||
|
||||
MENUITEMINFOW mii = {};
|
||||
mii.cbSize = sizeof(mii);
|
||||
mii.fMask = MIIM_BITMAP | MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
|
||||
mii.wID = idCmdFirst + IDM_PROTECT;
|
||||
mii.fType = MFT_STRING;
|
||||
mii.dwTypeData = L"Protect with VMProtect";
|
||||
mii.fState = MFS_ENABLED;
|
||||
mii.hbmpItem = utils_.IconToBitmapPARGB32(instance, IDI_ICON);
|
||||
if (!InsertMenuItemW(hMenu, indexMenu, TRUE, &mii))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
|
||||
MENUITEMINFOW sep = {};
|
||||
sep.cbSize = sizeof(sep);
|
||||
sep.fMask = MIIM_TYPE;
|
||||
sep.fType = MFT_SEPARATOR;
|
||||
if (!InsertMenuItemW(hMenu, indexMenu + 1, TRUE, &sep))
|
||||
return HRESULT_FROM_WIN32(GetLastError());
|
||||
|
||||
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(IDM_PROTECT + 1));
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::InvokeCommand(LPCMINVOKECOMMANDINFO command_info)
|
||||
{
|
||||
if (HIWORD(command_info->lpVerb))
|
||||
return E_INVALIDARG;
|
||||
|
||||
switch (LOWORD(command_info->lpVerb)) {
|
||||
case IDM_PROTECT:
|
||||
{
|
||||
wchar_t module_name[MAX_PATH];
|
||||
if (GetModuleFileNameW(instance, module_name, _countof(module_name)) != 0) {
|
||||
wchar_t *name = NULL;
|
||||
wchar_t *ptr = module_name;
|
||||
while (*ptr) {
|
||||
if (*ptr == '/' || *ptr == '\\')
|
||||
name = ptr + 1;
|
||||
ptr++;
|
||||
}
|
||||
if (name) {
|
||||
wcscpy_s(name, module_name + MAX_PATH - name - 1, L"VMProtect.exe"); //-V782
|
||||
for (size_t i = 0; i < file_names_.size(); i++) {
|
||||
wchar_t file_name[MAX_PATH * 2 + 2];
|
||||
wnsprintf(file_name, MAX_PATH * 2, L"\"%s\" \"%s\"", module_name, file_names_[i].c_str());
|
||||
PROCESS_INFORMATION pi = PROCESS_INFORMATION();
|
||||
STARTUPINFO si = STARTUPINFO();
|
||||
if (!CreateProcessW(module_name, file_name, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
|
||||
MessageBoxW(command_info->hwnd, L"Error executing VMProtect", L"Error", MB_ICONERROR | MB_OK);
|
||||
break;
|
||||
}
|
||||
CloseHandle(pi.hProcess);
|
||||
CloseHandle(pi.hThread);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::GetCommandString(UINT_PTR idCommand,
|
||||
UINT uFlags, UINT *pwReserved, LPSTR pszName, UINT cchMax)
|
||||
{
|
||||
if (idCommand == IDM_PROTECT) {
|
||||
switch (uFlags) {
|
||||
case GCS_HELPTEXTA:
|
||||
strncpy_s(reinterpret_cast<PSTR>(pszName), cchMax, "Protect with VMProtect", cchMax);
|
||||
return S_OK;
|
||||
case GCS_HELPTEXTW:
|
||||
wcsncpy_s(reinterpret_cast<PWSTR>(pszName), cchMax, L"Protect with VMProtect", cchMax);
|
||||
return S_OK;
|
||||
default:
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
}
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::HandleMenuMsg(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
LRESULT res;
|
||||
return HandleMenuMsg2(uMsg, wParam, lParam, &res);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP ContextMenuExt::HandleMenuMsg2(UINT uMsg, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
|
||||
{
|
||||
LRESULT res;
|
||||
if (!pResult)
|
||||
pResult = &res;
|
||||
*pResult = FALSE;
|
||||
|
||||
switch (uMsg)
|
||||
{
|
||||
case WM_MEASUREITEM:
|
||||
{
|
||||
MEASUREITEMSTRUCT* lpmis = (MEASUREITEMSTRUCT*)lParam;
|
||||
if (lpmis==NULL)
|
||||
break;
|
||||
lpmis->itemWidth += 2;
|
||||
if(lpmis->itemHeight < 16)
|
||||
lpmis->itemHeight = 16;
|
||||
*pResult = TRUE;
|
||||
}
|
||||
break;
|
||||
case WM_DRAWITEM:
|
||||
{
|
||||
DRAWITEMSTRUCT* lpdis = (DRAWITEMSTRUCT*)lParam;
|
||||
if (!lpdis || (lpdis->CtlType != ODT_MENU))
|
||||
break; //not for a menu
|
||||
HICON icon = static_cast<HICON>(LoadImageW(instance, MAKEINTRESOURCE(IDI_ICON), IMAGE_ICON, 16, 16, LR_DEFAULTCOLOR));
|
||||
if (!icon)
|
||||
break;
|
||||
DrawIconEx(lpdis->hDC,
|
||||
1,
|
||||
lpdis->rcItem.top + (lpdis->rcItem.bottom - lpdis->rcItem.top - 16) / 2,
|
||||
icon, 16, 16,
|
||||
0, 0, DI_NORMAL);
|
||||
DestroyIcon(icon);
|
||||
*pResult = TRUE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
return NOERROR;
|
||||
}
|
Reference in New Issue
Block a user