[PATCH 3/3] shell32: Implement the Groups request for Progman DDE.

Zebediah Figura z.figura12 at gmail.com
Fri Dec 1 20:52:51 CST 2017


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/shell32/dde.c               | 81 +++++++++++++++++++++++++++++-----------
 dlls/shell32/tests/progman_dde.c | 53 ++++++++++++++++++++++++++
 2 files changed, 112 insertions(+), 22 deletions(-)

diff --git a/dlls/shell32/dde.c b/dlls/shell32/dde.c
index cfe5a05..365ce1c 100644
--- a/dlls/shell32/dde.c
+++ b/dlls/shell32/dde.c
@@ -79,29 +79,8 @@ static inline BOOL Dde_OnWildConnect(HSZ hszTopic, HSZ hszService)
     return FALSE;
 }
 
-static inline HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic,
-                                     HSZ hszItem)
-{
-    if (hszTopic == hszProgmanTopic && hszItem == hszGroups && uFmt == CF_TEXT)
-    {
-        static BYTE groups_data[] = "Accessories\r\nStartup\r\n";
-        FIXME( "returning fake program groups list\n" );
-        return DdeCreateDataHandle( dwDDEInst, groups_data, sizeof(groups_data), 0, hszGroups, uFmt, 0 );
-    }
-    else if (hszTopic == hszProgmanTopic && hszItem == hszProgmanService && uFmt == CF_TEXT)
-    {
-        static BYTE groups_data[] = "\r\n";
-        FIXME( "returning empty groups list\n" );
-	/* This is a workaround for an application which expects some data
-	 * and cannot handle NULL. */
-        return DdeCreateDataHandle( dwDDEInst, groups_data, sizeof(groups_data), 0, hszProgmanService, uFmt, 0 );
-    }
-    FIXME( "%u %p %s %s: stub\n", uFmt, hconv, debugstr_hsz(hszTopic), debugstr_hsz(hszItem) );
-    return NULL;
-}
-
 /* Returned string must be freed by caller */
-static WCHAR *get_programs_path(WCHAR *name)
+static WCHAR *get_programs_path(const WCHAR *name)
 {
     static const WCHAR slashW[] = {'/',0};
     WCHAR *programs, *path;
@@ -120,6 +99,64 @@ static WCHAR *get_programs_path(WCHAR *name)
     return path;
 }
 
+static inline HDDEDATA Dde_OnRequest(UINT uFmt, HCONV hconv, HSZ hszTopic,
+                                     HSZ hszItem)
+{
+    if (hszTopic == hszProgmanTopic && hszItem == hszGroups && uFmt == CF_TEXT)
+    {
+        static const WCHAR asteriskW[] = {'*',0};
+        static const WCHAR newlineW[] = {'\r','\n',0};
+        static const WCHAR dotW[] = {'.',0};
+        static const WCHAR dotdotW[] = {'.','.',0};
+        WCHAR *programs;
+        WIN32_FIND_DATAW finddata;
+        HANDLE hfind;
+        int len = 1;
+        WCHAR *groups_data = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR));
+        char *groups_dataA;
+        HDDEDATA ret;
+
+        groups_data[0] = 0;
+        programs = get_programs_path(asteriskW);
+        hfind = FindFirstFileW(programs, &finddata);
+        if (hfind)
+        {
+            do
+            {
+                if ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) &&
+                    lstrcmpW(finddata.cFileName, dotW) && lstrcmpW(finddata.cFileName, dotdotW))
+                {
+                    len += lstrlenW(finddata.cFileName) + 2;
+                    groups_data = HeapReAlloc(GetProcessHeap(), 0, groups_data, len * sizeof(WCHAR));
+                    lstrcatW(groups_data, finddata.cFileName);
+                    lstrcatW(groups_data, newlineW);
+                }
+            } while (FindNextFileW(hfind, &finddata));
+            FindClose(hfind);
+        }
+
+        len = WideCharToMultiByte(CP_ACP, 0, groups_data, -1, NULL, 0, NULL, NULL);
+        groups_dataA = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
+        WideCharToMultiByte(CP_ACP, 0, groups_data, -1, groups_dataA, len, NULL, NULL);
+        ret = DdeCreateDataHandle(dwDDEInst, (BYTE *)groups_dataA, len, 0, hszGroups, uFmt, 0);
+
+        HeapFree(GetProcessHeap(), 0, groups_dataA);
+        HeapFree(GetProcessHeap(), 0, groups_data);
+        HeapFree(GetProcessHeap(), 0, programs);
+        return ret;
+    }
+    else if (hszTopic == hszProgmanTopic && hszItem == hszProgmanService && uFmt == CF_TEXT)
+    {
+        static BYTE groups_data[] = "\r\n";
+        FIXME( "returning empty groups list\n" );
+	/* This is a workaround for an application which expects some data
+	 * and cannot handle NULL. */
+        return DdeCreateDataHandle( dwDDEInst, groups_data, sizeof(groups_data), 0, hszProgmanService, uFmt, 0 );
+    }
+    FIXME( "%u %p %s %s: stub\n", uFmt, hconv, debugstr_hsz(hszTopic), debugstr_hsz(hszItem) );
+    return NULL;
+}
+
 static DWORD PROGMAN_OnExecute(WCHAR *command, int argc, WCHAR **argv)
 {
     static const WCHAR create_groupW[] = {'C','r','e','a','t','e','G','r','o','u','p',0};
diff --git a/dlls/shell32/tests/progman_dde.c b/dlls/shell32/tests/progman_dde.c
index b66c862..bfa9f65 100644
--- a/dlls/shell32/tests/progman_dde.c
+++ b/dlls/shell32/tests/progman_dde.c
@@ -171,6 +171,24 @@ static UINT dde_execute(DWORD instance, HCONV hconv, const char *command_str)
     return ret;
 }
 
