Author: janderwald
Date: Fri Nov 2 05:49:14 2007
New Revision: 30061
URL:
http://svn.reactos.org/svn/reactos?rev=30061&view=rev
Log:
- refactor dynamic context menu loading
- dynamic shell extensions should now work
- WinRar extension is now working except for the email handling thing
Modified:
trunk/reactos/dll/win32/shell32/shv_item_cmenu.c
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 Fri Nov 2 05:49:14 2007
@@ -50,6 +50,14 @@
struct _StaticShellEntry_ * Next;
}StaticShellEntry, *PStaticShellEntry;
+typedef struct _DynamicShellEntry_
+{
+ UINT iIdCmdFirst;
+ UINT NumIds;
+ IContextMenu * CMenu;
+ struct _DynamicShellEntry_ * Next;
+}DynamicShellEntry, *PDynamicShellEntry;
+
/**************************************************************************
* IContextMenu Implementation
*/
@@ -62,9 +70,7 @@
LPITEMIDLIST *apidl; /* array of child pidls */
UINT cidl;
BOOL bAllValues;
- IContextMenu ** ecmenu;
- UINT esize;
- UINT ecount;
+ PDynamicShellEntry dhead;
PStaticShellEntry head;
UINT iIdSCMFirst;
UINT iIdSCMLast;
@@ -74,7 +80,7 @@
} ItemCmImpl;
UINT
-SH_EnumerateDynamicContextHandlerForKey(LPWSTR szFileClass, ItemCmImpl *This, IDataObject
* pDataObj, LPITEMIDLIST pidlFolder);
+SH_EnumerateDynamicContextHandlerForKey(LPWSTR szFileClass, ItemCmImpl *This, IDataObject
* pDataObj);
WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls);
WCHAR *strdupW(LPWSTR str);
static const IContextMenu2Vtbl cmvt;
@@ -190,7 +196,7 @@
ULONG refCount = InterlockedDecrement(&This->ref);
PStaticShellEntry curEntry;
PStaticShellEntry nextEntry;
- UINT i;
+
TRACE("(%p)->(count=%i)\n", This, refCount + 1);
@@ -207,11 +213,6 @@
free(curEntry);
curEntry = nextEntry;
}
- for(i = 0; i < This->ecount; i++)
- {
- IContextMenu_Release(This->ecmenu[i]);
- }
- HeapFree(GetProcessHeap(), 0, This->ecmenu);
if(This->pSFParent)
IShellFolder_Release(This->pSFParent);
@@ -261,71 +262,41 @@
DoCustomItemAction(ItemCmImpl *This, LPARAM lParam, UINT uMsg)
{
IContextMenu2 * cmenu;
- IContextMenu * menu;
MEASUREITEMSTRUCT * lpmis = (MEASUREITEMSTRUCT *)lParam;
- DRAWITEMSTRUCT * drawItem = (DRAWITEMSTRUCT *)lParam;
HRESULT hResult;
-
+ UINT i;
+ PDynamicShellEntry curEntry;
TRACE("DoCustomItemAction entered with uMsg %x lParam %p\n", uMsg, lParam);
- if (uMsg == WM_MEASUREITEM)
+ curEntry = This->dhead;
+ i = This->iIdSHEFirst;
+
+
+ while(curEntry)
{
- menu = This->ecmenu[lpmis->itemID - This->iIdSHEFirst];
+ if (i == lpmis->itemID)
+ break;
+
+ i++;
+ curEntry = curEntry->Next;
}
- else if (uMsg == WM_DRAWITEM)
- {
- menu = This->ecmenu[drawItem->itemID - This->iIdSHEFirst];
- }
- else
- {
- ERR("unexpected message\n");
- return E_FAIL;
- }
-
- if (!menu)
- {
- ERR("item is not valid\n");
- return E_FAIL;
- }
-
- hResult = menu->lpVtbl->QueryInterface(menu, &IID_IContextMenu2,
(void**)&cmenu);
+
+ if (!curEntry)
+ return E_FAIL;
+
+ hResult = IContextMenu_QueryInterface(curEntry->CMenu, &IID_IContextMenu2,
(void**)&cmenu);
if (hResult != S_OK)
{
ERR("failed to get IID_IContextMenu2 interface\n");
return hResult;
}
- hResult = cmenu->lpVtbl->HandleMenuMsg(cmenu, uMsg, (WPARAM)0, lParam);
+ hResult = IContextMenu2_HandleMenuMsg(cmenu, uMsg, (WPARAM)0, lParam);
+ IContextMenu2_Release(cmenu);
+
TRACE("returning hResult %x\n", hResult);
return hResult;
-}
-
-BOOL
-SH_EnlargeContextMenuArray(ItemCmImpl *This, UINT newsize)
-{
- BOOL ret = FALSE;
-
- if (This->ecmenu == NULL)
- {
- This->ecmenu = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,
sizeof(IContextMenu*) *10);
- if(This->ecmenu)
- ret = TRUE;
- This->ecount = 0;
- This->esize = 10;
- }
- else
- {
- IContextMenu ** newcmenu =
HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IContextMenu*)*newsize);
- if (newcmenu)
- {
- memcpy(newcmenu, This->ecmenu, This->ecount * sizeof(IContextMenu*));
- HeapFree(GetProcessHeap(), 0, This->ecmenu);
- This->ecmenu = newcmenu;
- ret = TRUE;
- }
- }
- return ret;
}
UINT
@@ -335,13 +306,13 @@
WCHAR buffer[111];
char ebuf[10];
HRESULT hr;
- IContextMenu * cmenu;
HRESULT hResult;
- UINT idCmdFirst = 0x5000;
+ UINT idCmdFirst = 0x6000;
UINT idCmdLast = 0xFFF0;
+ PDynamicShellEntry curEntry;
static WCHAR szAny[] = { '*',0};
- SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj, This->pidl);
+ SH_EnumerateDynamicContextHandlerForKey(szAny, This, pDataObj);
for (i = 0; i < This->cidl; i++)
{
@@ -355,7 +326,7 @@
if (hr == S_OK)
{
memcpy(&buffer[6], pwszCLSID, 38 * sizeof(WCHAR));
- SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj,
This->pidl);
+ SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj);
}
}
@@ -364,22 +335,33 @@
ebuf[0] = L'.';
buffer[0] = L'\0';
if (MultiByteToWideChar(CP_ACP, 0, ebuf, -1, buffer, 111))
- SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj,
This->pidl);
+ SH_EnumerateDynamicContextHandlerForKey(buffer, This, pDataObj);
}
}
-
- TRACE("SH_LoadContextMenuHandlers num extensions %u\n", This->ecount);
- This->iIdSHEFirst = idCmdFirst;
- for (i = 0; i < This->ecount; i++)
- {
- cmenu = This->ecmenu[i];
- hResult = cmenu->lpVtbl->QueryContextMenu(cmenu, hMenu, indexMenu,
idCmdFirst, idCmdLast, CMF_NORMAL);
- if (SUCCEEDED(hResult))
- {
- idCmdFirst += (hResult & 0xFFFF);
- indexMenu +=(hResult & 0xFFFF);
- }
- }
+ TRACE("-- done loading\n");
+ if (!This->dhead)
+ {
+ This->iIdSHEFirst = 0;
+ This->iIdSHELast = 0;
+ return indexMenu;
+ }
+
+ curEntry = This->dhead;
+ do
+ {
+
+ hResult = IContextMenu_QueryContextMenu(curEntry->CMenu, hMenu, indexMenu,
idCmdFirst, idCmdLast, CMF_NORMAL);
+ if (SUCCEEDED(hResult))
+ {
+ curEntry->iIdCmdFirst = idCmdFirst;
+ curEntry->NumIds = LOWORD(hResult);
+ indexMenu += curEntry->NumIds;
+ idCmdFirst += curEntry->NumIds + 0x10;
+ }
+ TRACE("curEntry %p hresult %x contextmenu %p cmdfirst %x num ids %x\n",
curEntry, hResult, curEntry->CMenu, curEntry->iIdCmdFirst, curEntry->NumIds);
+ curEntry = curEntry->Next;
+ }while(curEntry);
+
This->iIdSHELast = idCmdFirst;
TRACE("SH_LoadContextMenuHandlers first %x last %x\n",
This->iIdSHEFirst, This->iIdSHELast);
return indexMenu;
@@ -1000,20 +982,28 @@
DoDynamicShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
{
HRESULT hResult = NOERROR;
- UINT i;
-
- TRACE("DoDynamicShellExtensions %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))
- {
+ PDynamicShellEntry curEntry;
+ UINT id;
+
+ curEntry = This->dhead;
+ id = LOWORD(lpcmi->lpVerb);
+
+ while(curEntry)
+ {
+ if (curEntry->iIdCmdFirst <= id && curEntry->iIdCmdFirst +
curEntry->NumIds >= id)
break;
- }
- }
- TRACE("DoShellExtensions result %x\n", hResult);
+
+ curEntry = curEntry->Next;
+ }
+
+ if (!curEntry)
+ return E_FAIL;
+
+ lpcmi->lpVerb -= curEntry->iIdCmdFirst;
+
+ hResult = IContextMenu_InvokeCommand(curEntry->CMenu, lpcmi);
+
+ TRACE("DoDynamicShellExtensions hResult %x verb %x first %x\n", hResult,
lpcmi->lpVerb, curEntry->iIdCmdFirst);
return hResult;
}
@@ -1190,12 +1180,12 @@
};
HRESULT
-SH_LoadDynamicContextMenuHandler(HKEY hKey, const CLSID * szClass, IContextMenu** ppv,
IDataObject * pDataObj, LPITEMIDLIST pidlFolder)
+SH_LoadDynamicContextMenuHandler(HKEY hKey, const CLSID * szClass, ItemCmImpl *This,
IDataObject * pDataObj)
{
HRESULT hr;
IContextMenu * cmobj;
IShellExtInit *shext;
-
+ PDynamicShellEntry curEntry;
TRACE("SH_LoadDynamicContextMenuHandler entered with
%s\n",wine_dbgstr_guid(szClass));
hr = SHCoCreateInstance(NULL, szClass, NULL, &IID_IContextMenu,
(void**)&cmobj);
@@ -1204,7 +1194,6 @@
TRACE("SHCoCreateInstance failed %x\n", GetLastError());
return hr;
}
-
hr = cmobj->lpVtbl->QueryInterface(cmobj, &IID_IShellExtInit,
(void**)&shext);
if (hr != S_OK)
{
@@ -1215,21 +1204,43 @@
hr = shext->lpVtbl->Initialize(shext, NULL, pDataObj, hKey);
if (hr != S_OK)
{
- TRACE("Failed to initialize shell extension\n");
+ TRACE("Failed to initialize shell extension error %x\n", hr);
shext->lpVtbl->Release(shext);
cmobj->lpVtbl->Release(cmobj);
+ return hr;
+ }
+ curEntry = malloc(sizeof(DynamicShellEntry));
+ if(!curEntry)
+ {
+ return E_OUTOFMEMORY;
+ }
+
+ curEntry->iIdCmdFirst = 0;
+ curEntry->Next = NULL;
+ curEntry->NumIds = 0;
+ curEntry->CMenu = cmobj;
+
+ if (This->dhead)
+ {
+ PDynamicShellEntry pEntry = This->dhead;
+
+ while(pEntry->Next)
+ {
+ pEntry = pEntry->Next;
+ }
+
+ pEntry->Next = curEntry;
}
else
{
- shext->lpVtbl->Release(shext);
- *ppv = cmobj;
+ This->dhead = curEntry;
}
return hr;
}
UINT
-SH_EnumerateDynamicContextHandlerForKey(const LPWSTR szFileClass, ItemCmImpl *This,
IDataObject * pDataObj, LPITEMIDLIST pidlFolder)
+SH_EnumerateDynamicContextHandlerForKey(const LPWSTR szFileClass, ItemCmImpl *This,
IDataObject * pDataObj)
{
HKEY hKey;
WCHAR szKey[MAX_PATH] = {0};
@@ -1237,7 +1248,6 @@
DWORD dwIndex, dwName;
LONG res;
HRESULT hResult;
- IContextMenu * cmobj;
UINT index;
CLSID clsid;
static const WCHAR szShellEx[] = {
'\\','s','h','e','l','l','e','x','\\','C','o','n','t','e','x','t','M','e','n','u','H','a','n','d','l','e','r','s',0
};
@@ -1273,18 +1283,7 @@
TRACE("hResult %x szKey %s name %s\n",hResult, debugstr_w(szKey),
debugstr_w(szName));
if (hResult == S_OK)
{
- hResult = SH_LoadDynamicContextMenuHandler(hKey, &clsid, &cmobj,
pDataObj, pidlFolder);
- }
- if (hResult == S_OK)
- {
- if (This->ecount + 1 > This->esize)
- {
- if (!SH_EnlargeContextMenuArray(This, max(This->esize * 2, 10)))
- break;
- }
-
- This->ecmenu[This->ecount] = cmobj;
- This->ecount++;
+ SH_LoadDynamicContextMenuHandler(hKey, &clsid, This, pDataObj);
}
}
dwIndex++;