Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
08219c02
Commit
08219c02
authored
Mar 03, 2024
by
Zebediah Figura
Committed by
Alexandre Julliard
Mar 04, 2024
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
shell32/tests: Add tests for context menu copy/paste.
parent
366398cc
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
300 additions
and
0 deletions
+300
-0
shlfolder.c
dlls/shell32/tests/shlfolder.c
+299
-0
shlobj.h
include/shlobj.h
+1
-0
No files found.
dlls/shell32/tests/shlfolder.c
View file @
08219c02
...
...
@@ -5604,6 +5604,304 @@ static void test_SHBindToFolderIDListParent(void)
ok
(
pidl_last
==
NULL
,
"got %p
\n
"
,
pidl_last
);
}
static
void
test_copy_paste
(
void
)
{
CMINVOKECOMMANDINFO
invoke_info
=
{.
cbSize
=
sizeof
(
invoke_info
)};
WCHAR
cwd
[
MAX_PATH
],
temp_path
[
MAX_PATH
],
path
[
MAX_PATH
];
ITEMIDLIST
*
pidl
,
*
src_pidl
,
*
dst_pidl
,
*
pidls
[
2
];
IShellFolder
*
tmp_folder
,
*
dst_folder
;
IContextMenu
*
src_menu
,
*
dst_menu
;
const
DROPFILES
*
dropfiles
;
const
WCHAR
*
filenameW
;
IDataObject
*
data_obj
;
const
CIDA
*
cida
;
STGMEDIUM
medium
;
FORMATETC
format
;
DWORD
*
effect
;
HRESULT
hr
;
BOOL
ret
;
format
.
dwAspect
=
DVASPECT_CONTENT
;
format
.
ptd
=
NULL
;
format
.
tymed
=
TYMED_HGLOBAL
;
format
.
lindex
=
-
1
;
GetCurrentDirectoryW
(
ARRAY_SIZE
(
cwd
),
cwd
);
GetTempPathW
(
ARRAY_SIZE
(
temp_path
),
temp_path
);
SetCurrentDirectoryW
(
temp_path
);
ret
=
CreateDirectoryW
(
L"testcopy_src"
,
NULL
);
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
ret
=
CreateDirectoryW
(
L"testcopy_dst"
,
NULL
);
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
hr
=
SHParseDisplayName
(
temp_path
,
NULL
,
&
pidl
,
0
,
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
SHBindToObject
(
NULL
,
pidl
,
NULL
,
&
IID_IShellFolder
,
(
void
**
)
&
tmp_folder
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ILFree
(
pidl
);
hr
=
IShellFolder_ParseDisplayName
(
tmp_folder
,
NULL
,
NULL
,
(
WCHAR
*
)
L"testcopy_src"
,
NULL
,
&
src_pidl
,
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
IShellFolder_ParseDisplayName
(
tmp_folder
,
NULL
,
NULL
,
(
WCHAR
*
)
L"testcopy_dst"
,
NULL
,
&
dst_pidl
,
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
IShellFolder_BindToObject
(
tmp_folder
,
dst_pidl
,
NULL
,
&
IID_IShellFolder
,
(
void
**
)
&
dst_folder
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
IShellFolder_GetUIObjectOf
(
tmp_folder
,
NULL
,
1
,
(
const
ITEMIDLIST
**
)
&
src_pidl
,
&
IID_IContextMenu
,
NULL
,
(
void
**
)
&
src_menu
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
OleSetClipboard
(
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
/* Cut. */
invoke_info
.
lpVerb
=
"cut"
;
hr
=
IContextMenu_InvokeCommand
(
src_menu
,
&
invoke_info
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
OleGetClipboard
(
&
data_obj
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
trace
(
"%p ole %p shell %p
\n
"
,
data_obj
->
lpVtbl
->
SetData
,
GetModuleHandleW
(
L"ole32"
),
GetModuleHandleW
(
L"shell32"
));
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_SHELLIDLISTW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
CF_HDROP
;
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
RegisterClipboardFormatA
(
CFSTR_FILENAMEA
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_FILENAMEW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_PREFERREDDROPEFFECTW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
if
(
hr
==
S_OK
)
{
effect
=
GlobalLock
(
medium
.
hGlobal
);
ok
(
*
effect
==
DROPEFFECT_MOVE
,
"Got effect %#lx.
\n
"
,
*
effect
);
GlobalUnlock
(
medium
.
hGlobal
);
ReleaseStgMedium
(
&
medium
);
}
IDataObject_Release
(
data_obj
);
ret
=
GetFileAttributesW
(
L"testcopy_src"
);
ok
(
ret
!=
INVALID_FILE_ATTRIBUTES
,
"Got %#x.
\n
"
,
ret
);
hr
=
IShellFolder_GetUIObjectOf
(
tmp_folder
,
NULL
,
1
,
(
const
ITEMIDLIST
**
)
&
dst_pidl
,
&
IID_IContextMenu
,
NULL
,
(
void
**
)
&
dst_menu
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
invoke_info
.
lpVerb
=
"paste"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ret
=
MoveFileExW
(
L"testcopy_dst/testcopy_src"
,
L"testcopy_src"
,
0
);
todo_wine
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
/* Copy. */
invoke_info
.
lpVerb
=
"copy"
;
hr
=
IContextMenu_InvokeCommand
(
src_menu
,
&
invoke_info
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
OleGetClipboard
(
&
data_obj
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_SHELLIDLISTW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_PREFERREDDROPEFFECTW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
if
(
hr
==
S_OK
)
{
effect
=
GlobalLock
(
medium
.
hGlobal
);
ok
(
*
effect
==
(
DROPEFFECT_COPY
|
DROPEFFECT_LINK
),
"Got effect %#lx.
\n
"
,
*
effect
);
GlobalUnlock
(
medium
.
hGlobal
);
ReleaseStgMedium
(
&
medium
);
}
IDataObject_Release
(
data_obj
);
ret
=
GetFileAttributesW
(
L"testcopy_src"
);
ok
(
ret
!=
INVALID_FILE_ATTRIBUTES
,
"Got %#x.
\n
"
,
ret
);
hr
=
IShellFolder_GetUIObjectOf
(
tmp_folder
,
NULL
,
1
,
(
const
ITEMIDLIST
**
)
&
dst_pidl
,
&
IID_IContextMenu
,
NULL
,
(
void
**
)
&
dst_menu
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
invoke_info
.
lpVerb
=
"paste"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ret
=
GetFileAttributesW
(
L"testcopy_src"
);
ok
(
ret
!=
INVALID_FILE_ATTRIBUTES
,
"Got %#x.
\n
"
,
ret
);
ret
=
RemoveDirectoryW
(
L"testcopy_dst/testcopy_src"
);
todo_wine
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
/* Manually change the drop effect back to "cut". */
hr
=
OleGetClipboard
(
&
data_obj
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_PREFERREDDROPEFFECTW
);
medium
.
tymed
=
TYMED_HGLOBAL
;
medium
.
hGlobal
=
GlobalAlloc
(
GMEM_MOVEABLE
,
sizeof
(
DWORD
));
effect
=
GlobalLock
(
medium
.
hGlobal
);
*
effect
=
DROPEFFECT_MOVE
;
GlobalUnlock
(
medium
.
hGlobal
);
hr
=
IDataObject_SetData
(
data_obj
,
&
format
,
&
medium
,
TRUE
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
IDataObject_Release
(
data_obj
);
invoke_info
.
lpVerb
=
"paste"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ret
=
MoveFileExW
(
L"testcopy_dst/testcopy_src"
,
L"testcopy_src"
,
0
);
todo_wine
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
/* Paste into a background menu. */
IContextMenu_Release
(
dst_menu
);
invoke_info
.
lpVerb
=
"copy"
;
hr
=
IContextMenu_InvokeCommand
(
src_menu
,
&
invoke_info
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
IShellFolder_CreateViewObject
(
dst_folder
,
NULL
,
&
IID_IContextMenu
,
(
void
**
)
&
dst_menu
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
invoke_info
.
lpVerb
=
"paste"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ret
=
GetFileAttributesW
(
L"testcopy_src"
);
ok
(
ret
!=
INVALID_FILE_ATTRIBUTES
,
"Got %#x.
\n
"
,
ret
);
ret
=
RemoveDirectoryW
(
L"testcopy_dst/testcopy_src"
);
todo_wine
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
/* Paste into a selection comprising multiple directories. In this case the
* first directory is used, and the second is just ignored.
* This same behaviour can of course be observed when using the UI. */
IContextMenu_Release
(
dst_menu
);
ret
=
CreateDirectoryW
(
L"testcopy_dst2"
,
NULL
);
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
hr
=
IShellFolder_ParseDisplayName
(
tmp_folder
,
NULL
,
NULL
,
(
WCHAR
*
)
L"testcopy_dst2"
,
NULL
,
&
pidls
[
0
],
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
pidls
[
1
]
=
dst_pidl
;
hr
=
IShellFolder_GetUIObjectOf
(
tmp_folder
,
NULL
,
2
,
(
const
ITEMIDLIST
**
)
pidls
,
&
IID_IContextMenu
,
NULL
,
(
void
**
)
&
dst_menu
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
invoke_info
.
lpVerb
=
"paste"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
todo_wine
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ret
=
RemoveDirectoryW
(
L"testcopy_dst2/testcopy_src"
);
todo_wine
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
ret
=
GetFileAttributesW
(
L"testcopy_dst/testcopy_src"
);
ok
(
ret
==
INVALID_FILE_ATTRIBUTES
,
"Got %#x.
\n
"
,
ret
);
/* Cut multiple files, and test the clipboard contents. */
invoke_info
.
lpVerb
=
"cut"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
hr
=
OleGetClipboard
(
&
data_obj
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_SHELLIDLISTW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
cida
=
GlobalLock
(
medium
.
hGlobal
);
ok
(
cida
->
cidl
==
2
,
"Got count %u.
\n
"
,
cida
->
cidl
);
GlobalUnlock
(
medium
.
hGlobal
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
CF_HDROP
;
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
dropfiles
=
GlobalLock
(
medium
.
hGlobal
);
ok
(
dropfiles
->
pFiles
==
sizeof
(
DROPFILES
),
"Got offset %lu.
\n
"
,
dropfiles
->
pFiles
);
ok
(
dropfiles
->
fWide
==
TRUE
,
"Got wide %u.
\n
"
,
dropfiles
->
fWide
);
filenameW
=
(
const
WCHAR
*
)((
const
char
*
)
dropfiles
+
dropfiles
->
pFiles
);
swprintf
(
path
,
ARRAY_SIZE
(
path
),
L"%stestcopy_dst2"
,
temp_path
);
ok
(
!
wcscmp
(
filenameW
,
path
),
"Got path %s.
\n
"
,
debugstr_w
(
filenameW
));
filenameW
+=
wcslen
(
filenameW
)
+
1
;
swprintf
(
path
,
ARRAY_SIZE
(
path
),
L"%stestcopy_dst"
,
temp_path
);
ok
(
!
wcscmp
(
filenameW
,
path
),
"Got path %s.
\n
"
,
debugstr_w
(
filenameW
));
filenameW
+=
wcslen
(
filenameW
)
+
1
;
ok
(
!
filenameW
[
0
],
"Got path %s.
\n
"
,
debugstr_w
(
filenameW
));
GlobalUnlock
(
medium
.
hGlobal
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
RegisterClipboardFormatA
(
CFSTR_FILENAMEA
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
ReleaseStgMedium
(
&
medium
);
format
.
cfFormat
=
RegisterClipboardFormatW
(
CFSTR_FILENAMEW
);
hr
=
IDataObject_GetData
(
data_obj
,
&
format
,
&
medium
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
filenameW
=
GlobalLock
(
medium
.
hGlobal
);
swprintf
(
path
,
ARRAY_SIZE
(
path
),
L"%stestcopy_dst2"
,
temp_path
);
ok
(
!
wcscmp
(
filenameW
,
path
),
"Got path %s.
\n
"
,
debugstr_w
(
filenameW
));
GlobalUnlock
(
medium
.
hGlobal
);
ReleaseStgMedium
(
&
medium
);
IDataObject_Release
(
data_obj
);
ILFree
(
pidls
[
0
]);
/* Paste with nothing in the clipboard. */
hr
=
OleSetClipboard
(
NULL
);
ok
(
hr
==
S_OK
,
"Got hr %#lx.
\n
"
,
hr
);
invoke_info
.
lpVerb
=
"paste"
;
hr
=
IContextMenu_InvokeCommand
(
dst_menu
,
&
invoke_info
);
todo_wine
ok
(
hr
==
S_OK
||
hr
==
S_FALSE
/* win10 < 1809 */
,
"Got hr %#lx.
\n
"
,
hr
);
ret
=
RemoveDirectoryW
(
L"testcopy_src"
);
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
ret
=
RemoveDirectoryW
(
L"testcopy_dst"
);
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
ret
=
RemoveDirectoryW
(
L"testcopy_dst2"
);
ok
(
ret
,
"Got error %lu.
\n
"
,
GetLastError
());
IContextMenu_Release
(
src_menu
);
IContextMenu_Release
(
dst_menu
);
ILFree
(
src_pidl
);
ILFree
(
dst_pidl
);
IShellFolder_Release
(
dst_folder
);
IShellFolder_Release
(
tmp_folder
);
SetCurrentDirectoryW
(
cwd
);
}
START_TEST
(
shlfolder
)
{
init_function_pointers
();
...
...
@@ -5651,6 +5949,7 @@ START_TEST(shlfolder)
test_SHLimitInputEdit
();
test_SHGetSetFolderCustomSettings
();
test_SHOpenFolderAndSelectItems
();
test_copy_paste
();
OleUninitialize
();
}
include/shlobj.h
View file @
08219c02
...
...
@@ -77,6 +77,7 @@ typedef int GPFIDL_FLAGS;
WINSHELLAPI
void
WINAPI
SHFree
(
void
*
);
WINSHELLAPI
UINT
WINAPI
SHAddFromPropSheetExtArray
(
HPSXA
,
LPFNADDPROPSHEETPAGE
,
LPARAM
);
WINSHELLAPI
void
*
WINAPI
SHAlloc
(
ULONG
)
__WINE_ALLOC_SIZE
(
1
)
__WINE_DEALLOC
(
SHFree
)
__WINE_MALLOC
;
WINSHELLAPI
HRESULT
WINAPI
SHBindToObject
(
IShellFolder
*
,
const
ITEMIDLIST
*
,
IBindCtx
*
,
REFIID
,
void
**
);
WINSHELLAPI
HRESULT
WINAPI
SHCoCreateInstance
(
LPCWSTR
,
const
CLSID
*
,
IUnknown
*
,
REFIID
,
LPVOID
*
);
WINSHELLAPI
HPSXA
WINAPI
SHCreatePropSheetExtArray
(
HKEY
,
LPCWSTR
,
UINT
);
WINSHELLAPI
HPSXA
WINAPI
SHCreatePropSheetExtArrayEx
(
HKEY
,
LPCWSTR
,
UINT
,
IDataObject
*
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment