mirror of
https://github.com/reactos/reactos.git
synced 2025-08-07 00:23:02 +00:00
sync shell32 winetest to wine 1.1.32
svn path=/trunk/; revision=44098
This commit is contained in:
parent
7f4bf6c490
commit
4574bb5be8
5 changed files with 361 additions and 143 deletions
|
@ -205,6 +205,7 @@ static void test_setpos(void)
|
||||||
RECT rc;
|
RECT rc;
|
||||||
int screen_width, screen_height;
|
int screen_width, screen_height;
|
||||||
BOOL ret;
|
BOOL ret;
|
||||||
|
int org_bottom1;
|
||||||
|
|
||||||
screen_width = GetSystemMetrics(SM_CXSCREEN);
|
screen_width = GetSystemMetrics(SM_CXSCREEN);
|
||||||
screen_height = GetSystemMetrics(SM_CYSCREEN);
|
screen_height = GetSystemMetrics(SM_CYSCREEN);
|
||||||
|
@ -336,6 +337,9 @@ static void test_setpos(void)
|
||||||
|
|
||||||
/* removing windows[0] will cause windows[1] to move down into its space */
|
/* removing windows[0] will cause windows[1] to move down into its space */
|
||||||
expected_bottom = max(windows[0].allocated_rect.bottom, windows[1].allocated_rect.bottom);
|
expected_bottom = max(windows[0].allocated_rect.bottom, windows[1].allocated_rect.bottom);
|
||||||
|
org_bottom1 = windows[1].allocated_rect.bottom;
|
||||||
|
ok(windows[0].allocated_rect.bottom > windows[1].allocated_rect.bottom,
|
||||||
|
"Expected windows[0] to be lower than windows[1]\n");
|
||||||
|
|
||||||
abd.hWnd = windows[0].hwnd;
|
abd.hWnd = windows[0].hwnd;
|
||||||
windows[0].to_be_deleted = TRUE;
|
windows[0].to_be_deleted = TRUE;
|
||||||
|
@ -346,7 +350,12 @@ static void test_setpos(void)
|
||||||
|
|
||||||
do_events_until(got_expected_bottom);
|
do_events_until(got_expected_bottom);
|
||||||
|
|
||||||
ok(windows[1].allocated_rect.bottom == expected_bottom, "windows[1]'s bottom is %i, expected %i\n", windows[1].allocated_rect.bottom, expected_bottom);
|
if (windows[1].allocated_rect.bottom == org_bottom1)
|
||||||
|
win_skip("Some broken Vista boxes don't move the higher appbar down\n");
|
||||||
|
else
|
||||||
|
ok(windows[1].allocated_rect.bottom == expected_bottom,
|
||||||
|
"windows[1]'s bottom is %i, expected %i\n",
|
||||||
|
windows[1].allocated_rect.bottom, expected_bottom);
|
||||||
|
|
||||||
test_window_rects(1, 2);
|
test_window_rects(1, 2);
|
||||||
|
|
||||||
|
|
|
@ -107,6 +107,7 @@ static void test_get_set(void)
|
||||||
{
|
{
|
||||||
HRESULT r;
|
HRESULT r;
|
||||||
IShellLinkA *sl;
|
IShellLinkA *sl;
|
||||||
|
IShellLinkW *slW = NULL;
|
||||||
char mypath[MAX_PATH];
|
char mypath[MAX_PATH];
|
||||||
char buffer[INFOTIPSIZE];
|
char buffer[INFOTIPSIZE];
|
||||||
LPITEMIDLIST pidl, tmp_pidl;
|
LPITEMIDLIST pidl, tmp_pidl;
|
||||||
|
@ -156,6 +157,19 @@ static void test_get_set(void)
|
||||||
ok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r);
|
ok(SUCCEEDED(r), "GetPath failed (0x%08x)\n", r);
|
||||||
ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
|
ok(*buffer=='\0', "GetPath returned '%s'\n", buffer);
|
||||||
|
|
||||||
|
CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
|
||||||
|
&IID_IShellLinkW, (LPVOID*)&slW);
|
||||||
|
if (!slW)
|
||||||
|
skip("SetPath with NULL parameter crashes on Win9x\n");
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IShellLinkW_Release(slW);
|
||||||
|
r = IShellLinkA_SetPath(sl, NULL);
|
||||||
|
ok(r==E_INVALIDARG ||
|
||||||
|
broken(r==S_OK), /* Some Win95 and NT4 */
|
||||||
|
"SetPath failed (0x%08x)\n", r);
|
||||||
|
}
|
||||||
|
|
||||||
r = IShellLinkA_SetPath(sl, "");
|
r = IShellLinkA_SetPath(sl, "");
|
||||||
ok(r==S_OK, "SetPath failed (0x%08x)\n", r);
|
ok(r==S_OK, "SetPath failed (0x%08x)\n", r);
|
||||||
|
|
||||||
|
@ -651,16 +665,12 @@ static void test_load_save(void)
|
||||||
static void test_datalink(void)
|
static void test_datalink(void)
|
||||||
{
|
{
|
||||||
static const WCHAR lnk[] = {
|
static const WCHAR lnk[] = {
|
||||||
':',':','{','9','d','b','1','1','8','6','f','-','4','0','d','f','-','1',
|
':',':','{','9','d','b','1','1','8','6','e','-','4','0','d','f','-','1',
|
||||||
'1','d','1','-','a','a','8','c','-','0','0','c','0','4','f','b','6','7',
|
'1','d','1','-','a','a','8','c','-','0','0','c','0','4','f','b','6','7',
|
||||||
'8','6','3','}',':','{','0','0','0','1','0','4','0','9','-','7','8','E',
|
'8','6','3','}',':','2','6',',','!','!','g','x','s','f','(','N','g',']',
|
||||||
'1','-','1','1','D','2','-','B','6','0','F','-','0','0','6','0','9','7',
|
'q','F','`','H','{','L','s','A','C','C','E','S','S','F','i','l','e','s',
|
||||||
'C','9','9','8','E','7','}',':',':','{','9','d','b','1','1','8','6','e',
|
'>','p','l','T',']','j','I','{','j','f','(','=','1','&','L','[','-','8',
|
||||||
'-','4','0','d','f','-','1','1','d','1','-','a','a','8','c','-','0','0',
|
'1','-',']',':',':',0 };
|
||||||
'c','0','4','f','b','6','7','8','6','3','}',':','2','6',',','!','!','g',
|
|
||||||
'x','s','f','(','N','g',']','q','F','`','H','{','L','s','A','C','C','E',
|
|
||||||
'S','S','F','i','l','e','s','>','p','l','T',']','j','I','{','j','f','(',
|
|
||||||
'=','1','&','L','[','-','8','1','-',']',':',':',0 };
|
|
||||||
static const WCHAR comp[] = {
|
static const WCHAR comp[] = {
|
||||||
'2','6',',','!','!','g','x','s','f','(','N','g',']','q','F','`','H','{',
|
'2','6',',','!','!','g','x','s','f','(','N','g',']','q','F','`','H','{',
|
||||||
'L','s','A','C','C','E','S','S','F','i','l','e','s','>','p','l','T',']',
|
'L','s','A','C','C','E','S','S','F','i','l','e','s','>','p','l','T',']',
|
||||||
|
@ -704,6 +714,9 @@ static void test_datalink(void)
|
||||||
ok( r == E_FAIL, "CopyDataBlock failed\n");
|
ok( r == E_FAIL, "CopyDataBlock failed\n");
|
||||||
ok( dar == NULL, "should be null\n");
|
ok( dar == NULL, "should be null\n");
|
||||||
|
|
||||||
|
r = IShellLinkW_SetPath(sl, NULL);
|
||||||
|
ok(r == E_INVALIDARG, "set path failed\n");
|
||||||
|
|
||||||
r = IShellLinkW_SetPath(sl, lnk);
|
r = IShellLinkW_SetPath(sl, lnk);
|
||||||
ok(r == S_OK, "set path failed\n");
|
ok(r == S_OK, "set path failed\n");
|
||||||
|
|
||||||
|
@ -715,7 +728,8 @@ static void test_datalink(void)
|
||||||
flags = 0;
|
flags = 0;
|
||||||
r = IShellLinkDataList_GetFlags( dl, &flags );
|
r = IShellLinkDataList_GetFlags( dl, &flags );
|
||||||
ok( r == S_OK, "GetFlags failed\n");
|
ok( r == S_OK, "GetFlags failed\n");
|
||||||
ok( flags == (SLDF_HAS_DARWINID|SLDF_HAS_LOGO3ID),
|
/* SLDF_HAS_LOGO3ID is no longer supported on Vista+, filter it out */
|
||||||
|
ok( (flags & (~ SLDF_HAS_LOGO3ID)) == SLDF_HAS_DARWINID,
|
||||||
"GetFlags returned wrong flags\n");
|
"GetFlags returned wrong flags\n");
|
||||||
|
|
||||||
dar = NULL;
|
dar = NULL;
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* from pidl.h, not included here: */
|
/* from pidl.h, not included here: */
|
||||||
|
#ifndef PT_CPL /* Guess, Win7 uses this for CSIDL_CONTROLS */
|
||||||
|
#define PT_CPL 0x01 /* no path */
|
||||||
|
#endif
|
||||||
#ifndef PT_GUID
|
#ifndef PT_GUID
|
||||||
#define PT_GUID 0x1f /* no path */
|
#define PT_GUID 0x1f /* no path */
|
||||||
#endif
|
#endif
|
||||||
|
@ -93,7 +96,7 @@ static UINT (WINAPI *pGetSystemWow64DirectoryA)(LPSTR,UINT);
|
||||||
static DLLVERSIONINFO shellVersion = { 0 };
|
static DLLVERSIONINFO shellVersion = { 0 };
|
||||||
static LPMALLOC pMalloc;
|
static LPMALLOC pMalloc;
|
||||||
static const BYTE guidType[] = { PT_GUID };
|
static const BYTE guidType[] = { PT_GUID };
|
||||||
static const BYTE controlPanelType[] = { PT_SHELLEXT, PT_GUID };
|
static const BYTE controlPanelType[] = { PT_SHELLEXT, PT_GUID, PT_CPL };
|
||||||
static const BYTE folderType[] = { PT_FOLDER, PT_FOLDERW };
|
static const BYTE folderType[] = { PT_FOLDER, PT_FOLDERW };
|
||||||
static const BYTE favoritesType[] = { PT_FOLDER, PT_FOLDERW, 0, PT_IESPECIAL2 /* Win98 */ };
|
static const BYTE favoritesType[] = { PT_FOLDER, PT_FOLDERW, 0, PT_IESPECIAL2 /* Win98 */ };
|
||||||
static const BYTE folderOrSpecialType[] = { PT_FOLDER, PT_IESPECIAL2 };
|
static const BYTE folderOrSpecialType[] = { PT_FOLDER, PT_IESPECIAL2 };
|
||||||
|
|
|
@ -56,6 +56,7 @@ static char** myARGV;
|
||||||
static char tmpdir[MAX_PATH];
|
static char tmpdir[MAX_PATH];
|
||||||
static char child_file[MAX_PATH];
|
static char child_file[MAX_PATH];
|
||||||
static DLLVERSIONINFO dllver;
|
static DLLVERSIONINFO dllver;
|
||||||
|
static BOOL skip_noassoc_tests = FALSE;
|
||||||
|
|
||||||
|
|
||||||
/***
|
/***
|
||||||
|
@ -117,7 +118,18 @@ static int shell_execute(LPCSTR operation, LPCSTR file, LPCSTR parameters, LPCST
|
||||||
{
|
{
|
||||||
int wait_rc;
|
int wait_rc;
|
||||||
wait_rc=WaitForSingleObject(hEvent, 5000);
|
wait_rc=WaitForSingleObject(hEvent, 5000);
|
||||||
ok(wait_rc==WAIT_OBJECT_0, "WaitForSingleObject returned %d\n", wait_rc);
|
if (wait_rc == WAIT_TIMEOUT)
|
||||||
|
{
|
||||||
|
HWND wnd = FindWindowA("#32770", "Windows");
|
||||||
|
if (wnd != NULL)
|
||||||
|
{
|
||||||
|
SendMessage(wnd, WM_CLOSE, 0, 0);
|
||||||
|
win_skip("Skipping shellexecute of file with unassociated extension\n");
|
||||||
|
skip_noassoc_tests = TRUE;
|
||||||
|
rc = SE_ERR_NOASSOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ok(wait_rc==WAIT_OBJECT_0 || rc <= 32, "WaitForSingleObject returned %d\n", wait_rc);
|
||||||
}
|
}
|
||||||
/* The child process may have changed the result file, so let profile
|
/* The child process may have changed the result file, so let profile
|
||||||
* functions know about it
|
* functions know about it
|
||||||
|
@ -462,11 +474,67 @@ static void childPrintf(HANDLE h, const char* fmt, ...)
|
||||||
WriteFile(h, buffer, strlen(buffer), &w, NULL);
|
WriteFile(h, buffer, strlen(buffer), &w, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static DWORD ddeInst;
|
||||||
|
static HSZ hszTopic;
|
||||||
|
static char ddeExec[MAX_PATH], ddeApplication[MAX_PATH];
|
||||||
|
static BOOL post_quit_on_execute;
|
||||||
|
|
||||||
|
static HDDEDATA CALLBACK ddeCb(UINT uType, UINT uFmt, HCONV hConv,
|
||||||
|
HSZ hsz1, HSZ hsz2, HDDEDATA hData,
|
||||||
|
ULONG_PTR dwData1, ULONG_PTR dwData2)
|
||||||
|
{
|
||||||
|
DWORD size = 0;
|
||||||
|
|
||||||
|
if (winetest_debug > 2)
|
||||||
|
trace("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
|
||||||
|
uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
|
||||||
|
|
||||||
|
switch (uType)
|
||||||
|
{
|
||||||
|
case XTYP_CONNECT:
|
||||||
|
if (!DdeCmpStringHandles(hsz1, hszTopic))
|
||||||
|
{
|
||||||
|
size = DdeQueryString(ddeInst, hsz2, ddeApplication, MAX_PATH, CP_WINANSI);
|
||||||
|
assert(size < MAX_PATH);
|
||||||
|
return (HDDEDATA)TRUE;
|
||||||
|
}
|
||||||
|
return (HDDEDATA)FALSE;
|
||||||
|
|
||||||
|
case XTYP_EXECUTE:
|
||||||
|
size = DdeGetData(hData, (LPBYTE)ddeExec, MAX_PATH, 0L);
|
||||||
|
assert(size < MAX_PATH);
|
||||||
|
DdeFreeDataHandle(hData);
|
||||||
|
if (post_quit_on_execute)
|
||||||
|
PostQuitMessage(0);
|
||||||
|
return (HDDEDATA)DDE_FACK;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is just to make sure the child won't run forever stuck in a GetMessage()
|
||||||
|
* loop when DDE fails for some reason.
|
||||||
|
*/
|
||||||
|
static void CALLBACK childTimeout(HWND wnd, UINT msg, UINT_PTR timer, DWORD time)
|
||||||
|
{
|
||||||
|
trace("childTimeout called\n");
|
||||||
|
|
||||||
|
PostQuitMessage(0);
|
||||||
|
}
|
||||||
|
|
||||||
static void doChild(int argc, char** argv)
|
static void doChild(int argc, char** argv)
|
||||||
{
|
{
|
||||||
char* filename;
|
char* filename;
|
||||||
HANDLE hFile;
|
HANDLE hFile, map;
|
||||||
int i;
|
int i;
|
||||||
|
int rc;
|
||||||
|
HSZ hszApplication;
|
||||||
|
UINT_PTR timer;
|
||||||
|
HANDLE dde_ready;
|
||||||
|
MSG msg;
|
||||||
|
char *shared_block;
|
||||||
|
|
||||||
filename=argv[2];
|
filename=argv[2];
|
||||||
hFile=CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
hFile=CreateFileA(filename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
|
||||||
|
@ -484,6 +552,51 @@ static void doChild(int argc, char** argv)
|
||||||
trace("argvA%d=%s\n", i, argv[i]);
|
trace("argvA%d=%s\n", i, argv[i]);
|
||||||
childPrintf(hFile, "argvA%d=%s\r\n", i, encodeA(argv[i]));
|
childPrintf(hFile, "argvA%d=%s\r\n", i, encodeA(argv[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
map = OpenFileMappingA(FILE_MAP_READ, FALSE, "winetest_shlexec_dde_map");
|
||||||
|
if (map != NULL)
|
||||||
|
{
|
||||||
|
shared_block = MapViewOfFile(map, FILE_MAP_READ, 0, 0, 4096);
|
||||||
|
CloseHandle(map);
|
||||||
|
if (shared_block[0] != '\0' || shared_block[1] != '\0')
|
||||||
|
{
|
||||||
|
post_quit_on_execute = TRUE;
|
||||||
|
ddeInst = 0;
|
||||||
|
rc = DdeInitializeA(&ddeInst, ddeCb, CBF_SKIP_ALLNOTIFICATIONS | CBF_FAIL_ADVISES |
|
||||||
|
CBF_FAIL_POKES | CBF_FAIL_REQUESTS, 0L);
|
||||||
|
assert(rc == DMLERR_NO_ERROR);
|
||||||
|
hszApplication = DdeCreateStringHandleA(ddeInst, shared_block, CP_WINANSI);
|
||||||
|
hszTopic = DdeCreateStringHandleA(ddeInst, shared_block + strlen(shared_block) + 1, CP_WINANSI);
|
||||||
|
assert(hszApplication && hszTopic);
|
||||||
|
assert(DdeNameService(ddeInst, hszApplication, 0L, DNS_REGISTER | DNS_FILTEROFF));
|
||||||
|
|
||||||
|
timer = SetTimer(NULL, 0, 2500, childTimeout);
|
||||||
|
|
||||||
|
dde_ready = CreateEvent(NULL, FALSE, FALSE, "winetest_shlexec_dde_ready");
|
||||||
|
SetEvent(dde_ready);
|
||||||
|
CloseHandle(dde_ready);
|
||||||
|
|
||||||
|
while (GetMessage(&msg, NULL, 0, 0))
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
|
||||||
|
KillTimer(NULL, timer);
|
||||||
|
assert(DdeNameService(ddeInst, hszApplication, 0L, DNS_UNREGISTER));
|
||||||
|
assert(DdeFreeStringHandle(ddeInst, hszTopic));
|
||||||
|
assert(DdeFreeStringHandle(ddeInst, hszApplication));
|
||||||
|
assert(DdeUninitialize(ddeInst));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dde_ready = CreateEvent(NULL, FALSE, FALSE, "winetest_shlexec_dde_ready");
|
||||||
|
SetEvent(dde_ready);
|
||||||
|
CloseHandle(dde_ready);
|
||||||
|
}
|
||||||
|
|
||||||
|
UnmapViewOfFile(shared_block);
|
||||||
|
|
||||||
|
childPrintf(hFile, "ddeExec=%s\r\n", encodeA(ddeExec));
|
||||||
|
}
|
||||||
|
|
||||||
CloseHandle(hFile);
|
CloseHandle(hFile);
|
||||||
|
|
||||||
init_event(filename);
|
init_event(filename);
|
||||||
|
@ -751,6 +864,13 @@ static void test_filename(void)
|
||||||
{
|
{
|
||||||
BOOL quotedfile = FALSE;
|
BOOL quotedfile = FALSE;
|
||||||
|
|
||||||
|
if (skip_noassoc_tests && test->rc == SE_ERR_NOASSOC)
|
||||||
|
{
|
||||||
|
win_skip("Skipping shellexecute of file with unassociated extension\n");
|
||||||
|
test++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(filename, test->basename, tmpdir);
|
sprintf(filename, test->basename, tmpdir);
|
||||||
if (strchr(filename, '/'))
|
if (strchr(filename, '/'))
|
||||||
{
|
{
|
||||||
|
@ -1159,14 +1279,21 @@ static void test_exes(void)
|
||||||
okChildInt("argcA", 4);
|
okChildInt("argcA", 4);
|
||||||
okChildString("argvA3", "Exec");
|
okChildString("argvA3", "Exec");
|
||||||
|
|
||||||
sprintf(filename, "%s\\test file.noassoc", tmpdir);
|
if (! skip_noassoc_tests)
|
||||||
if (CopyFile(argv0, filename, FALSE))
|
|
||||||
{
|
{
|
||||||
rc=shell_execute(NULL, filename, params, NULL);
|
sprintf(filename, "%s\\test file.noassoc", tmpdir);
|
||||||
todo_wine {
|
if (CopyFile(argv0, filename, FALSE))
|
||||||
ok(rc==SE_ERR_NOASSOC, "%s succeeded: rc=%d\n", shell_call, rc);
|
{
|
||||||
|
rc=shell_execute(NULL, filename, params, NULL);
|
||||||
|
todo_wine {
|
||||||
|
ok(rc==SE_ERR_NOASSOC, "%s succeeded: rc=%d\n", shell_call, rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
win_skip("Skipping shellexecute of file with unassociated extension\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_exes_long(void)
|
static void test_exes_long(void)
|
||||||
|
@ -1190,14 +1317,21 @@ static void test_exes_long(void)
|
||||||
okChildInt("argcA", 4);
|
okChildInt("argcA", 4);
|
||||||
okChildString("argvA3", longparam);
|
okChildString("argvA3", longparam);
|
||||||
|
|
||||||
sprintf(filename, "%s\\test file.noassoc", tmpdir);
|
if (! skip_noassoc_tests)
|
||||||
if (CopyFile(argv0, filename, FALSE))
|
|
||||||
{
|
{
|
||||||
rc=shell_execute(NULL, filename, params, NULL);
|
sprintf(filename, "%s\\test file.noassoc", tmpdir);
|
||||||
todo_wine {
|
if (CopyFile(argv0, filename, FALSE))
|
||||||
ok(rc==SE_ERR_NOASSOC, "%s succeeded: rc=%d\n", shell_call, rc);
|
{
|
||||||
|
rc=shell_execute(NULL, filename, params, NULL);
|
||||||
|
todo_wine {
|
||||||
|
ok(rc==SE_ERR_NOASSOC, "%s succeeded: rc=%d\n", shell_call, rc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
win_skip("Skipping shellexecute of file with unassociated extension\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -1210,115 +1344,123 @@ typedef struct
|
||||||
int expectedArgs;
|
int expectedArgs;
|
||||||
const char* expectedDdeExec;
|
const char* expectedDdeExec;
|
||||||
int todo;
|
int todo;
|
||||||
int rc;
|
|
||||||
} dde_tests_t;
|
} dde_tests_t;
|
||||||
|
|
||||||
static dde_tests_t dde_tests[] =
|
static dde_tests_t dde_tests[] =
|
||||||
{
|
{
|
||||||
/* Test passing and not passing command-line
|
/* Test passing and not passing command-line
|
||||||
* argument, no DDE */
|
* argument, no DDE */
|
||||||
{"", NULL, NULL, NULL, NULL, FALSE, "", 0x0, 33},
|
{"", NULL, NULL, NULL, NULL, FALSE, "", 0x0},
|
||||||
{"\"%1\"", NULL, NULL, NULL, NULL, TRUE, "", 0x0, 33},
|
{"\"%1\"", NULL, NULL, NULL, NULL, TRUE, "", 0x0},
|
||||||
|
|
||||||
/* Test passing and not passing command-line
|
/* Test passing and not passing command-line
|
||||||
* argument, with DDE */
|
* argument, with DDE */
|
||||||
{"", "[open(\"%1\")]", "shlexec", "dde", NULL, FALSE, "[open(\"%s\")]", 0x0, 33},
|
{"", "[open(\"%1\")]", "shlexec", "dde", NULL, FALSE, "[open(\"%s\")]", 0x0},
|
||||||
{"\"%1\"", "[open(\"%1\")]", "shlexec", "dde", NULL, TRUE, "[open(\"%s\")]", 0x0, 33},
|
{"\"%1\"", "[open(\"%1\")]", "shlexec", "dde", NULL, TRUE, "[open(\"%s\")]", 0x0},
|
||||||
|
|
||||||
/* Test unquoted %1 in command and ddeexec
|
/* Test unquoted %1 in command and ddeexec
|
||||||
* (test filename has space) */
|
* (test filename has space) */
|
||||||
{"%1", "[open(%1)]", "shlexec", "dde", NULL, 2, "[open(%s)]", 0x0, 33},
|
{"%1", "[open(%1)]", "shlexec", "dde", NULL, 2, "[open(%s)]", 0x0},
|
||||||
|
|
||||||
/* Test ifexec precedence over ddeexec */
|
/* Test ifexec precedence over ddeexec */
|
||||||
{"", "[open(\"%1\")]", "shlexec", "dde", "[ifexec(\"%1\")]", FALSE, "[ifexec(\"%s\")]", 0x0, 33},
|
{"", "[open(\"%1\")]", "shlexec", "dde", "[ifexec(\"%1\")]", FALSE, "[ifexec(\"%s\")]", 0x0},
|
||||||
|
|
||||||
/* Test default DDE topic */
|
/* Test default DDE topic */
|
||||||
{"", "[open(\"%1\")]", "shlexec", NULL, NULL, FALSE, "[open(\"%s\")]", 0x0, 33},
|
{"", "[open(\"%1\")]", "shlexec", NULL, NULL, FALSE, "[open(\"%s\")]", 0x0},
|
||||||
|
|
||||||
/* Test default DDE application */
|
/* Test default DDE application */
|
||||||
{"", "[open(\"%1\")]", NULL, "dde", NULL, FALSE, "[open(\"%s\")]", 0x0, 33},
|
{"", "[open(\"%1\")]", NULL, "dde", NULL, FALSE, "[open(\"%s\")]", 0x0},
|
||||||
|
|
||||||
{NULL, NULL, NULL, NULL, NULL, 0, 0x0, 0}
|
{NULL, NULL, NULL, NULL, NULL, 0, 0x0}
|
||||||
};
|
};
|
||||||
|
|
||||||
static DWORD ddeInst;
|
static DWORD WINAPI hooked_WaitForInputIdle(HANDLE process, DWORD timeout)
|
||||||
static HSZ hszTopic;
|
|
||||||
static char ddeExec[MAX_PATH], ddeApplication[MAX_PATH];
|
|
||||||
static BOOL denyNextConnection;
|
|
||||||
|
|
||||||
static HDDEDATA CALLBACK ddeCb(UINT uType, UINT uFmt, HCONV hConv,
|
|
||||||
HSZ hsz1, HSZ hsz2, HDDEDATA hData,
|
|
||||||
ULONG_PTR dwData1, ULONG_PTR dwData2)
|
|
||||||
{
|
{
|
||||||
DWORD size = 0;
|
HANDLE dde_ready;
|
||||||
|
DWORD wait_result;
|
||||||
|
|
||||||
if (winetest_debug > 2)
|
dde_ready = CreateEventA(NULL, FALSE, FALSE, "winetest_shlexec_dde_ready");
|
||||||
trace("dde_cb: %04x, %04x, %p, %p, %p, %p, %08lx, %08lx\n",
|
wait_result = WaitForSingleObject(dde_ready, timeout);
|
||||||
uType, uFmt, hConv, hsz1, hsz2, hData, dwData1, dwData2);
|
CloseHandle(dde_ready);
|
||||||
|
|
||||||
switch (uType)
|
return wait_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* WaitForInputIdle() will normally return immediately for console apps. That's
|
||||||
|
* a problem for us because ShellExecute will assume that an app is ready to
|
||||||
|
* receive DDE messages after it has called WaitForInputIdle() on that app.
|
||||||
|
* To work around that we install our own version of WaitForInputIdle() that
|
||||||
|
* will wait for the child to explicitly tell us that it is ready. We do that
|
||||||
|
* by changing the entry for WaitForInputIdle() in the shell32 import address
|
||||||
|
* table.
|
||||||
|
*/
|
||||||
|
static void hook_WaitForInputIdle(void *new_func)
|
||||||
|
{
|
||||||
|
char *base;
|
||||||
|
PIMAGE_NT_HEADERS nt_headers;
|
||||||
|
DWORD import_directory_rva;
|
||||||
|
PIMAGE_IMPORT_DESCRIPTOR import_descriptor;
|
||||||
|
|
||||||
|
base = (char *) GetModuleHandleA("shell32.dll");
|
||||||
|
nt_headers = (PIMAGE_NT_HEADERS)(base + ((PIMAGE_DOS_HEADER) base)->e_lfanew);
|
||||||
|
import_directory_rva = nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
|
||||||
|
|
||||||
|
/* Search for the correct imported module by walking the import descriptors */
|
||||||
|
import_descriptor = (PIMAGE_IMPORT_DESCRIPTOR)(base + import_directory_rva);
|
||||||
|
while (U(*import_descriptor).OriginalFirstThunk != 0)
|
||||||
{
|
{
|
||||||
case XTYP_CONNECT:
|
char *import_module_name;
|
||||||
if (!DdeCmpStringHandles(hsz1, hszTopic))
|
|
||||||
|
import_module_name = base + import_descriptor->Name;
|
||||||
|
if (lstrcmpiA(import_module_name, "user32.dll") == 0 ||
|
||||||
|
lstrcmpiA(import_module_name, "user32") == 0)
|
||||||
|
{
|
||||||
|
PIMAGE_THUNK_DATA int_entry;
|
||||||
|
PIMAGE_THUNK_DATA iat_entry;
|
||||||
|
|
||||||
|
/* The import name table and import address table are two parallel
|
||||||
|
* arrays. We need the import name table to find the imported
|
||||||
|
* routine and the import address table to patch the address, so
|
||||||
|
* walk them side by side */
|
||||||
|
int_entry = (PIMAGE_THUNK_DATA)(base + U(*import_descriptor).OriginalFirstThunk);
|
||||||
|
iat_entry = (PIMAGE_THUNK_DATA)(base + import_descriptor->FirstThunk);
|
||||||
|
while (int_entry->u1.Ordinal != 0)
|
||||||
{
|
{
|
||||||
if (denyNextConnection)
|
if (! IMAGE_SNAP_BY_ORDINAL(int_entry->u1.Ordinal))
|
||||||
denyNextConnection = FALSE;
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
size = DdeQueryString(ddeInst, hsz2, ddeApplication, MAX_PATH, CP_WINANSI);
|
PIMAGE_IMPORT_BY_NAME import_by_name;
|
||||||
assert(size < MAX_PATH);
|
import_by_name = (PIMAGE_IMPORT_BY_NAME)(base + int_entry->u1.AddressOfData);
|
||||||
return (HDDEDATA)TRUE;
|
if (lstrcmpA((char *) import_by_name->Name, "WaitForInputIdle") == 0)
|
||||||
|
{
|
||||||
|
/* Found the correct routine in the correct imported module. Patch it. */
|
||||||
|
DWORD old_prot;
|
||||||
|
VirtualProtect(&iat_entry->u1.Function, sizeof(ULONG_PTR), PAGE_READWRITE, &old_prot);
|
||||||
|
iat_entry->u1.Function = (ULONG_PTR) new_func;
|
||||||
|
VirtualProtect(&iat_entry->u1.Function, sizeof(ULONG_PTR), old_prot, &old_prot);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
int_entry++;
|
||||||
|
iat_entry++;
|
||||||
}
|
}
|
||||||
return (HDDEDATA)FALSE;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case XTYP_EXECUTE:
|
import_descriptor++;
|
||||||
size = DdeGetData(hData, (LPBYTE)ddeExec, MAX_PATH, 0L);
|
|
||||||
assert(size < MAX_PATH);
|
|
||||||
DdeFreeDataHandle(hData);
|
|
||||||
return (HDDEDATA)DDE_FACK;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
char *filename;
|
|
||||||
DWORD threadIdParent;
|
|
||||||
} dde_thread_info_t;
|
|
||||||
|
|
||||||
static DWORD CALLBACK ddeThread(LPVOID arg)
|
|
||||||
{
|
|
||||||
dde_thread_info_t *info = arg;
|
|
||||||
assert(info && info->filename);
|
|
||||||
PostThreadMessage(info->threadIdParent,
|
|
||||||
WM_QUIT,
|
|
||||||
shell_execute_ex(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI, NULL, info->filename, NULL, NULL),
|
|
||||||
0L);
|
|
||||||
ExitThread(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ShellExecute won't successfully send DDE commands to console applications after starting them,
|
|
||||||
* so we run a DDE server in this application, deny the first connection request to make
|
|
||||||
* ShellExecute start the application, and then process the next DDE connection in this application
|
|
||||||
* to see the execute command that is sent. */
|
|
||||||
static void test_dde(void)
|
static void test_dde(void)
|
||||||
{
|
{
|
||||||
char filename[MAX_PATH], defApplication[MAX_PATH];
|
char filename[MAX_PATH], defApplication[MAX_PATH];
|
||||||
HSZ hszApplication;
|
|
||||||
dde_thread_info_t info = { filename, GetCurrentThreadId() };
|
|
||||||
const dde_tests_t* test;
|
const dde_tests_t* test;
|
||||||
char params[1024];
|
char params[1024];
|
||||||
DWORD threadId;
|
|
||||||
MSG msg;
|
|
||||||
int rc;
|
int rc;
|
||||||
|
HANDLE map;
|
||||||
|
char *shared_block;
|
||||||
|
|
||||||
ddeInst = 0;
|
hook_WaitForInputIdle((void *) hooked_WaitForInputIdle);
|
||||||
rc = DdeInitializeA(&ddeInst, ddeCb, CBF_SKIP_ALLNOTIFICATIONS | CBF_FAIL_ADVISES |
|
|
||||||
CBF_FAIL_POKES | CBF_FAIL_REQUESTS, 0L);
|
|
||||||
assert(rc == DMLERR_NO_ERROR);
|
|
||||||
|
|
||||||
sprintf(filename, "%s\\test file.sde", tmpdir);
|
sprintf(filename, "%s\\test file.sde", tmpdir);
|
||||||
|
|
||||||
|
@ -1326,6 +1468,10 @@ static void test_dde(void)
|
||||||
strcpy(defApplication, strrchr(argv0, '\\')+1);
|
strcpy(defApplication, strrchr(argv0, '\\')+1);
|
||||||
*strchr(defApplication, '.') = 0;
|
*strchr(defApplication, '.') = 0;
|
||||||
|
|
||||||
|
map = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0,
|
||||||
|
4096, "winetest_shlexec_dde_map");
|
||||||
|
shared_block = MapViewOfFile(map, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, 4096);
|
||||||
|
|
||||||
test = dde_tests;
|
test = dde_tests;
|
||||||
while (test->command)
|
while (test->command)
|
||||||
{
|
{
|
||||||
|
@ -1336,29 +1482,31 @@ static void test_dde(void)
|
||||||
}
|
}
|
||||||
create_test_verb_dde(".sde", "Open", 0, test->command, test->ddeexec,
|
create_test_verb_dde(".sde", "Open", 0, test->command, test->ddeexec,
|
||||||
test->application, test->topic, test->ifexec);
|
test->application, test->topic, test->ifexec);
|
||||||
hszApplication = DdeCreateStringHandleA(ddeInst, test->application ?
|
|
||||||
test->application : defApplication, CP_WINANSI);
|
if (test->application != NULL || test->topic != NULL)
|
||||||
hszTopic = DdeCreateStringHandleA(ddeInst, test->topic ? test->topic : SZDDESYS_TOPIC,
|
{
|
||||||
CP_WINANSI);
|
strcpy(shared_block, test->application ? test->application : defApplication);
|
||||||
assert(hszApplication && hszTopic);
|
strcpy(shared_block + strlen(shared_block) + 1, test->topic ? test->topic : SZDDESYS_TOPIC);
|
||||||
assert(DdeNameService(ddeInst, hszApplication, 0L, DNS_REGISTER));
|
}
|
||||||
denyNextConnection = TRUE;
|
else
|
||||||
|
{
|
||||||
|
shared_block[0] = '\0';
|
||||||
|
shared_block[1] = '\0';
|
||||||
|
}
|
||||||
ddeExec[0] = 0;
|
ddeExec[0] = 0;
|
||||||
|
|
||||||
assert(CreateThread(NULL, 0, ddeThread, &info, 0, &threadId));
|
rc = shell_execute_ex(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI, NULL, filename, NULL, NULL);
|
||||||
while (GetMessage(&msg, NULL, 0, 0)) DispatchMessage(&msg);
|
|
||||||
rc = msg.wParam > 32 ? 33 : msg.wParam;
|
|
||||||
if ((test->todo & 0x1)==0)
|
if ((test->todo & 0x1)==0)
|
||||||
{
|
{
|
||||||
ok(rc==test->rc, "%s failed: rc=%d err=%d\n", shell_call,
|
ok(32 < rc, "%s failed: rc=%d err=%d\n", shell_call,
|
||||||
rc, GetLastError());
|
rc, GetLastError());
|
||||||
}
|
}
|
||||||
else todo_wine
|
else todo_wine
|
||||||
{
|
{
|
||||||
ok(rc==test->rc, "%s failed: rc=%d err=%d\n", shell_call,
|
ok(32 < rc, "%s failed: rc=%d err=%d\n", shell_call,
|
||||||
rc, GetLastError());
|
rc, GetLastError());
|
||||||
}
|
}
|
||||||
if (rc == 33)
|
if (32 < rc)
|
||||||
{
|
{
|
||||||
if ((test->todo & 0x2)==0)
|
if ((test->todo & 0x2)==0)
|
||||||
{
|
{
|
||||||
|
@ -1382,25 +1530,22 @@ static void test_dde(void)
|
||||||
if ((test->todo & 0x8) == 0)
|
if ((test->todo & 0x8) == 0)
|
||||||
{
|
{
|
||||||
sprintf(params, test->expectedDdeExec, filename);
|
sprintf(params, test->expectedDdeExec, filename);
|
||||||
ok(StrCmpPath(params, ddeExec) == 0,
|
okChildPath("ddeExec", params);
|
||||||
"ddeexec expected '%s', got '%s'\n", params, ddeExec);
|
|
||||||
}
|
}
|
||||||
else todo_wine
|
else todo_wine
|
||||||
{
|
{
|
||||||
sprintf(params, test->expectedDdeExec, filename);
|
sprintf(params, test->expectedDdeExec, filename);
|
||||||
ok(StrCmpPath(params, ddeExec) == 0,
|
okChildPath("ddeExec", params);
|
||||||
"ddeexec expected '%s', got '%s'\n", params, ddeExec);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(DdeNameService(ddeInst, hszApplication, 0L, DNS_UNREGISTER));
|
|
||||||
assert(DdeFreeStringHandle(ddeInst, hszTopic));
|
|
||||||
assert(DdeFreeStringHandle(ddeInst, hszApplication));
|
|
||||||
delete_test_association(".sde");
|
delete_test_association(".sde");
|
||||||
test++;
|
test++;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(DdeUninitialize(ddeInst));
|
UnmapViewOfFile(shared_block);
|
||||||
|
CloseHandle(map);
|
||||||
|
hook_WaitForInputIdle((void *) WaitForInputIdle);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DDE_DEFAULT_APP_VARIANTS 2
|
#define DDE_DEFAULT_APP_VARIANTS 2
|
||||||
|
@ -1454,6 +1599,23 @@ static dde_default_app_tests_t dde_default_app_tests[] =
|
||||||
{NULL, {NULL}, 0, {0}}
|
{NULL, {NULL}, 0, {0}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
char *filename;
|
||||||
|
DWORD threadIdParent;
|
||||||
|
} dde_thread_info_t;
|
||||||
|
|
||||||
|
static DWORD CALLBACK ddeThread(LPVOID arg)
|
||||||
|
{
|
||||||
|
dde_thread_info_t *info = arg;
|
||||||
|
assert(info && info->filename);
|
||||||
|
PostThreadMessage(info->threadIdParent,
|
||||||
|
WM_QUIT,
|
||||||
|
shell_execute_ex(SEE_MASK_FLAG_DDEWAIT | SEE_MASK_FLAG_NO_UI, NULL, info->filename, NULL, NULL),
|
||||||
|
0L);
|
||||||
|
ExitThread(0);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_dde_default_app(void)
|
static void test_dde_default_app(void)
|
||||||
{
|
{
|
||||||
char filename[MAX_PATH];
|
char filename[MAX_PATH];
|
||||||
|
@ -1465,6 +1627,7 @@ static void test_dde_default_app(void)
|
||||||
MSG msg;
|
MSG msg;
|
||||||
int rc, which = 0;
|
int rc, which = 0;
|
||||||
|
|
||||||
|
post_quit_on_execute = FALSE;
|
||||||
ddeInst = 0;
|
ddeInst = 0;
|
||||||
rc = DdeInitializeA(&ddeInst, ddeCb, CBF_SKIP_ALLNOTIFICATIONS | CBF_FAIL_ADVISES |
|
rc = DdeInitializeA(&ddeInst, ddeCb, CBF_SKIP_ALLNOTIFICATIONS | CBF_FAIL_ADVISES |
|
||||||
CBF_FAIL_POKES | CBF_FAIL_REQUESTS, 0L);
|
CBF_FAIL_POKES | CBF_FAIL_REQUESTS, 0L);
|
||||||
|
@ -1491,7 +1654,6 @@ static void test_dde_default_app(void)
|
||||||
sprintf(params, test->command, tmpdir);
|
sprintf(params, test->command, tmpdir);
|
||||||
create_test_verb_dde(".sde", "Open", 1, params, "[test]", NULL,
|
create_test_verb_dde(".sde", "Open", 1, params, "[test]", NULL,
|
||||||
"shlexec", NULL);
|
"shlexec", NULL);
|
||||||
denyNextConnection = FALSE;
|
|
||||||
ddeApplication[0] = 0;
|
ddeApplication[0] = 0;
|
||||||
|
|
||||||
/* No application will be run as we will respond to the first DDE event,
|
/* No application will be run as we will respond to the first DDE event,
|
||||||
|
|
|
@ -48,8 +48,8 @@
|
||||||
"Expected %d, got %d\n", ret, retval)
|
"Expected %d, got %d\n", ret, retval)
|
||||||
|
|
||||||
static CHAR CURR_DIR[MAX_PATH];
|
static CHAR CURR_DIR[MAX_PATH];
|
||||||
static const WCHAR UNICODE_PATH[] = {'c',':','\\',0x00c4,'\0','\0'};
|
static const WCHAR UNICODE_PATH[] = {'c',':','\\',0x00ae,'\0','\0'};
|
||||||
/* "c:\Ä", or "c:\A" with diaeresis */
|
/* "c:\®" can be used in all codepages */
|
||||||
/* Double-null termination needed for pFrom field of SHFILEOPSTRUCT */
|
/* Double-null termination needed for pFrom field of SHFILEOPSTRUCT */
|
||||||
|
|
||||||
static HMODULE hshell32;
|
static HMODULE hshell32;
|
||||||
|
@ -207,11 +207,11 @@ static void test_get_file_info(void)
|
||||||
memset(&shfiw, 0xcf, sizeof(shfiw));
|
memset(&shfiw, 0xcf, sizeof(shfiw));
|
||||||
memset(&unset_icon, 0xcf, sizeof(unset_icon));
|
memset(&unset_icon, 0xcf, sizeof(unset_icon));
|
||||||
rc=pSHGetFileInfoW(NULL, 0, &shfiw, sizeof(shfiw), 0);
|
rc=pSHGetFileInfoW(NULL, 0, &shfiw, sizeof(shfiw), 0);
|
||||||
todo_wine ok(!rc, "SHGetFileInfoW(NULL | 0) should fail\n");
|
ok(!rc, "SHGetFileInfoW(NULL | 0) should fail\n");
|
||||||
ok(shfiw.hIcon == unset_icon, "SHGetFileInfoW(NULL | 0) should not clear hIcon\n");
|
ok(shfiw.hIcon == unset_icon, "SHGetFileInfoW(NULL | 0) should not clear hIcon\n");
|
||||||
todo_wine ok(shfiw.szDisplayName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szDisplayName[0]\n");
|
ok(shfiw.szDisplayName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szDisplayName[0]\n");
|
||||||
todo_wine ok(shfiw.szTypeName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szTypeName[0]\n");
|
ok(shfiw.szTypeName[0] == 0xcfcf, "SHGetFileInfoW(NULL | 0) should not clear szTypeName[0]\n");
|
||||||
todo_wine ok(shfiw.iIcon == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear iIcon\n");
|
ok(shfiw.iIcon == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear iIcon\n");
|
||||||
ok(shfiw.dwAttributes == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear dwAttributes\n");
|
ok(shfiw.dwAttributes == 0xcfcfcfcf, "SHGetFileInfoW(NULL | 0) should not clear dwAttributes\n");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1042,10 +1042,13 @@ static void test_copy(void)
|
||||||
shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
|
shfo.pTo = "testdir2\\a.txt\0testdir2\\b.txt\0testdir2\\c.txt\0";
|
||||||
shfo.fAnyOperationsAborted = FALSE;
|
shfo.fAnyOperationsAborted = FALSE;
|
||||||
retval = SHFileOperation(&shfo);
|
retval = SHFileOperation(&shfo);
|
||||||
ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
|
ok(retval == ERROR_SUCCESS ||
|
||||||
|
broken(retval == 0x100a1), /* WinMe */
|
||||||
|
"Expected ERROR_SUCCESS, got %d\n", retval);
|
||||||
ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
|
ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
|
||||||
ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
|
ok(DeleteFile("testdir2\\b.txt"), "Expected testdir2\\b.txt to exist\n");
|
||||||
ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
|
if (retval == ERROR_SUCCESS)
|
||||||
|
ok(RemoveDirectory("testdir2\\c.txt"), "Expected testdir2\\c.txt to exist\n");
|
||||||
|
|
||||||
/* try many dest files without FOF_MULTIDESTFILES flag */
|
/* try many dest files without FOF_MULTIDESTFILES flag */
|
||||||
shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
|
shfo.pFrom = "test1.txt\0test2.txt\0test3.txt\0";
|
||||||
|
@ -1073,7 +1076,9 @@ static void test_copy(void)
|
||||||
shfo.pTo = "testdir2\0";
|
shfo.pTo = "testdir2\0";
|
||||||
shfo.fFlags &= ~FOF_MULTIDESTFILES;
|
shfo.fFlags &= ~FOF_MULTIDESTFILES;
|
||||||
retval = SHFileOperation(&shfo);
|
retval = SHFileOperation(&shfo);
|
||||||
ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
|
ok(retval == ERROR_SUCCESS ||
|
||||||
|
broken(retval == 0x100a1), /* WinMe */
|
||||||
|
"Expected ERROR_SUCCESS, got %d\n", retval);
|
||||||
ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
|
ok(file_exists("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
|
||||||
|
|
||||||
/* try a glob with FOF_FILESONLY */
|
/* try a glob with FOF_FILESONLY */
|
||||||
|
@ -1190,18 +1195,28 @@ static void test_copy(void)
|
||||||
shfo.fFlags &= ~FOF_MULTIDESTFILES;
|
shfo.fFlags &= ~FOF_MULTIDESTFILES;
|
||||||
shfo.fAnyOperationsAborted = FALSE;
|
shfo.fAnyOperationsAborted = FALSE;
|
||||||
retval = SHFileOperation(&shfo);
|
retval = SHFileOperation(&shfo);
|
||||||
ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
|
ok(retval == ERROR_SUCCESS ||
|
||||||
ok(DeleteFile("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
|
broken(retval == 0x100a1), /* WinMe */
|
||||||
ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
|
"Expected ERROR_SUCCESS, got %d\n", retval);
|
||||||
ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
|
if (retval == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ok(DeleteFile("testdir2\\test1.txt"), "Expected testdir2\\test1.txt to exist\n");
|
||||||
|
ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
|
||||||
|
ok(RemoveDirectory("testdir2\\test4.txt"), "Expected testdir2\\test4.txt to exist\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* copy one directory and a file in that dir to another dir */
|
/* copy one directory and a file in that dir to another dir */
|
||||||
shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
|
shfo.pFrom = "test4.txt\0test4.txt\\a.txt\0";
|
||||||
shfo.pTo = "testdir2\0";
|
shfo.pTo = "testdir2\0";
|
||||||
retval = SHFileOperation(&shfo);
|
retval = SHFileOperation(&shfo);
|
||||||
ok(retval == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", retval);
|
ok(retval == ERROR_SUCCESS ||
|
||||||
ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
|
broken(retval == 0x100a1), /* WinMe */
|
||||||
ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
|
"Expected ERROR_SUCCESS, got %d\n", retval);
|
||||||
|
if (retval == ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
ok(DeleteFile("testdir2\\test4.txt\\a.txt"), "Expected a.txt to exist\n");
|
||||||
|
ok(DeleteFile("testdir2\\a.txt"), "Expected testdir2\\a.txt to exist\n");
|
||||||
|
}
|
||||||
|
|
||||||
/* copy a file in a directory first, and then the directory to a nonexistent dir */
|
/* copy a file in a directory first, and then the directory to a nonexistent dir */
|
||||||
shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
|
shfo.pFrom = "test4.txt\\a.txt\0test4.txt\0";
|
||||||
|
@ -1362,13 +1377,21 @@ static void test_copy(void)
|
||||||
createTestFile("test4.txt\\test1.txt");
|
createTestFile("test4.txt\\test1.txt");
|
||||||
shfo.pFrom = "test4.txt\0";
|
shfo.pFrom = "test4.txt\0";
|
||||||
shfo.pTo = "testdir2\0";
|
shfo.pTo = "testdir2\0";
|
||||||
shfo.fFlags = FOF_NOCONFIRMATION;
|
/* WinMe needs FOF_NOERRORUI */
|
||||||
ok(!SHFileOperation(&shfo), "First SHFileOperation failed\n");
|
shfo.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI;
|
||||||
createTestFile("test4.txt\\.\\test1.txt"); /* modify the content of the file */
|
|
||||||
/* without FOF_NOCONFIRMATION the confirmation is "This folder already contains a folder named ..." */
|
|
||||||
retval = SHFileOperation(&shfo);
|
retval = SHFileOperation(&shfo);
|
||||||
ok(retval == 0, "Expected 0, got %d\n", retval);
|
ok(retval == ERROR_SUCCESS ||
|
||||||
ok(file_has_content("testdir2\\test4.txt\\test1.txt", "test4.txt\\.\\test1.txt\n"), "The file was not copied\n");
|
broken(retval == 0x100a1), /* WinMe */
|
||||||
|
"Expected ERROR_SUCCESS, got %d\n", retval);
|
||||||
|
shfo.fFlags = FOF_NOCONFIRMATION;
|
||||||
|
if (ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
createTestFile("test4.txt\\.\\test1.txt"); /* modify the content of the file */
|
||||||
|
/* without FOF_NOCONFIRMATION the confirmation is "This folder already contains a folder named ..." */
|
||||||
|
retval = SHFileOperation(&shfo);
|
||||||
|
ok(retval == 0, "Expected 0, got %d\n", retval);
|
||||||
|
ok(file_has_content("testdir2\\test4.txt\\test1.txt", "test4.txt\\.\\test1.txt\n"), "The file was not copied\n");
|
||||||
|
}
|
||||||
|
|
||||||
createTestFile("one.txt");
|
createTestFile("one.txt");
|
||||||
|
|
||||||
|
@ -1955,6 +1978,7 @@ static void test_sh_path_prepare(void)
|
||||||
{
|
{
|
||||||
HRESULT res;
|
HRESULT res;
|
||||||
CHAR path[MAX_PATH];
|
CHAR path[MAX_PATH];
|
||||||
|
CHAR UNICODE_PATH_A[MAX_PATH];
|
||||||
|
|
||||||
if(!pSHPathPrepareForWriteA)
|
if(!pSHPathPrepareForWriteA)
|
||||||
{
|
{
|
||||||
|
@ -1987,12 +2011,14 @@ static void test_sh_path_prepare(void)
|
||||||
set_curr_dir_path(path, "test1.txt\0");
|
set_curr_dir_path(path, "test1.txt\0");
|
||||||
res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
|
res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
|
||||||
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
|
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
|
||||||
|
res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
|
||||||
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
|
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
|
||||||
"Unexpected result : 0x%08x\n", res);
|
"Unexpected result : 0x%08x\n", res);
|
||||||
|
|
||||||
/* file exists, SHPPFW_DIRCREATE */
|
/* file exists, SHPPFW_DIRCREATE */
|
||||||
res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
|
res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_DIRCREATE);
|
||||||
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
|
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
|
||||||
|
res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
|
||||||
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
|
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
|
||||||
"Unexpected result : 0x%08x\n", res);
|
"Unexpected result : 0x%08x\n", res);
|
||||||
|
|
||||||
|
@ -2000,6 +2026,7 @@ static void test_sh_path_prepare(void)
|
||||||
set_curr_dir_path(path, "test1.txt\\\0");
|
set_curr_dir_path(path, "test1.txt\\\0");
|
||||||
res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
|
res = pSHPathPrepareForWriteA(0, 0, path, SHPPFW_NONE);
|
||||||
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
|
ok(res == HRESULT_FROM_WIN32(ERROR_DIRECTORY) ||
|
||||||
|
res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND) || /* WinMe */
|
||||||
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
|
res == HRESULT_FROM_WIN32(ERROR_INVALID_NAME), /* Vista */
|
||||||
"Unexpected result : 0x%08x\n", res);
|
"Unexpected result : 0x%08x\n", res);
|
||||||
|
|
||||||
|
@ -2040,19 +2067,22 @@ static void test_sh_path_prepare(void)
|
||||||
|
|
||||||
if(!pSHPathPrepareForWriteW)
|
if(!pSHPathPrepareForWriteW)
|
||||||
{
|
{
|
||||||
skip("Skipping SHPathPrepareForWriteW tests\n");
|
win_skip("Skipping SHPathPrepareForWriteW tests\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
WideCharToMultiByte(CP_ACP, 0, UNICODE_PATH, -1, UNICODE_PATH_A, sizeof(UNICODE_PATH_A), NULL, NULL);
|
||||||
|
|
||||||
/* unicode directory doesn't exist, SHPPFW_NONE */
|
/* unicode directory doesn't exist, SHPPFW_NONE */
|
||||||
|
RemoveDirectoryA(UNICODE_PATH_A);
|
||||||
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
|
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
|
||||||
ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
|
ok(res == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "res == %08x, expected HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND)\n", res);
|
||||||
ok(!file_existsW(UNICODE_PATH), "unicode path was created but shouldn't be\n");
|
ok(!file_exists(UNICODE_PATH_A), "unicode path was created but shouldn't be\n");
|
||||||
RemoveDirectoryW(UNICODE_PATH);
|
RemoveDirectoryA(UNICODE_PATH_A);
|
||||||
|
|
||||||
/* unicode directory doesn't exist, SHPPFW_DIRCREATE */
|
/* unicode directory doesn't exist, SHPPFW_DIRCREATE */
|
||||||
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
|
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
|
||||||
ok(res == S_OK, "res == %08x, expected S_OK\n", res);
|
ok(res == S_OK, "res == %08x, expected S_OK\n", res);
|
||||||
ok(file_existsW(UNICODE_PATH), "unicode path should've been created\n");
|
ok(file_exists(UNICODE_PATH_A), "unicode path should've been created\n");
|
||||||
|
|
||||||
/* unicode directory exists, SHPPFW_NONE */
|
/* unicode directory exists, SHPPFW_NONE */
|
||||||
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
|
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_NONE);
|
||||||
|
@ -2061,7 +2091,7 @@ static void test_sh_path_prepare(void)
|
||||||
/* unicode directory exists, SHPPFW_DIRCREATE */
|
/* unicode directory exists, SHPPFW_DIRCREATE */
|
||||||
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
|
res = pSHPathPrepareForWriteW(0, 0, UNICODE_PATH, SHPPFW_DIRCREATE);
|
||||||
ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
|
ok(res == S_OK, "ret == %08x, expected S_OK\n", res);
|
||||||
RemoveDirectoryW(UNICODE_PATH);
|
RemoveDirectoryA(UNICODE_PATH_A);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void test_sh_new_link_info(void)
|
static void test_sh_new_link_info(void)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue