[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