Author: janderwald
Date: Tue Oct 30 21:35:02 2007
New Revision: 29981
URL:
http://svn.reactos.org/svn/reactos?rev=29981&view=rev
Log:
- populate Open With with found entries
- see
http://windowsxp.mvps.org/OpenWith.htm
- silence debug messages
- invoke shell extension's InvokeCommand on a event
Modified:
trunk/reactos/dll/win32/shell32/she_ocmenu.c
trunk/reactos/dll/win32/shell32/shv_item_cmenu.c
Modified: trunk/reactos/dll/win32/shell32/she_ocmenu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/she_ocme…
==============================================================================
--- trunk/reactos/dll/win32/shell32/she_ocmenu.c (original)
+++ trunk/reactos/dll/win32/shell32/she_ocmenu.c Tue Oct 30 21:35:02 2007
@@ -23,7 +23,7 @@
#define COBJMACROS
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
-#define YDEBUG
+//#define YDEBUG
#include "winerror.h"
#include "wine/debug.h"
@@ -46,8 +46,10 @@
const IShellExtInitVtbl *lpvtblShellExtInit;
LONG wId;
volatile LONG ref;
+ WCHAR ** szArray;
+ UINT size;
+ UINT count;
} SHEOWImpl;
-
static const IShellExtInitVtbl eivt;
static const IContextMenu2Vtbl cmvt;
@@ -145,7 +147,8 @@
{
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 @@
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 @@
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 @@
MENUITEMINFOW mii;
USHORT items = 0;
WCHAR szBuffer[100];
+ BOOL bDefault = FALSE;
HMENU hSubMenu = NULL;
SHEOWImpl *This = impl_from_IContextMenu(iface);
@@ -190,14 +213,26 @@
return E_FAIL;
}
-
- hSubMenu = CreatePopupMenu();
- if (hSubMenu == NULL)
- {
- ERR("failed to create submenu");
- return E_FAIL;
- }
- items = AddItems(This, hSubMenu, idCmdFirst);
+ if (This->count)
+ {
+ 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);
+ }
+ }
ZeroMemory(&mii, sizeof(mii));
mii.cbSize = sizeof(mii);
@@ -209,7 +244,14 @@
}
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 @@
SHEOWCm_fnInvokeCommand( IContextMenu2* iface, LPCMINVOKECOMMANDINFO lpici )
{
SHEOWImpl *This = impl_from_IContextMenu(iface);
-
- TRACE("This %p\n", This);
-
- return E_FAIL;
+ TRACE("This %p wId %x count %u verb %x\n", This, This->wId,
This->count, LOWORD(lpici->lpVerb));
+
+ 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 @@
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 @@
TRACE("This %p\n", This);
- return S_OK;
+ return SHEOW_LoadOpenWithItems(This, pdtobj);
}
static ULONG WINAPI SHEOW_ExtInit_AddRef(IShellExtInit *iface)
Modified: trunk/reactos/dll/win32/shell32/shv_item_cmenu.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/shell32/shv_item…
==============================================================================
--- trunk/reactos/dll/win32/shell32/shv_item_cmenu.c (original)
+++ trunk/reactos/dll/win32/shell32/shv_item_cmenu.c Tue Oct 30 21:35:02 2007
@@ -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 @@
/**************************************************************************
* IContextMenu Implementation
*/
+
typedef struct
{ const IContextMenu2Vtbl *lpVtbl;
LONG ref;
@@ -615,6 +616,24 @@
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 @@
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));
}
}