[PATCH 1/4] shell32: Add a parser for DDE commands.
Zebediah Figura
z.figura12 at gmail.com
Wed Nov 29 17:00:45 CST 2017
Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
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;
--
2.7.4
More information about the wine-devel
mailing list