[ros-diffs] [janderwald] 30052: - implement loading & executing of static context menu extensions

janderwald at svn.reactos.org janderwald at svn.reactos.org
Thu Nov 1 21:54:46 CET 2007


Author: janderwald
Date: Thu Nov  1 23:54:46 2007
New Revision: 30052

URL: http://svn.reactos.org/svn/reactos?rev=30052&view=rev
Log:
- implement loading & executing of static context menu extensions

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_cmenu.c?rev=30052&r1=30051&r2=30052&view=diff
==============================================================================
--- trunk/reactos/dll/win32/shell32/shv_item_cmenu.c (original)
+++ trunk/reactos/dll/win32/shell32/shv_item_cmenu.c Thu Nov  1 23:54:46 2007
@@ -43,6 +43,13 @@
 /* ugly hack for cut&paste files */
 BOOL fileMoving = FALSE;
 
+typedef struct _StaticShellEntry_
+{
+   LPWSTR szVerb;
+   LPWSTR szCmd;
+   struct _StaticShellEntry_ * Next;
+}StaticShellEntry, *PStaticShellEntry;
+
 /**************************************************************************
 *  IContextMenu Implementation
 */
@@ -58,6 +65,9 @@
     IContextMenu ** ecmenu;
     UINT           esize;
     UINT           ecount;
+    PStaticShellEntry head;
+    UINT           iIdSCMFirst;
+    UINT           iIdSCMLast;
     UINT           iIdSHEFirst;
     UINT           iIdSHELast;
     SFGAOF         rfg;
@@ -66,7 +76,7 @@
 UINT
 SH_EnumerateDynamicContextHandlerForKey(LPWSTR szFileClass, ItemCmImpl *This, IDataObject * pDataObj, LPITEMIDLIST pidlFolder);
 WCHAR *build_paths_list(LPCWSTR wszBasePath, int cidl, LPCITEMIDLIST *pidls);
