2 * Unit test of the Program Manager DDE Interfaces
4 * Copyright 2009 Mikey Alexander
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 /* DDE Program Manager Tests
22 * - Covers basic CreateGroup, ShowGroup, DeleteGroup, AddItem, and DeleteItem
24 * - Todo: Handle CommonGroupFlag
25 * Better AddItem Tests (Lots of parameters to test)
26 * Tests for Invalid Characters in Names / Invalid Parameters
30 #include <wine/test.h>
37 static HRESULT (WINAPI
*pSHGetLocalizedName
)(LPCWSTR
, LPWSTR
, UINT
, int *);
39 static void init_function_pointers(void)
43 hmod
= GetModuleHandleA("shell32.dll");
44 pSHGetLocalizedName
= (void*)GetProcAddress(hmod
, "SHGetLocalizedName");
47 static BOOL
use_common(void)
50 static BOOL (WINAPI
*pIsNTAdmin
)(DWORD
, LPDWORD
);
52 /* IsNTAdmin() is available on all platforms. */
53 hmod
= LoadLibraryA("advpack.dll");
54 pIsNTAdmin
= (void*)GetProcAddress(hmod
, "IsNTAdmin");
56 if (!pIsNTAdmin(0, NULL
))
58 /* We are definitely not an administrator */
64 /* If we end up here we are on NT4+ as Win9x and WinMe don't have the
65 * notion of administrators (as we need it).
68 /* As of Vista we should always use the users directory. Tests with the
69 * real Administrator account on Windows 7 proved this.
71 * FIXME: We need a better way of identifying Vista+ as currently this check
72 * also covers Wine and we don't know yet which behavior we want to follow.
74 if (pSHGetLocalizedName
)
80 static BOOL
full_title(void)
84 memset(&cs
, 0, sizeof(cs
));
85 ReadCabinetState(&cs
, sizeof(cs
));
87 return (cs
.fFullPathTitle
== -1);
90 static char ProgramsDir
[MAX_PATH
];
92 static void init_strings(void)
94 char commonprograms
[MAX_PATH
];
95 char programs
[MAX_PATH
];
97 SHGetSpecialFolderPathA(NULL
, programs
, CSIDL_PROGRAMS
, FALSE
);
98 SHGetSpecialFolderPathA(NULL
, commonprograms
, CSIDL_COMMON_PROGRAMS
, FALSE
);
100 /* ProgramsDir on Vista+ is always the users one (CSIDL_PROGRAMS). Before Vista
101 * it depends on whether the user is an administrator (CSIDL_COMMON_PROGRAMS) or
102 * not (CSIDL_PROGRAMS).
105 lstrcpyA(ProgramsDir
, commonprograms
);
107 lstrcpyA(ProgramsDir
, programs
);
110 static HDDEDATA CALLBACK
DdeCallback(UINT type
, UINT format
, HCONV hConv
, HSZ hsz1
, HSZ hsz2
,
111 HDDEDATA hDDEData
, ULONG_PTR data1
, ULONG_PTR data2
)
113 trace("Callback: type=%i, format=%i\n", type
, format
);
117 static UINT
dde_execute(DWORD instance
, HCONV hconv
, const char *command_str
)
119 HDDEDATA command
, hdata
;
123 command
= DdeCreateDataHandle(instance
, (BYTE
*)command_str
, strlen(command_str
)+1, 0, 0, 0, 0);
124 ok(command
!= NULL
, "DdeCreateDataHandle() failed: %u\n", DdeGetLastError(instance
));
126 hdata
= DdeClientTransaction((BYTE
*)command
, -1, hconv
, 0, 0, XTYP_EXECUTE
, 2000, &result
);
127 ret
= DdeGetLastError(instance
);
128 /* PROGMAN always returns 1 on success */
129 ok((UINT_PTR
)hdata
== !ret
, "expected %u, got %p\n", !ret
, hdata
);
134 static char *dde_request(DWORD instance
, HCONV hconv
, const char *request_str
)
136 static char data
[2000];
141 item
= DdeCreateStringHandleA(instance
, request_str
, CP_WINANSI
);
142 ok(item
!= NULL
, "DdeCreateStringHandle() failed: %u\n", DdeGetLastError(instance
));
144 hdata
= DdeClientTransaction(NULL
, -1, hconv
, item
, CF_TEXT
, XTYP_REQUEST
, 2000, &result
);
145 if (hdata
== NULL
) return NULL
;
147 DdeGetData(hdata
, (BYTE
*)data
, 2000, 0);
152 static BOOL
check_window_exists(const char *name
)
154 char title
[MAX_PATH
];
160 strcpy(title
, ProgramsDir
);
167 for (i
= 0; i
< 20; i
++)
170 if ((window
= FindWindowA("ExplorerWClass", title
)) ||
171 (window
= FindWindowA("CabinetWClass", title
)))
173 SendMessageA(window
, WM_SYSCOMMAND
, SC_CLOSE
, 0);
178 return (window
!= NULL
);
181 static BOOL
check_exists(const char *name
)
185 strcpy(path
, ProgramsDir
);
188 return GetFileAttributesA(path
) != INVALID_FILE_ATTRIBUTES
;
191 static void test_parser(DWORD instance
, HCONV hConv
)
195 /* Invalid Command */
196 error
= dde_execute(instance
, hConv
, "[InvalidCommand()]");
197 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
200 error
= dde_execute(instance
, hConv
, "");
201 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
203 error
= dde_execute(instance
, hConv
, "CreateGroup");
204 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
206 error
= dde_execute(instance
, hConv
, "[CreateGroup");
207 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
209 error
= dde_execute(instance
, hConv
, "[CreateGroup]");
210 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
212 error
= dde_execute(instance
, hConv
, "[CreateGroup()]");
213 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
215 error
= dde_execute(instance
, hConv
, "[cREATEgROUP(test)]");
216 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
217 ok(check_exists("test"), "directory not created\n");
218 ok(check_window_exists("test"), "window not created\n");
220 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,foobar)]");
221 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
222 ok(check_exists("test/foobar.lnk"), "link not created\n");
224 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,foo bar)]");
225 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
226 ok(check_exists("test/foo bar.lnk"), "link not created\n");
228 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,a[b,c]d)]");
229 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
231 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,\"a[b,c]d\")]");
232 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
233 ok(check_exists("test/a[b,c]d.lnk"), "link not created\n");
235 error
= dde_execute(instance
, hConv
, " [ AddItem ( notepad , test ) ] ");
236 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
237 ok(check_exists("test/test.lnk"), "link not created\n");
239 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,one)][AddItem(notepad,two)]");
240 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
241 ok(check_exists("test/one.lnk"), "link not created\n");
242 ok(check_exists("test/two.lnk"), "link not created\n");
244 error
= dde_execute(instance
, hConv
, "[FakeCommand(test)][DeleteGroup(test)]");
245 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
246 ok(check_exists("test"), "directory should exist\n");
248 error
= dde_execute(instance
, hConv
, "[DeleteGroup(test)]");
249 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
250 ok(!check_exists("test"), "directory should not exist\n");
252 error
= dde_execute(instance
, hConv
, "[ExitProgman()]");
253 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
255 error
= dde_execute(instance
, hConv
, "[ExitProgman]");
256 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
259 /* 1st set of tests */
260 static void test_progman_dde(DWORD instance
, HCONV hConv
)
264 /* test creating and deleting groups and items */
265 error
= dde_execute(instance
, hConv
, "[CreateGroup(Group1)]");
266 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
267 ok(check_exists("Group1"), "directory not created\n");
268 ok(check_window_exists("Group1"), "window not created\n");
270 error
= dde_execute(instance
, hConv
, "[AddItem]");
271 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
273 error
= dde_execute(instance
, hConv
, "[AddItem(test)]");
274 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
276 error
= dde_execute(instance
, hConv
, "[AddItem(notepad.exe)]");
277 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
278 ok(check_exists("Group1/notepad.lnk"), "link not created\n");
280 error
= dde_execute(instance
, hConv
, "[DeleteItem(notepad.exe)]");
281 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
283 error
= dde_execute(instance
, hConv
, "[DeleteItem(notepad)]");
284 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
285 ok(!check_exists("Group1/notepad.lnk"), "link should not exist\n");
287 error
= dde_execute(instance
, hConv
, "[DeleteItem(notepad)]");
288 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
290 error
= dde_execute(instance
, hConv
, "[AddItem(notepad)]");
291 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
292 ok(check_exists("Group1/notepad.lnk"), "link not created\n");
294 error
= dde_execute(instance
, hConv
, "[AddItem(notepad)]");
295 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
297 /* XP allows any valid path even if it does not exist; Vista+ requires that
298 * the path both exist and be a file (directories are invalid). */
300 error
= dde_execute(instance
, hConv
, "[AddItem(C:\\windows\\system.ini)]");
301 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
302 ok(check_exists("Group1/system.lnk"), "link not created\n");
304 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,test1)]");
305 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
306 ok(check_exists("Group1/test1.lnk"), "link not created\n");
308 error
= dde_execute(instance
, hConv
, "[DeleteItem(test1)]");
309 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
310 ok(!check_exists("Group1/test1.lnk"), "link should not exist\n");
312 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,test1)]");
313 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
314 ok(check_exists("Group1/test1.lnk"), "link not created\n");
316 error
= dde_execute(instance
, hConv
, "[ReplaceItem(test1)]");
317 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
318 ok(!check_exists("Group1/test1.lnk"), "link should not exist\n");
320 error
= dde_execute(instance
, hConv
, "[AddItem(regedit)]");
321 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
322 ok(check_exists("Group1/regedit.lnk"), "link not created\n");
324 /* test ShowGroup() and test which group an item gets added to */
325 error
= dde_execute(instance
, hConv
, "[ShowGroup(Group1)]");
326 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
328 error
= dde_execute(instance
, hConv
, "[ShowGroup(Group1, 0)]");
329 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
330 ok(check_window_exists("Group1"), "window not created\n");
332 error
= dde_execute(instance
, hConv
, "[CreateGroup(Group2)]");
333 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
334 ok(check_exists("Group2"), "directory not created\n");
335 ok(check_window_exists("Group2"), "window not created\n");
337 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,test2)]");
338 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
339 ok(check_exists("Group2/test2.lnk"), "link not created\n");
341 error
= dde_execute(instance
, hConv
, "[ShowGroup(Group1, 0)]");
342 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
343 ok(check_window_exists("Group1"), "window not created\n");
345 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,test3)]");
346 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
347 ok(check_exists("Group1/test3.lnk"), "link not created\n");
349 error
= dde_execute(instance
, hConv
, "[DeleteGroup(Group1)]");
350 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
351 ok(!check_exists("Group1"), "directory should not exist\n");
353 error
= dde_execute(instance
, hConv
, "[DeleteGroup(Group1)]");
354 ok(error
== DMLERR_NOTPROCESSED
, "expected DMLERR_NOTPROCESSED, got %u\n", error
);
356 error
= dde_execute(instance
, hConv
, "[ShowGroup(Group2, 0)]");
357 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
358 ok(check_window_exists("Group2"), "window not created\n");
360 error
= dde_execute(instance
, hConv
, "[ExitProgman(1)]");
361 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
363 error
= dde_execute(instance
, hConv
, "[AddItem(notepad,test4)]");
364 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
365 ok(check_exists("Group2/test4.lnk"), "link not created\n");
368 /* 2nd set of tests - 2nd connection */
369 static void test_progman_dde2(DWORD instance
, HCONV hConv
)
373 /* last open group is retained across connections */
374 error
= dde_execute(instance
, hConv
, "[AddItem(notepad)]");
375 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
376 ok(check_exists("Group2/notepad.lnk"), "link not created\n");
378 error
= dde_execute(instance
, hConv
, "[DeleteGroup(Group2)]");
379 ok(error
== DMLERR_NO_ERROR
, "expected DMLERR_NO_ERROR, got %u\n", error
);
380 ok(!check_exists("Group2"), "directory should not exist\n");
383 static BOOL
check_in_programs_list(const char *list
, const char *group
)
387 if (!strncmp(list
, group
, strlen(group
)) && list
[strlen(group
)] == '\r')
389 if (!(list
= strchr(list
, '\r'))) break;
395 static void test_request_groups(DWORD instance
, HCONV hconv
)
398 char programs
[MAX_PATH
];
399 WIN32_FIND_DATAA finddata
;
402 list
= dde_request(instance
, hconv
, "Groups");
403 ok(list
!= NULL
, "request failed: %u\n", DdeGetLastError(instance
));
404 strcpy(programs
, ProgramsDir
);
405 strcat(programs
, "/*");
406 hfind
= FindFirstFileA(programs
, &finddata
);
409 if ((finddata
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) && finddata
.cFileName
[0] != '.')
411 ok(check_in_programs_list(list
, finddata
.cFileName
),
412 "directory '%s' missing from group list\n", finddata
.cFileName
);
414 } while (FindNextFileA(hfind
, &finddata
));
418 START_TEST(progman_dde
)
426 init_function_pointers();
429 /* Initialize DDE Instance */
430 err
= DdeInitializeA(&instance
, DdeCallback
, APPCMD_CLIENTONLY
, 0);
431 ok(err
== DMLERR_NO_ERROR
, "DdeInitialize() failed: %u\n", err
);
433 /* Create Connection */
434 hszProgman
= DdeCreateStringHandleA(instance
, "PROGMAN", CP_WINANSI
);
435 ok(hszProgman
!= NULL
, "DdeCreateStringHandle() failed: %u\n", DdeGetLastError(instance
));
436 hConv
= DdeConnect(instance
, hszProgman
, hszProgman
, NULL
);
437 ret
= DdeFreeStringHandle(instance
, hszProgman
);
438 ok(ret
, "DdeFreeStringHandle() failed: %u\n", DdeGetLastError(instance
));
439 /* Seeing failures on early versions of Windows Connecting to progman, exit if connection fails */
442 ok (DdeUninitialize(instance
), "DdeUninitialize failed\n");
446 test_parser(instance
, hConv
);
447 test_progman_dde(instance
, hConv
);
448 test_request_groups(instance
, hConv
);
451 ret
= DdeDisconnect(hConv
);
452 ok(ret
, "DdeDisonnect() failed: %u\n", DdeGetLastError(instance
));
453 ret
= DdeUninitialize(instance
);
454 ok(ret
, "DdeUninitialize() failed: %u\n", DdeGetLastError(instance
));
456 /* 2nd Instance (Followup Tests) */
457 /* Initialize DDE Instance */
459 err
= DdeInitializeA(&instance
, DdeCallback
, APPCMD_CLIENTONLY
, 0);
460 ok (err
== DMLERR_NO_ERROR
, "DdeInitialize() failed: %u\n", err
);
462 /* Create Connection */
463 hszProgman
= DdeCreateStringHandleA(instance
, "PROGMAN", CP_WINANSI
);
464 ok(hszProgman
!= NULL
, "DdeCreateStringHandle() failed: %u\n", DdeGetLastError(instance
));
465 hConv
= DdeConnect(instance
, hszProgman
, hszProgman
, NULL
);
466 ok(hConv
!= NULL
, "DdeConnect() failed: %u\n", DdeGetLastError(instance
));
467 ret
= DdeFreeStringHandle(instance
, hszProgman
);
468 ok(ret
, "DdeFreeStringHandle() failed: %u\n", DdeGetLastError(instance
));
471 test_progman_dde2(instance
, hConv
);
474 ret
= DdeDisconnect(hConv
);
475 ok(ret
, "DdeDisonnect() failed: %u\n", DdeGetLastError(instance
));
476 ret
= DdeUninitialize(instance
);
477 ok(ret
, "DdeUninitialize() failed: %u\n", DdeGetLastError(instance
));