[Wine-patches] [eterwine] oledlg: Implement OleUIAddVerbMenuA/W functions

Konstantin Kondratyuk kondratyuk на etersoft.ru
Ср Сен 14 14:17:32 MSD 2011


Переделка патчей Виталика для баги #6864.

-- 
Best regards,
Konstantin Kondratyuk.
----------- следующая часть -----------
Вложение в формате HTML было удалено...
URL: <http://lists.etersoft.ru/pipermail/wine-patches/attachments/20110914/b2ecf529/attachment-0001.html>
----------- следующая часть -----------
From 7bb879fb32cc2c673d9b45c45705d0fc38368c11 Mon Sep 17 00:00:00 2001
From: Vitaly Lipatov <lav на etersoft.ru>
Date: Wed, 14 Sep 2011 13:50:59 +0400
Subject: [PATCH 1/2] oledlg: Implement OleUIAddVerbMenuA/W functions

---
 dlls/oledlg/oledlg.rc     |    3 +
 dlls/oledlg/oledlg_main.c |  133 ++++++++++++++++++++++++++++++++++++++++-----
 dlls/oledlg/resource.h    |    3 +
 3 files changed, 125 insertions(+), 14 deletions(-)

diff --git a/dlls/oledlg/oledlg.rc b/dlls/oledlg/oledlg.rc
index 864fd06..b11e256 100644
--- a/dlls/oledlg/oledlg.rc
+++ b/dlls/oledlg/oledlg.rc
@@ -27,6 +27,9 @@ STRINGTABLE
   IDS_BROWSE            "Browse"
   IDS_NOTOLEMOD         "File does not appear to be a valid OLE module. Unable to register OLE control."
   IDS_NOTOLEMODCAPTION  "Add Control"
+  IDS_OBJECT            "Object: "
+  IDS_NOOBJECT          "No OLE object"
+  IDS_CONVERTING        "Converting..."
 }
 
 STRINGTABLE
diff --git a/dlls/oledlg/oledlg_main.c b/dlls/oledlg/oledlg_main.c
index 6033231..9e81db6 100644
--- a/dlls/oledlg/oledlg_main.c
+++ b/dlls/oledlg/oledlg_main.c
@@ -2,6 +2,7 @@
  *	OLEDLG library
  *
  *	Copyright 1998	Patrik Stridvall
+ *	Copyright 2008  Vitaly Lipatov (Etersoft)
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -25,9 +26,14 @@
 #include "winerror.h"
 #include "wingdi.h"
 #include "winuser.h"
+
+#define COBJMACROS
 #include "oledlg.h"
 #include "ole2.h"
+#include "oleidl.h"
 #include "oledlg_private.h"
+#include "wine/unicode.h"
+#include "resource.h"
 
 #include "wine/debug.h"
 
