mirror of
https://github.com/reactos/reactos.git
synced 2025-02-24 17:34:57 +00:00
- populate Open With with found entries
- see http://windowsxp.mvps.org/OpenWith.htm - silence debug messages - invoke shell extension's InvokeCommand on a event svn path=/trunk/; revision=29981
This commit is contained in:
parent
d4d9d8158b
commit
3b7c69f9c9
2 changed files with 416 additions and 17 deletions
|
@ -23,7 +23,7 @@
|
|||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#define YDEBUG
|
||||
//#define YDEBUG
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -46,9 +46,11 @@ typedef struct
|
|||
const IShellExtInitVtbl *lpvtblShellExtInit;
|
||||
LONG wId;
|
||||
volatile LONG ref;
|
||||
WCHAR ** szArray;
|
||||
UINT size;
|
||||
UINT count;
|
||||
} SHEOWImpl;
|
||||
|
||||
|
||||
static const IShellExtInitVtbl eivt;
|
||||
static const IContextMenu2Vtbl cmvt;
|
||||
static HRESULT WINAPI SHEOWCm_fnQueryInterface(IContextMenu2 *iface, REFIID riid, LPVOID *ppvObj);
|
||||
|
@ -145,7 +147,8 @@ AddItems(SHEOWImpl *This, HMENU hMenu, UINT idCmdFirst)
|
|||
{
|
||||
UINT count = 0;
|
||||
MENUITEMINFOW mii;
|
||||
WCHAR szBuffer[50];
|
||||
WCHAR szBuffer[MAX_PATH];
|
||||
UINT index;
|
||||
static const WCHAR szChoose[] = { 'C','h','o','o','s','e',' ','P','r','o','g','r','a','m','.','.','.',0 };
|
||||
|
||||
ZeroMemory(&mii, sizeof(mii));
|
||||
|
@ -153,7 +156,25 @@ AddItems(SHEOWImpl *This, HMENU hMenu, UINT idCmdFirst)
|
|||
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
|
||||
mii.fType = MFT_STRING;
|
||||
mii.fState = MFS_ENABLED;
|
||||
mii.wID = idCmdFirst;
|
||||
|
||||
for (index = 0; index < This->count; index++)
|
||||
{
|
||||
mii.wID = idCmdFirst;
|
||||
mii.dwTypeData = (LPWSTR)This->szArray[index];
|
||||
if (InsertMenuItemW(hMenu, -1, TRUE, &mii))
|
||||
{
|
||||
idCmdFirst++;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
mii.fMask = MIIM_TYPE | MIIM_ID;
|
||||
mii.fType = MFT_SEPARATOR;
|
||||
mii.wID = -1;
|
||||
InsertMenuItemW(hMenu, -1, TRUE, &mii);
|
||||
|
||||
mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE;
|
||||
mii.fType = MFT_STRING;
|
||||
|
||||
if (!LoadStringW(shell32_hInstance, IDS_OPEN_WITH_CHOOSE, szBuffer, sizeof(szBuffer) / sizeof(WCHAR)))
|
||||
{
|
||||
|
@ -161,8 +182,9 @@ AddItems(SHEOWImpl *This, HMENU hMenu, UINT idCmdFirst)
|
|||
wcscpy(szBuffer, szChoose);
|
||||
}
|
||||
|
||||
mii.wID = idCmdFirst;
|
||||
mii.dwTypeData = (LPWSTR)szBuffer;
|
||||
if (InsertMenuItemW(hMenu, 0, TRUE, &mii))
|
||||
if (InsertMenuItemW(hMenu, -1, TRUE, &mii))
|
||||
count++;
|
||||
|
||||
return count;
|
||||
|
@ -180,6 +202,7 @@ static HRESULT WINAPI SHEOWCm_fnQueryContextMenu(
|
|||
MENUITEMINFOW mii;
|
||||
USHORT items = 0;
|
||||
WCHAR szBuffer[100];
|
||||
BOOL bDefault = FALSE;
|
||||
|
||||
HMENU hSubMenu = NULL;
|
||||
SHEOWImpl *This = impl_from_IContextMenu(iface);
|
||||
|
@ -190,14 +213,26 @@ static HRESULT WINAPI SHEOWCm_fnQueryContextMenu(
|
|||
return E_FAIL;
|
||||
}
|
||||
|
||||
|
||||
hSubMenu = CreatePopupMenu();
|
||||
if (hSubMenu == NULL)
|
||||
if (This->count)
|
||||
{
|
||||
ERR("failed to create submenu");
|
||||
return E_FAIL;
|
||||
hSubMenu = CreatePopupMenu();
|
||||
if (hSubMenu == NULL)
|
||||
{
|
||||
ERR("failed to create submenu");
|
||||
return E_FAIL;
|
||||
}
|
||||
items = AddItems(This, hSubMenu, idCmdFirst + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no file association found */
|
||||
UINT pos = GetMenuDefaultItem(hmenu, TRUE, 0);
|
||||
if (pos != -1)
|
||||
{
|
||||
/* replace default item with "Open With" action */
|
||||
bDefault = DeleteMenu(hmenu, pos, MF_BYPOSITION);
|
||||
}
|
||||
}
|
||||
items = AddItems(This, hSubMenu, idCmdFirst);
|
||||
|
||||
ZeroMemory(&mii, sizeof(mii));
|
||||
mii.cbSize = sizeof(mii);
|
||||
|
@ -209,7 +244,14 @@ static HRESULT WINAPI SHEOWCm_fnQueryContextMenu(
|
|||
}
|
||||
mii.dwTypeData = (LPWSTR) szBuffer;
|
||||
mii.fState = MFS_ENABLED;
|
||||
mii.wID = idCmdFirst + items;
|
||||
if (bDefault)
|
||||
{
|
||||
mii.fState |= MFS_DEFAULT;
|
||||
}
|
||||
|
||||
mii.wID = idCmdFirst;
|
||||
This->wId = idCmdFirst;
|
||||
|
||||
mii.fType = MFT_STRING;
|
||||
if (InsertMenuItemW( hmenu, 0, TRUE, &mii))
|
||||
items++;
|
||||
|
@ -222,10 +264,21 @@ static HRESULT WINAPI
|
|||
SHEOWCm_fnInvokeCommand( IContextMenu2* iface, LPCMINVOKECOMMANDINFO lpici )
|
||||
{
|
||||
SHEOWImpl *This = impl_from_IContextMenu(iface);
|
||||
|
||||
TRACE("This %p\n", This);
|
||||
TRACE("This %p wId %x count %u verb %x\n", This, This->wId, This->count, LOWORD(lpici->lpVerb));
|
||||
|
||||
return E_FAIL;
|
||||
if (This->wId > LOWORD(lpici->lpVerb) || This->count + This->wId < LOWORD(lpici->lpVerb))
|
||||
return E_FAIL;
|
||||
|
||||
if (This->wId == LOWORD(lpici->lpVerb))
|
||||
{
|
||||
/* show Open As dialog */
|
||||
return S_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* show program select dialog */
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static HRESULT WINAPI
|
||||
|
@ -264,6 +317,329 @@ static const IContextMenu2Vtbl cmvt =
|
|||
SHEOWCm_fnHandleMenuMsg
|
||||
};
|
||||
|
||||
BOOL
|
||||
SHEOW_ResizeArray(SHEOWImpl *This)
|
||||
{
|
||||
WCHAR ** new_array;
|
||||
UINT ncount;
|
||||
|
||||
if (This->count == 0)
|
||||
ncount = 10;
|
||||
else
|
||||
ncount = This->count * 2;
|
||||
|
||||
new_array = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ncount * sizeof(WCHAR*));
|
||||
|
||||
if (!new_array)
|
||||
return FALSE;
|
||||
|
||||
if (This->szArray)
|
||||
{
|
||||
memcpy(new_array, This->szArray, This->count * sizeof(WCHAR*));
|
||||
HeapFree(GetProcessHeap(), 0, This->szArray);
|
||||
}
|
||||
|
||||
This->szArray = new_array;
|
||||
This->size = ncount;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SHEOW_AddOWItem(SHEOWImpl *This, WCHAR * szAppName)
|
||||
{
|
||||
UINT index;
|
||||
WCHAR * szPtr;
|
||||
|
||||
if (This->count + 1 >= This->size || !This->szArray)
|
||||
{
|
||||
if (!SHEOW_ResizeArray(This))
|
||||
return;
|
||||
}
|
||||
|
||||
szPtr = wcsrchr(szAppName, '.');
|
||||
if (szPtr)
|
||||
{
|
||||
szPtr[0] = 0;
|
||||
}
|
||||
|
||||
for(index = 0; index < This->count; index++)
|
||||
{
|
||||
if (!wcsicmp(This->szArray[index], szAppName))
|
||||
return;
|
||||
}
|
||||
This->szArray[This->count] = wcsdup(szAppName);
|
||||
|
||||
if (This->szArray[This->count])
|
||||
This->count++;
|
||||
}
|
||||
|
||||
UINT
|
||||
SHEW_AddOpenWithProgId(SHEOWImpl *This, HKEY hKey)
|
||||
{
|
||||
FIXME("implement me :)))\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
UINT
|
||||
SHEW_AddOpenWithItem(SHEOWImpl *This, HKEY hKey)
|
||||
{
|
||||
|
||||
UINT NumItems = 0;
|
||||
DWORD dwIndex = 0;
|
||||
DWORD dwName, dwValue;
|
||||
LONG result = ERROR_SUCCESS;
|
||||
WCHAR szName[10];
|
||||
WCHAR szValue[MAX_PATH];
|
||||
WCHAR szMRUList[MAX_PATH] = {0};
|
||||
|
||||
static const WCHAR szMRU[] = {'M','R','U','L','i','s','t', 0 };
|
||||
|
||||
while(result == ERROR_SUCCESS)
|
||||
{
|
||||
dwName = sizeof(szName);
|
||||
dwValue = sizeof(szValue);
|
||||
|
||||
|
||||
result = RegEnumValueW(hKey,
|
||||
dwIndex,
|
||||
szName,
|
||||
&dwName,
|
||||
NULL,
|
||||
NULL,
|
||||
(LPBYTE)szValue,
|
||||
&dwValue);
|
||||
szName[9] = 0;
|
||||
szValue[MAX_PATH-1] = 0;
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
if (wcsicmp(szValue, szMRU))
|
||||
{
|
||||
SHEOW_AddOWItem(This, szValue);
|
||||
NumItems++;
|
||||
}
|
||||
else
|
||||
{
|
||||
wcscpy(szMRUList, szValue);
|
||||
}
|
||||
}
|
||||
dwIndex++;
|
||||
}
|
||||
|
||||
if (szMRUList[0])
|
||||
{
|
||||
FIXME("handle MRUList\n");
|
||||
}
|
||||
return NumItems;
|
||||
}
|
||||
|
||||
|
||||
|
||||
UINT
|
||||
SHEOW_LoadItemFromHKCR(SHEOWImpl *This, WCHAR * szExt)
|
||||
{
|
||||
HKEY hKey;
|
||||
HKEY hSubKey;
|
||||
LONG result;
|
||||
UINT NumKeys = 0;
|
||||
WCHAR szBuffer[30];
|
||||
WCHAR szResult[70];
|
||||
DWORD dwSize;
|
||||
|
||||
static const WCHAR szCROW[] = { 'O','p','e','n','W','i','t','h','L','i','s','t', 0 };
|
||||
static const WCHAR szCROP[] = { 'O','p','e','n','W','i','t','h','P','r','o','g','I','D','s',0 };
|
||||
static const WCHAR szPT[] = { 'P','e','r','c','e','i','v','e','d','T','y','p','e', 0 };
|
||||
static const WCHAR szSys[] = { 'S','y','s','t','e','m','F','i','l','e','A','s','s','o','c','i','a','t','i','o','n','s','\\','%','s','\\','O','p','e','n','W','i','t','h','L','i','s','t', 0 };
|
||||
|
||||
|
||||
TRACE("SHEOW_LoadItemFromHKCR entered with This %p szExt %s\n",This, debugstr_w(szExt));
|
||||
|
||||
result = RegOpenKeyExW(HKEY_CLASSES_ROOT,
|
||||
szExt,
|
||||
0,
|
||||
KEY_READ | KEY_QUERY_VALUE,
|
||||
&hKey);
|
||||
if (result != ERROR_SUCCESS)
|
||||
return NumKeys;
|
||||
|
||||
result = RegOpenKeyExW(hKey,
|
||||
szCROW,
|
||||
0,
|
||||
KEY_READ | KEY_QUERY_VALUE,
|
||||
&hSubKey);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
NumKeys = SHEW_AddOpenWithItem(This, hSubKey);
|
||||
RegCloseKey(hSubKey);
|
||||
}
|
||||
|
||||
result = RegOpenKeyExW(hKey,
|
||||
szCROP,
|
||||
0,
|
||||
KEY_READ | KEY_QUERY_VALUE,
|
||||
&hSubKey);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
NumKeys += SHEW_AddOpenWithProgId(This, hSubKey);
|
||||
RegCloseKey(hSubKey);
|
||||
}
|
||||
|
||||
dwSize = sizeof(szBuffer);
|
||||
|
||||
result = RegGetValueW(hKey,
|
||||
NULL,
|
||||
szPT,
|
||||
RRF_RT_REG_SZ,
|
||||
NULL,
|
||||
szBuffer,
|
||||
&dwSize);
|
||||
szBuffer[29] = 0;
|
||||
|
||||
if (result != ERROR_SUCCESS)
|
||||
{
|
||||
RegCloseKey(hKey);
|
||||
return NumKeys;
|
||||
}
|
||||
|
||||
sprintfW(szResult, szSys, szExt);
|
||||
result = RegOpenKeyExW(hKey,
|
||||
szCROW,
|
||||
0,
|
||||
KEY_READ | KEY_QUERY_VALUE,
|
||||
&hSubKey);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
NumKeys += SHEW_AddOpenWithProgId(This, hSubKey);
|
||||
RegCloseKey(hSubKey);
|
||||
}
|
||||
|
||||
RegCloseKey(hKey);
|
||||
return NumKeys;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
UINT
|
||||
SHEOW_LoadItemFromHKCU(SHEOWImpl *This, WCHAR * szExt)
|
||||
{
|
||||
WCHAR szBuffer[MAX_PATH];
|
||||
HKEY hKey;
|
||||
UINT KeyCount = 0;
|
||||
LONG result;
|
||||
|
||||
static const WCHAR szOWPL[] = { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',
|
||||
'\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','F','i','l','e','E','x','t','s',
|
||||
'\\','%','s','\\','O','p','e','n','W','i','t','h','P','r','o','g','I','D','s',0 };
|
||||
|
||||
static const WCHAR szOpenWith[] = { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\','W','i','n','d','o','w','s',
|
||||
'\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\','E','x','p','l','o','r','e','r','\\','F','i','l','e','E','x','t','s',
|
||||
'\\','%','s','\\','O','p','e','n','W','i','t','h','L','i','s','t', 0 };
|
||||
|
||||
TRACE("SHEOW_LoadItemFromHKCU entered with This %p szExt %s\n",This, debugstr_w(szExt));
|
||||
|
||||
/* process HKCU settings */
|
||||
sprintfW(szBuffer, szOWPL, szExt);
|
||||
TRACE("szBuffer %s\n", debugstr_w(szBuffer));
|
||||
result = RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
szBuffer,
|
||||
0,
|
||||
KEY_READ | KEY_QUERY_VALUE,
|
||||
&hKey);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
KeyCount = SHEW_AddOpenWithProgId(This, hKey);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
sprintfW(szBuffer, szOpenWith, szExt);
|
||||
TRACE("szBuffer %s\n", debugstr_w(szBuffer));
|
||||
result = RegOpenKeyExW(HKEY_CURRENT_USER,
|
||||
szBuffer,
|
||||
0,
|
||||
KEY_READ | KEY_QUERY_VALUE,
|
||||
&hKey);
|
||||
|
||||
if (result == ERROR_SUCCESS)
|
||||
{
|
||||
KeyCount += SHEW_AddOpenWithItem(This, hKey);
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
return KeyCount;
|
||||
}
|
||||
|
||||
HRESULT
|
||||
SHEOW_LoadOpenWithItems(SHEOWImpl *This, IDataObject *pdtobj)
|
||||
{
|
||||
STGMEDIUM medium;
|
||||
FORMATETC fmt;
|
||||
HRESULT hr;
|
||||
LPIDA pida;
|
||||
LPCITEMIDLIST pidl_folder;
|
||||
LPCITEMIDLIST pidl_child;
|
||||
LPCITEMIDLIST pidl;
|
||||
WCHAR szPath[MAX_PATH];
|
||||
LPWSTR szPtr;
|
||||
|
||||
fmt.cfFormat = RegisterClipboardFormatA(CFSTR_SHELLIDLIST);
|
||||
fmt.ptd = NULL;
|
||||
fmt.dwAspect = DVASPECT_CONTENT;
|
||||
fmt.lindex = -1;
|
||||
fmt.tymed = TYMED_HGLOBAL;
|
||||
|
||||
hr = IDataObject_GetData(pdtobj, &fmt, &medium);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
ERR("IDataObject_GetData failed with 0x%x\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
/*assert(pida->cidl==1);*/
|
||||
pida = (LPIDA)GlobalLock(medium.u.hGlobal);
|
||||
|
||||
pidl_folder = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[0]);
|
||||
pidl_child = (LPCITEMIDLIST) ((LPBYTE)pida+pida->aoffset[1]);
|
||||
|
||||
pidl = ILCombine(pidl_folder, pidl_child);
|
||||
|
||||
GlobalUnlock(medium.u.hGlobal);
|
||||
GlobalFree(medium.u.hGlobal);
|
||||
|
||||
if (!pidl)
|
||||
{
|
||||
ERR("no mem\n");
|
||||
return E_OUTOFMEMORY;
|
||||
}
|
||||
if (!SHGetPathFromIDListW(pidl, szPath))
|
||||
{
|
||||
SHFree(pidl);
|
||||
ERR("SHGetPathFromIDListW failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
SHFree(pidl);
|
||||
TRACE("szPath %s\n", debugstr_w(szPath));
|
||||
|
||||
szPtr = wcschr(szPath, '.');
|
||||
if (szPtr)
|
||||
{
|
||||
SHEOW_LoadItemFromHKCU(This, szPtr);
|
||||
SHEOW_LoadItemFromHKCR(This, szPtr);
|
||||
}
|
||||
TRACE("count %u\n", This->count);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static HRESULT WINAPI
|
||||
SHEOW_ExtInit_Initialize( IShellExtInit* iface, LPCITEMIDLIST pidlFolder,
|
||||
IDataObject *pdtobj, HKEY hkeyProgID )
|
||||
|
@ -272,7 +648,7 @@ SHEOW_ExtInit_Initialize( IShellExtInit* iface, LPCITEMIDLIST pidlFolder,
|
|||
|
||||
TRACE("This %p\n", This);
|
||||
|
||||
return S_OK;
|
||||
return SHEOW_LoadOpenWithItems(This, pdtobj);
|
||||
}
|
||||
|
||||
static ULONG WINAPI SHEOW_ExtInit_AddRef(IShellExtInit *iface)
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#define COBJMACROS
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#define YDEBUG
|
||||
//#define YDEBUG
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
|
@ -45,6 +45,7 @@ BOOL fileMoving = FALSE;
|
|||
/**************************************************************************
|
||||
* IContextMenu Implementation
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ const IContextMenu2Vtbl *lpVtbl;
|
||||
LONG ref;
|
||||
|
@ -615,6 +616,24 @@ static void DoProperties(
|
|||
SHFree(pidlFQ);
|
||||
}
|
||||
}
|
||||
HRESULT
|
||||
DoShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
|
||||
{
|
||||
HRESULT hResult;
|
||||
UINT i;
|
||||
|
||||
TRACE("DoShellExtensions %p verb %x count %u\n",This, LOWORD(lpcmi->lpVerb), This->ecount);
|
||||
for(i = 0; i < This->ecount; i++)
|
||||
{
|
||||
IContextMenu * cmenu = This->ecmenu[i];
|
||||
|
||||
hResult = cmenu->lpVtbl->InvokeCommand(cmenu, lpcmi);
|
||||
if (SUCCEEDED(hResult))
|
||||
return hResult;
|
||||
}
|
||||
return NOERROR;
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************
|
||||
* ISvItemCm_fnInvokeCommand()
|
||||
|
@ -669,6 +688,10 @@ static HRESULT WINAPI ISvItemCm_fnInvokeCommand(
|
|||
DoProperties(iface, lpcmi->hwnd);
|
||||
break;
|
||||
default:
|
||||
if (LOWORD(lpcmi->lpVerb) >= This->iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSHELast)
|
||||
{
|
||||
return DoShellExtensions(iface, lpcmi);
|
||||
}
|
||||
FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue