Signed-off-by: Zebediah Figura z.figura12@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));