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_ocmen... ============================================================================== --- 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)); } }