-
+WCHAR *strdupW(LPWSTR str);
 static const IContextMenu2Vtbl cmvt;
 
 /**************************************************************************
@@ -353,6 +363,179 @@
     TRACE("SH_LoadContextMenuHandlers first %x last %x\n", This->iIdSHEFirst, This->iIdSHELast);
 }
 
+void
+SH_AddStaticEntry(ItemCmImpl * This, HKEY hKey, WCHAR *szVerb)
+{
+  WCHAR szBuffer[50];
+  WCHAR szCmd[100];
+  DWORD dwCmd, dwBuffer;
+  LONG result;
+  HKEY hSubKey;
+  PStaticShellEntry curEntry;
+  PStaticShellEntry lastEntry = NULL;
+
+  wcscpy(szBuffer, szVerb);
+  wcscat(szBuffer, L"\\command");
+
+  TRACE("szBuffer %s\n", debugstr_w(szBuffer));
+
+  result = RegOpenKeyExW(hKey, szBuffer, 0, KEY_READ, &hSubKey);
+  if (result != ERROR_SUCCESS)
+  {
+      TRACE("RegOpenKeyEx failed with 0x%x\n", result);
+      return;
+  }
+  dwCmd = sizeof(szCmd);
+  dwBuffer = 50;
+  result = RegEnumValueW(hSubKey, 0, szBuffer, &dwBuffer, 0, NULL, (LPBYTE)szCmd, &dwCmd);
+  RegCloseKey(hSubKey);
+  if (result != ERROR_SUCCESS)
+  {
+      TRACE("RegGetValueW failed with 0x%x\n", result);
+      return;
+  }
+  TRACE("SH_AddStaticEntry szBuffer %s szCmd %s\n", debugstr_w(szBuffer), debugstr_w(szCmd));
+
+  curEntry = This->head;
+
+  while(curEntry)
+  {
+    if (!wcsicmp(curEntry->szVerb, szVerb))
+    {
+       /* entry already exists */
+       return;
+    }
+    lastEntry = curEntry;
+    curEntry->Next = curEntry;
+  }
+  
+  curEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(StaticShellEntry));
+  if (curEntry)
+  {
+      curEntry->Next = NULL;
+      curEntry->szCmd = StrDupW(szCmd);
+      curEntry->szVerb = StrDupW(szVerb);
+  }
+
+  if (lastEntry)
+  {
+    lastEntry->Next = curEntry;
+  }
+  else
+  {
+    This->head = curEntry;
+  }
+}
+
+void
+SH_AddStaticEntryForKey(ItemCmImpl * This, HKEY hKey)
+{
+    LONG result;
+    DWORD dwIndex;
+    WCHAR szName[40];
+    DWORD dwName;
+
+    TRACE("SH_AddStaticEntryForKey entered\n");
+
+    dwIndex = 0;
+    do
+    {
+        szName[0] = 0;
+        dwName = sizeof(szName) / sizeof(WCHAR);
+        result = RegEnumKeyExW(hKey, dwIndex, szName, &dwName, NULL, NULL, NULL, NULL);
+        szName[39] = 0;   
+        if (result == ERROR_SUCCESS)
+        {
+            TRACE("szVerb %s\n", debugstr_w(szName));
+            SH_AddStaticEntry(This, hKey, szName);
+        }
+        dwIndex++;
+    }while(result == ERROR_SUCCESS);
+}
+
+void
+SH_AddStaticEntryForFileClass(ItemCmImpl * This, WCHAR * szExt)
+{
+    WCHAR szBuffer[100];
+    HKEY hKey;
+    LONG result;
+    DWORD dwBuffer;
+
+    TRACE("SH_AddStaticEntryForFileClass entered with %s\n", debugstr_w(szExt));
+
+    wcscpy(szBuffer, szExt);
+    wcscat(szBuffer, L"\\shell");
+    result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
+    if (result == ERROR_SUCCESS)
+    {
+        SH_AddStaticEntryForKey(This, hKey);
+        RegCloseKey(hKey);
+    }
+
+    dwBuffer = sizeof(szBuffer);
+    result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, NULL, RRF_RT_REG_SZ, NULL, (LPBYTE)szBuffer, &dwBuffer);
+    if (result == ERROR_SUCCESS)
+    {
+        wcscat(szBuffer, L"\\shell");
+        TRACE("szBuffer %s\n", debugstr_w(szBuffer));
+
+        result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
+        if (result == ERROR_SUCCESS)
+        {
+           SH_AddStaticEntryForKey(This, hKey);
+           RegCloseKey(hKey);
+        }
+    }
+
+    strcpyW(szBuffer, "SystemFileAssociations\\");
+    dwBuffer = sizeof(szBuffer) - strlenW(szBuffer) * sizeof(WCHAR);
+    result = RegGetValueW(HKEY_CLASSES_ROOT, szExt, L"PerceivedType", RRF_RT_REG_SZ, NULL, (LPBYTE)&szBuffer[23], &dwBuffer);
+    if (result == ERROR_SUCCESS)
+    {
+        wcscat(szBuffer, L"\\shell");
+        TRACE("szBuffer %s\n", debugstr_w(szBuffer));
+
+        result = RegOpenKeyExW(HKEY_CLASSES_ROOT, szBuffer, 0, KEY_READ | KEY_QUERY_VALUE, &hKey);
+        if (result == ERROR_SUCCESS)
+        {
+           SH_AddStaticEntryForKey(This, hKey);
+           RegCloseKey(hKey);
+        }
+    }
+    RegCloseKey(hKey);
+}
+UINT
+SH_AddStaticEntryToMenu(HMENU hMenu, UINT indexMenu, ItemCmImpl * This)
+{
+    MENUITEMINFOW mii;
+    PStaticShellEntry curEntry;
+
+    mii.cbSize = sizeof(mii);
+    mii.fMask = MIIM_ID | MIIM_TYPE | MIIM_STATE | MIIM_DATA;
+    mii.fType = MFT_STRING;
+    mii.fState = MFS_ENABLED | MFS_DEFAULT;
+    mii.wID = 0x4000;
+    This->iIdSCMFirst = mii.wID;
+
+    curEntry = This->head;
+
+    while(curEntry)
+    {
+       /* FIXME
+        * load localized verbs if its an open edit find print printto openas properties verb
+        */
+
+       mii.dwTypeData = curEntry->szVerb;
+       mii.cch = strlenW(mii.dwTypeData);
+       InsertMenuItemW(hMenu, indexMenu++, TRUE, &mii);
+       mii.fState = MFS_ENABLED;
+       mii.wID++;
+       curEntry = curEntry->Next;
+    }
+    This->iIdSCMLast = mii.wID - 1;
+    return indexMenu;
+}
+
 const char * GetLocalizedString(HMENU hMenu, UINT wID, const char * sDefault, char * sResult)
 {
    MENUITEMINFOA mii;
@@ -395,6 +578,7 @@
     USHORT lastindex = 0;
     HMENU hLocalMenu;
     char sBuffer[100];
+    WCHAR szExt[10];
 
     static const char sExplore[] = { '&','E','x','p','l','o','r','e',0 };
     static const char sCopy[] = { '&','C','o','p','y',0 };
@@ -408,6 +592,22 @@
 	TRACE("(%p)->(hmenu=%p indexmenu=%x cmdfirst=%x cmdlast=%x flags=%x )\n",This, hmenu, indexMenu, idCmdFirst, idCmdLast, uFlags);
 
     hLocalMenu = LoadMenuW(shell32_hInstance, szSHVFile);
+
+    if (_ILGetExtension(This->apidl[0], &sBuffer[1], sizeof(sBuffer)-1))
+    {
+        sBuffer[0] = '.';
+        MultiByteToWideChar( CP_ACP, 0, sBuffer, -1, (LPWSTR)szExt, 10);
+        SH_AddStaticEntryForFileClass(This, szExt);
+        indexMenu = SH_AddStaticEntryToMenu(hmenu, indexMenu, This);
+    }
+
+    pDataObj = IDataObject_Constructor(NULL, This->pidl, This->apidl, This->cidl);
+    if (pDataObj)
+    {
+        SH_LoadContextMenuHandlers(This, pDataObj, hmenu, indexMenu);
+        IDataObject_Release(pDataObj);
+    }
+
 
 	if (idCmdFirst != 0)
 	  FIXME("We should use idCmdFirst=%d and idCmdLast=%d for command ids\n", idCmdFirst, idCmdLast);
@@ -460,12 +660,7 @@
 
       lastindex = FCIDM_SHVIEWLAST;
 	}