@@ -101,36 +107,135 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
 
 /***********************************************************************
  *           OleUIAddVerbMenuA (OLEDLG.1)
+ *  See OleUIAddVerbMenuW description
  */
 BOOL WINAPI OleUIAddVerbMenuA(
   LPOLEOBJECT lpOleObj, LPCSTR lpszShortType,
   HMENU hMenu, UINT uPos, UINT uIDVerbMin, UINT uIDVerbMax,
   BOOL bAddConvert, UINT idConvert, HMENU *lphMenu)
 {
-  FIXME("(%p, %s, %p, %d, %d, %d, %d, %d, %p): stub\n",
-    lpOleObj, debugstr_a(lpszShortType),
-    hMenu, uPos, uIDVerbMin, uIDVerbMax,
-    bAddConvert, idConvert, lphMenu
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    LPWSTR newstr = NULL;
+    BOOL ret = FALSE;
+
+    if (lpszShortType) {
+        INT len = MultiByteToWideChar( CP_ACP, 0, lpszShortType, -1, NULL, 0 );
+        newstr = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
+        if (newstr)
+            MultiByteToWideChar( CP_ACP, 0, lpszShortType, -1, newstr, len );
+    }
+    ret = OleUIAddVerbMenuW(
+                          lpOleObj, newstr,
+                          hMenu, uPos, uIDVerbMin, uIDVerbMax,
+                          bAddConvert, idConvert, lphMenu);
+    HeapFree( GetProcessHeap(), 0, newstr );
+    return ret;
 }
 
 /***********************************************************************
  *           OleUIAddVerbMenuW (OLEDLG.14)
+ *  Adds Object menu for the OLE object
+ *
+ * PARAMS
+ *  lpOleObj       [I ] pointer to the OLE object
+ *  lpszShortType  [I ] short name of the object or NULL if it is unknown
+ *  hMenu          [I ] menu handle
+ *  uPos           [I ] menu item position
+ *  uIDVerbMin,    [I ] min Verb ID
+ *  uIDVerbMax,    [I ] max Verb ID (0 if it's not used)
+ *  bAddConvert    [I ] TRUE if the item "Converting" is needed in the bottom of menu
+ *  idConvert      [I ] ID of the item "Converting"
+ *  lphMenu        [IO] pointer to the popup menu, if created
+ *
+ * NOTES
+ *  If lpOleObj is NULL, then a default disabled menu item is created.
+ *
+ * RETURNS
+ *  TRUE if at least one verb was added to the menu
+ *  FALSE if disabled default menu item was created
+ *
+ * TODO
+ *  Check if OLE object has no verbs
  */
 BOOL WINAPI OleUIAddVerbMenuW(
   LPOLEOBJECT lpOleObj, LPCWSTR lpszShortType,
   HMENU hMenu, UINT uPos, UINT uIDVerbMin, UINT uIDVerbMax,
   BOOL bAddConvert, UINT idConvert, HMENU *lphMenu)
 {
-  FIXME("(%p, %s, %p, %d, %d, %d, %d, %d, %p): stub\n",
-    lpOleObj, debugstr_w(lpszShortType),
-    hMenu, uPos, uIDVerbMin, uIDVerbMax,
-    bAddConvert, idConvert, lphMenu
-  );
-  SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
-  return FALSE;
+    HRESULT hr;
+    IEnumOLEVERB *pEnumVerbs;
+    HMENU popup = NULL;
+
+    FIXME("(%p, %s, %p, %d, %d, %d, %d, %d, %p): stub\n",
+        lpOleObj, debugstr_w(lpszShortType),
+        hMenu, uPos, uIDVerbMin, uIDVerbMax,
+        bAddConvert, idConvert, lphMenu );
+
+    if (!lpOleObj) {
+        WCHAR buf[MAX_PATH];
+        TRACE("Create disabled menu entry\n");
+        LoadStringW(OLEDLG_hInstance, IDS_NOOBJECT, buf, MAX_PATH);
+        DeleteMenu(hMenu, uPos, MF_BYPOSITION);
+        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING|MF_DISABLED, uIDVerbMin, buf);
+        return FALSE;
+    }
+
+    hr = IOleObject_EnumVerbs(lpOleObj, &pEnumVerbs);
+    if (hr == S_OK) {
+        int num; /* Number of menu entries */
+        OLEVERB oleVerb;
+        /* FIXME: there is OLE_S_USEREG, OLEOBJ_E_NOVERBS also */
+        for (num = 0; IEnumOLEVERB_Next(pEnumVerbs, 1, &oleVerb, NULL) == S_OK ; num++)
+            CoTaskMemFree(oleVerb.lpszVerbName);
+        IEnumOLEVERB_Reset(pEnumVerbs);
+
+        /* It destroys popup menu also */
+        if (num)
+            DeleteMenu(hMenu, uPos, MF_BYPOSITION);
+
+        /* If there is a few entries or converting entry needed */
+        if (num > 1 || bAddConvert) {
+            WCHAR menustr[MAX_PATH];
+            int len;
+            /* Prepare menu entry for popup menu */
+            LoadStringW(OLEDLG_hInstance, IDS_OBJECT, menustr, MAX_PATH);
+            len = strlenW(menustr);
+            if (lpszShortType)
+                strcpyW(menustr+len, lpszShortType);
+            else {
+                LPOLESTR lpszUserType;
+                IOleObject_GetUserType(lpOleObj, 0, &lpszUserType);
+                TRACE("Get UserType: %s\n", debugstr_w(lpszUserType));
+                strcpyW(menustr+len, lpszUserType);
+                CoTaskMemFree(lpszUserType);
+            }
+
+            popup = CreatePopupMenu();
+            InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT_PTR)popup, menustr);
+            uPos = -1;
+            hMenu = popup;
+        }
+
+        while (IEnumOLEVERB_Next(pEnumVerbs, 1, &oleVerb, NULL) == S_OK) {
+            TRACE("lVerb=%d VerbName=%s fuFlags=%x\n", oleVerb.lVerb,
+                  debugstr_w(oleVerb.lpszVerbName), oleVerb.fuFlags);
+            if (uIDVerbMax && (oleVerb.lVerb > uIDVerbMax-uIDVerbMin))
+                break;
+            InsertMenuW(hMenu, uPos, oleVerb.fuFlags|MF_BYPOSITION|MF_STRING, oleVerb.lVerb+uIDVerbMin, oleVerb.lpszVerbName);
+            /* FIXME: Is it really needed and documented? */
+            CoTaskMemFree(oleVerb.lpszVerbName);
+        }
+
+        /* Converting entry may be only in popup menu */
+        if (popup && bAddConvert) {
+            WCHAR buf[MAX_PATH];
+            InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
+            if (LoadStringW(OLEDLG_hInstance, IDS_CONVERTING, buf, MAX_PATH))
+                InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING, idConvert, buf);
+        }
+        IEnumOLEVERB_Release(pEnumVerbs);
+    }
+    *lphMenu = popup;
+    return TRUE;
 }
 
 /***********************************************************************
diff --git a/dlls/oledlg/resource.h b/dlls/oledlg/resource.h
index 13ca052..2d8f6d6 100644
--- a/dlls/oledlg/resource.h
+++ b/dlls/oledlg/resource.h
@@ -25,6 +25,9 @@
 #define IDS_BROWSE                      103
 #define IDS_NOTOLEMOD                   104
 #define IDS_NOTOLEMODCAPTION            105
+#define IDS_OBJECT                      2000
+#define IDS_NOOBJECT                    2001
+#define IDS_CONVERTING                  2002
 
 #define UIINSERTOBJECT                  129
 
-- 
1.7.6.1

----------- следующая часть -----------
From d8f9d9c2f135f77a0bf3de4ef7ec2dd97a033981 Mon Sep 17 00:00:00 2001
From: Vitaly Lipatov <lav на etersoft.ru>
Date: Wed, 14 Sep 2011 14:13:43 +0400
Subject: [PATCH 2/2] oledlg: Restructured OleUIAddVerbMenuW, rearrange buf
 using, cleanup code

---
 dlls/oledlg/oledlg_main.c |  135 ++++++++++++++++++++++++++------------------
 1 files changed, 80 insertions(+), 55 deletions(-)

diff --git a/dlls/oledlg/oledlg_main.c b/dlls/oledlg/oledlg_main.c
index 9e81db6..0901bb8 100644
--- a/dlls/oledlg/oledlg_main.c
+++ b/dlls/oledlg/oledlg_main.c
@@ -133,7 +133,7 @@ BOOL WINAPI OleUIAddVerbMenuA(
 
 /***********************************************************************
  *           OleUIAddVerbMenuW (OLEDLG.14)
- *  Adds Object menu for the OLE object
+ *  Add Object menu for the OLE object
  *
  * PARAMS
  *  lpOleObj       [I ] pointer to the OLE object
@@ -144,7 +144,7 @@ BOOL WINAPI OleUIAddVerbMenuA(
  *  uIDVerbMax,    [I ] max Verb ID (0 if it's not used)
  *  bAddConvert    [I ] TRUE if the item "Converting" is needed in the bottom of menu
  *  idConvert      [I ] ID of the item "Converting"
- *  lphMenu        [IO] pointer to the popup menu, if created
+ *  lphMenu        [IO] fill with pointer to the popup menu, if created
  *
  * NOTES
  *  If lpOleObj is NULL, then a default disabled menu item is created.
@@ -153,8 +153,6 @@ BOOL WINAPI OleUIAddVerbMenuA(
  *  TRUE if at least one verb was added to the menu
  *  FALSE if disabled default menu item was created
  *
- * TODO
- *  Check if OLE object has no verbs
  */
 BOOL WINAPI OleUIAddVerbMenuW(
   LPOLEOBJECT lpOleObj, LPCWSTR lpszShortType,
@@ -162,79 +160,106 @@ BOOL WINAPI OleUIAddVerbMenuW(
   BOOL bAddConvert, UINT idConvert, HMENU *lphMenu)
 {
     HRESULT hr;
+    WCHAR menustr[MAX_PATH];
     IEnumOLEVERB *pEnumVerbs;
     HMENU popup = NULL;
+    OLEVERB oleVerb;
+    int numVerbs = 0;
 
-    FIXME("(%p, %s, %p, %d, %d, %d, %d, %d, %p): stub\n",
+    TRACE("(%p, %s, %p, %d, %d, %d, %d, %d, %p)\n",
         lpOleObj, debugstr_w(lpszShortType),
         hMenu, uPos, uIDVerbMin, uIDVerbMax,
         bAddConvert, idConvert, lphMenu );
 
-    if (!lpOleObj) {
-        WCHAR buf[MAX_PATH];
-        TRACE("Create disabled menu entry\n");
-        LoadStringW(OLEDLG_hInstance, IDS_NOOBJECT, buf, MAX_PATH);
+    if (lpOleObj) {
+        hr = IOleObject_EnumVerbs(lpOleObj, &pEnumVerbs);
+/* FIXME: how to get clsid?
+        if (hr == OLE_S_USEREG)
+            hr = OleRegEnumVerbs(&lpOleObj->clsid, &pEnumVerbs);
+*/
+/* FIXME: set correct last error
+        if (hr != S_OK)
+            SetLastError(OLEOBJ_E_NOVERBS);
+*/
+    } else
+        hr = OLEOBJ_E_NOVERBS;
+
+    if (hr != S_OK) {
+        TRACE("Create disabled menu entry (oleObject is missed or without verbs)\n");
+        LoadStringW(OLEDLG_hInstance, IDS_NOOBJECT, menustr, MAX_PATH);
         DeleteMenu(hMenu, uPos, MF_BYPOSITION);
-        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING|MF_DISABLED, uIDVerbMin, buf);
+        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING|MF_DISABLED, uIDVerbMin, menustr);
         return FALSE;
     }
 
-    hr = IOleObject_EnumVerbs(lpOleObj, &pEnumVerbs);
-    if (hr == S_OK) {
-        int num; /* Number of menu entries */
-        OLEVERB oleVerb;
-        /* FIXME: there is OLE_S_USEREG, OLEOBJ_E_NOVERBS also */
-        for (num = 0; IEnumOLEVERB_Next(pEnumVerbs, 1, &oleVerb, NULL) == S_OK ; num++)
-            CoTaskMemFree(oleVerb.lpszVerbName);
-        IEnumOLEVERB_Reset(pEnumVerbs);
-
-        /* It destroys popup menu also */
-        if (num)
-            DeleteMenu(hMenu, uPos, MF_BYPOSITION);
-
-        /* If there is a few entries or converting entry needed */
-        if (num > 1 || bAddConvert) {
-            WCHAR menustr[MAX_PATH];
-            int len;
-            /* Prepare menu entry for popup menu */
-            LoadStringW(OLEDLG_hInstance, IDS_OBJECT, menustr, MAX_PATH);
-            len = strlenW(menustr);
-            if (lpszShortType)
-                strcpyW(menustr+len, lpszShortType);
-            else {
-                LPOLESTR lpszUserType;
-                IOleObject_GetUserType(lpOleObj, 0, &lpszUserType);
+    /* Count number of verbs */
+    for (; IEnumOLEVERB_Next(pEnumVerbs, 1, &oleVerb, NULL) == S_OK ; numVerbs++)
+        CoTaskMemFree(oleVerb.lpszVerbName);
+    IEnumOLEVERB_Reset(pEnumVerbs);
+
+    /* Destroy current menu entry or popup menu */
+    if (numVerbs)
+        DeleteMenu(hMenu, uPos, MF_BYPOSITION);
+
+    /* If there is a few entries or converting entry needed, create popup menu */
+    if (numVerbs > 1 || bAddConvert) {
+        int len;
+        /* Prepare menu entry for popup menu */
+        LoadStringW(OLEDLG_hInstance, IDS_OBJECT, menustr, MAX_PATH);
+        len = strlenW(menustr);
+        if (lpszShortType)
+            strcpyW(menustr+len, lpszShortType);
+        else {
+            LPOLESTR lpszUserType;
+            hr = IOleObject_GetUserType(lpOleObj, 0, &lpszUserType);
+/* FIXME
+            if (hr == OLE_S_USEREG)
+                hr = OleRegEnumVerbs(clsid, USERCLASSTYPE_SHORT, &lpszUserType);
+*/
+            if ( hr == S_OK) {
                 TRACE("Get UserType: %s\n", debugstr_w(lpszUserType));
                 strcpyW(menustr+len, lpszUserType);
                 CoTaskMemFree(lpszUserType);
             }
-
-            popup = CreatePopupMenu();
+        }
+        popup = CreatePopupMenu();
+        if (popup) {
             InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_POPUP|MF_STRING, (UINT_PTR)popup, menustr);
             uPos = -1;
             hMenu = popup;
         }
+    }
 
-        while (IEnumOLEVERB_Next(pEnumVerbs, 1, &oleVerb, NULL) == S_OK) {
-            TRACE("lVerb=%d VerbName=%s fuFlags=%x\n", oleVerb.lVerb,
-                  debugstr_w(oleVerb.lpszVerbName), oleVerb.fuFlags);
-            if (uIDVerbMax && (oleVerb.lVerb > uIDVerbMax-uIDVerbMin))
-                break;
-            InsertMenuW(hMenu, uPos, oleVerb.fuFlags|MF_BYPOSITION|MF_STRING, oleVerb.lVerb+uIDVerbMin, oleVerb.lpszVerbName);
-            /* FIXME: Is it really needed and documented? */
-            CoTaskMemFree(oleVerb.lpszVerbName);
-        }
+    /* Create menu items from available verbs */
+    while (IEnumOLEVERB_Next(pEnumVerbs, 1, &oleVerb, NULL) == S_OK) {
+        UINT itemID = oleVerb.lVerb+uIDVerbMin;
+        DWORD flags = oleVerb.fuFlags|MF_BYPOSITION|MF_STRING;
+        TRACE("lVerb=%d VerbName=%s fuFlags=%x\n", oleVerb.lVerb,
+            debugstr_w(oleVerb.lpszVerbName), oleVerb.fuFlags);
 
-        /* Converting entry may be only in popup menu */
-        if (popup && bAddConvert) {
-            WCHAR buf[MAX_PATH];
-            InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
-            if (LoadStringW(OLEDLG_hInstance, IDS_CONVERTING, buf, MAX_PATH))
-                InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING, idConvert, buf);
-        }
-        IEnumOLEVERB_Release(pEnumVerbs);
+        if (uIDVerbMax && (itemID > uIDVerbMax))
+            break;
+
+        /* Skip if should not be placed on the menu */
+        if (!(oleVerb.grfAttribs & OLEVERBATTRIB_ONCONTAINERMENU))
+            continue;
+        if (flags & (MF_BITMAP|MF_OWNERDRAW|MF_POPUP))
+            continue;
+
+        InsertMenuW(hMenu, uPos, flags, itemID, oleVerb.lpszVerbName);
+        CoTaskMemFree(oleVerb.lpszVerbName);
     }
-    *lphMenu = popup;
+    IEnumOLEVERB_Release(pEnumVerbs);
+
+    /* Converting entry may be only in popup menu */
+    if (popup && bAddConvert) {
+        InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_SEPARATOR, 0, NULL);
+        if (LoadStringW(OLEDLG_hInstance, IDS_CONVERTING, menustr, MAX_PATH))
+            InsertMenuW(hMenu, uPos, MF_BYPOSITION|MF_STRING, idConvert, menustr);
+    }
+
+    if (popup && lphMenu)
+        *lphMenu = popup;
     return TRUE;
 }
 
-- 
1.7.6.1



Подробная информация о списке рассылки Wine-patches