Zebediah Figura : shell32: Add a parser for DDE commands.

Alexandre Julliard julliard at winehq.org
Thu Nov 30 14:19:34 CST 2017


Module: wine
Branch: master
Commit: 6778023999912e0b3f601188bcca9a7971d8193b
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6778023999912e0b3f601188bcca9a7971d8193b

Author: Zebediah Figura <z.figura12 at gmail.com>
Date:   Wed Nov 29 17:00:45 2017 -0600

shell32: Add a parser for DDE commands.

Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/shell32/dde.c          | 115 +++++++++++++++++++++++++++++++++++++++++---
 dlls/shell32/shell32_main.h |  13 +++++
 2 files changed, 121 insertions(+), 7 deletions(-)

diff --git a/dlls/shell32/dde.c b/dlls/shell32/dde.c
index c44f05d..ae1143b 100644
--- a/dlls/shell32/dde.c
+++ b/dlls/shell32/dde.c
@@ -26,7 +26,10 @@
 #include "ddeml.h"
 #include "shellapi.h"
 
+#include "shell32_main.h"
+
 #include "wine/debug.h"
+#include "wine/unicode.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(shell);
 
@@ -94,21 +97,119 @@ static inline HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic,
     return NULL;
 }
 
-static inline DWORD Dde_OnExecute(HCONV hconv, HSZ hszTopic, HDDEDATA hdata)
+static DWORD PROGMAN_OnExecute(WCHAR *command, int argc, WCHAR **argv)
 {
-    WCHAR * pszCommand;
+    FIXME("unhandled command %s\n", debugstr_w(command));
+    return DDE_FNOTPROCESSED;
+}
+
+static DWORD parse_dde_command(HSZ hszTopic, WCHAR *command)
+{
+    static const WCHAR opcode_end[] = {' ',',','(',')','[',']','"',0};
+    static const WCHAR param_end[] = {',','(',')','[',']',0};
+
+    WCHAR *original = command;
+    WCHAR *opcode = NULL, **argv = NULL, *p;
+    int argc = 0, i;
+    DWORD ret = DDE_FACK;
+
+    while (*command == ' ') command++;
+
+    if (*command != '[') goto error;
+    while (*command == '[')
+    {
+        argc = 0;
+        argv = HeapAlloc(GetProcessHeap(), 0, sizeof(*argv));
+
+        command++;
+        while (*command == ' ') command++;
+        if (!(p = strpbrkW(command, opcode_end))) goto error;
+
+        opcode = strndupW(command, p - command);
+
+        command = p;
+        while (*command == ' ') command++;
+        if (*command == '(')
+        {
+            command++;
+
+            while (*command != ')')
+            {
+                while (*command == ' ') command++;
+                if (*command == '"')
+                {
+                    command++;
+                    if (!(p = strchrW(command, '"'))) goto error;
+                }
+                else
+                {
+                    if (!(p = strpbrkW(command, param_end))) goto error;
+                    while (p[-1] == ' ') p--;
+                }
 
-    pszCommand = (WCHAR *)DdeAccessData(hdata, NULL);
-    if (!pszCommand)
-        return DDE_FNOTPROCESSED;
+                argc++;
+                argv = HeapReAlloc(GetProcessHeap(), 0, argv, argc * sizeof(*argv));
+                argv[argc-1] = strndupW(command, p - command);
 
-    FIXME("stub: %s %s\n", debugstr_hsz(hszTopic), debugstr_w(pszCommand));
+                command = p;
+                if (*command == '"') command++;
+                while (*command == ' ') command++;
+                if (*command == ',') command++;
+                else if (*command != ')') goto error;
+            }
+            command++;
 
-    DdeUnaccessData(hdata);
+            while (*command == ' ') command++;
+        }
 
+        if (*command != ']') goto error;
+        command++;
+        while (*command == ' ') command++;
+
+        if (hszTopic == hszProgmanTopic)
+            ret = PROGMAN_OnExecute(opcode, argc, argv);
+        else
+        {
+            FIXME("unhandled topic %s, command %s\n", debugstr_hsz(hszTopic), debugstr_w(opcode));
+            ret = DDE_FNOTPROCESSED;
+        }
+
+        HeapFree(GetProcessHeap(), 0, opcode);
+        for (i = 0; i < argc; i++) HeapFree(GetProcessHeap(), 0, argv[i]);
+        HeapFree(GetProcessHeap(), 0, argv);
+
+        if (ret == DDE_FNOTPROCESSED) break;
+    }
+
+    return ret;
+
+error:
+    ERR("failed to parse command %s\n", debugstr_w(original));
+    HeapFree(GetProcessHeap(), 0, opcode);
+    for (i = 0; i < argc; i++) HeapFree(GetProcessHeap(), 0, argv[i]);
+    HeapFree(GetProcessHeap(), 0, argv);
     return DDE_FNOTPROCESSED;
 }
 
+static DWORD Dde_OnExecute(HCONV hconv, HSZ hszTopic, HDDEDATA hdata)
+{
+    WCHAR *command;
+    DWORD len;
+    DWORD ret;
+
+    len = DdeGetData(hdata, NULL, 0, 0);
+    if (!len) return DDE_FNOTPROCESSED;
+    command = HeapAlloc(GetProcessHeap(), 0, len);
+    DdeGetData(hdata, (BYTE *)command, len, 0);
+
+    TRACE("conv=%p topic=%s data=%s\n", hconv, debugstr_hsz(hszTopic), debugstr_w(command));
+
+    ret = parse_dde_command(hszTopic, command);
+
+    HeapFree(GetProcessHeap(), 0, command);
+    return ret;
+}
+
 static inline void Dde_OnDisconnect(HCONV hconv)
 {
     TRACE( "%p\n", hconv );
diff --git a/dlls/shell32/shell32_main.h b/dlls/shell32/shell32_main.h
index 368c0e0..b65141f 100644
--- a/dlls/shell32/shell32_main.h
+++ b/dlls/shell32/shell32_main.h
@@ -238,6 +238,19 @@ static inline WCHAR *strdupW(const WCHAR *src)
     return dest;
 }
 
+static inline WCHAR *strndupW(const WCHAR *src, DWORD len)
+{
+    WCHAR *dest;
+    if (!src) return NULL;
+    dest = HeapAlloc(GetProcessHeap(), 0, (len + 1) * sizeof(*dest));
+    if (dest)
+    {
+        memcpy(dest, src, len * sizeof(WCHAR));
+        dest[len] = '\0';
+    }
+    return dest;
+}
+
 static inline WCHAR *strdupAtoW(const char *str)
 {
     WCHAR *ret;




More information about the wine-cvs mailing list