-    pDataObj = IDataObject_Constructor(NULL, This->pidl, This->apidl, This->cidl);
-    if (pDataObj)
-    {
-        SH_LoadContextMenuHandlers(This, pDataObj, hmenu, indexMenu);
-        IDataObject_Release(pDataObj);
-    }
+
     if (hLocalMenu)
     {
         DestroyMenu(hLocalMenu);
@@ -706,7 +901,84 @@
     }
 }
 HRESULT
-DoShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
+DoStaticShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
+{
+  UINT i;
+  WCHAR szTarget[MAX_PATH];
+  WCHAR szTemp[MAX_PATH];
+  WCHAR *ptr, *szCmd;
+  PStaticShellEntry curEntry;
+  LPITEMIDLIST pidl;
+  STARTUPINFOW sInfo;
+  PROCESS_INFORMATION pi;
+
+  static const WCHAR szP1[] = { '%', '1', 0 };
+
+  TRACE("DoStaticShellExtensions entered with lpVerb %x first %x last %x\n", LOWORD(lpcmi->lpVerb), This->iIdSCMFirst, This->iIdSCMLast);
+
+  i = This->iIdSCMFirst;
+  curEntry = This->head;
+
+  while(curEntry)
+  {
+    if (i == LOWORD(lpcmi->lpVerb))
+        break;
+
+    i++;
+    curEntry = curEntry->Next;
+  }
+  
+  if (!curEntry)
+  {
+      ERR("unexpected\n");
+      return E_UNEXPECTED;
+  }
+
+  ExpandEnvironmentStringsW(curEntry->szCmd, szTarget, MAX_PATH);
+  
+  ptr = wcsstr(szTarget, szP1);
+  if (ptr)
+  {
+     ptr[1] = 's';
+     pidl = ILCombine(This->pidl, This->apidl[0]);
+     if (pidl)
+     {
+        WCHAR szPath[MAX_PATH];
+        if (SHGetPathFromIDListW(pidl, szPath))
+        {
+            sprintfW(szTemp, szTarget, szPath);
+        }
+        SHFree(pidl);
+     }
+     else
+     {
+         ptr[0] = 0;
+     }
+     ptr = szTemp;
+   }
+   else
+   {
+      ptr = szTarget;
+   }
+
+   ZeroMemory(&sInfo, sizeof(sInfo));
+   sInfo.cb = sizeof(sizeof(sInfo));
+   szCmd = wcsdup(ptr);
+
+   if (!szCmd)
+       return E_OUTOFMEMORY;
+
+   if (CreateProcessW(NULL, szCmd, NULL, NULL,FALSE,0,NULL,NULL,&sInfo, &pi))
+   {
+      CloseHandle( pi.hProcess );
+      CloseHandle( pi.hThread );
+   }
+   free(szCmd);
+   return S_OK;
+}
+
+HRESULT
+DoDynamicShellExtensions(ItemCmImpl *This, LPCMINVOKECOMMANDINFO lpcmi)
 {
     HRESULT hResult = NOERROR;
     UINT i;
@@ -739,7 +1011,7 @@
     if (lpcmi->cbSize != sizeof(CMINVOKECOMMANDINFO))
         FIXME("Is an EX structure\n");
 
-    TRACE("(%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
+    TRACE("ISvItemCm_fnInvokeCommand (%p)->(invcom=%p verb=%p wnd=%p)\n",This,lpcmi,lpcmi->lpVerb, lpcmi->hwnd);
 
     if( HIWORD(lpcmi->lpVerb)==0 && LOWORD(lpcmi->lpVerb) > FCIDM_SHVIEWLAST)
     {
@@ -782,8 +1054,14 @@
         default:
             if (LOWORD(lpcmi->lpVerb) >= This->iIdSHEFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSHELast)
             {
-                return DoShellExtensions(This, lpcmi);
+                return DoDynamicShellExtensions(This, lpcmi);
             }
+
+            if (LOWORD(lpcmi->lpVerb) >= This->iIdSCMFirst && LOWORD(lpcmi->lpVerb) <= This->iIdSCMLast)
+            {
+                return DoStaticShellExtensions(This, lpcmi);
+            }
+
             FIXME("Unhandled Verb %xl\n",LOWORD(lpcmi->lpVerb));
         }
     }




More information about the Ros-diffs mailing list