+static char *dde_request(DWORD instance, HCONV hconv, const char *request_str)
+{
+    static char data[2000];
+    HDDEDATA hdata;
+    HSZ item;
+    DWORD result;
+
+    item = DdeCreateStringHandleA(instance, request_str, CP_WINANSI);
+    ok(item != NULL, "DdeCreateStringHandle() failed: %u\n", DdeGetLastError(instance));
+
+    hdata = DdeClientTransaction(NULL, -1, hconv, item, CF_TEXT, XTYP_REQUEST, 2000, &result);
+    if (hdata == NULL) return NULL;
+
+    DdeGetData(hdata, (BYTE *)data, 2000, 0);
+
+    return data;
+}
+
 static BOOL check_window_exists(const char *name)
 {
     char title[MAX_PATH];
@@ -402,6 +420,40 @@ static void test_progman_dde2(DWORD instance, HCONV hConv)
     ok(!check_exists("Group2"), "directory should not exist\n");
 }
 
+static BOOL check_in_programs_list(const char *list, const char *group)
+{
+    while (1)
+    {
+        if (!strncmp(list, group, strlen(group)) && list[strlen(group)] == '\r')
+            return TRUE;
+        if (!(list = strchr(list, '\r'))) break;
+        list += 2;
+    }
+    return FALSE;
+}
+
+static void test_request_groups(DWORD instance, HCONV hconv)
+{
+    char *list;
+    char programs[MAX_PATH];
+    WIN32_FIND_DATAA finddata;
+    HANDLE hfind;
+
+    list = dde_request(instance, hconv, "Groups");
+    ok(list != NULL, "request failed: %u\n", DdeGetLastError(instance));
+    strcpy(programs, ProgramsDir);
+    strcat(programs, "/*");
+    hfind = FindFirstFileA(programs, &finddata);
+    do
+    {
+        if ((finddata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && finddata.cFileName[0] != '.')
+        {
+            ok(check_in_programs_list(list, finddata.cFileName),
+               "directory '%s' missing from group list\n", finddata.cFileName);
+        }
+    } while (FindNextFileA(hfind, &finddata));
+}
+
 START_TEST(progman_dde)
 {
     DWORD instance = 0;
@@ -430,6 +482,7 @@ START_TEST(progman_dde)
 
     test_parser(instance, hConv);
     test_progman_dde(instance, hConv);
+    test_request_groups(instance, hConv);
 
     /* Cleanup & Exit */
     ok(DdeDisconnect(hConv), "DdeDisonnect() failed: %u\n", DdeGetLastError(instance));
-- 
2.7.4




More information about the wine-devel mailing list