Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413/* * PROJECT: ReactOS api tests * LICENSE: LGPLv2.1+ - See COPYING.LIB in the top level directory * PURPOSE: Test for Drag & Drop * PROGRAMMER: Katayama Hirofumi MZ <katayama.hirofumi.mz@gmail.com> */
#include "shelltest.h"#include <shlwapi.h>
#define NDEBUG#include <debug.h>#include <stdio.h>
#define TESTFILENAME L"DragDropTest.txt"#define DROPPED_ON_FILE L"DragDroppedOn.lnk"
static CComPtr<IShellFolder> s_pDesktop;
static WCHAR s_szSrcTestFile[MAX_PATH];static WCHAR s_szDestFolder[MAX_PATH];static WCHAR s_szDestTestFile[MAX_PATH];static WCHAR s_szDestLinkSpec[MAX_PATH];static WCHAR s_szDroppedToItem[MAX_PATH];
enum OP{ OP_NONE, OP_COPY, OP_MOVE, OP_LINK, OP_NONE_OR_COPY, OP_NONE_OR_MOVE, OP_NONE_OR_LINK};
#define D_NONE DROPEFFECT_NONE#define D_COPY DROPEFFECT_COPY#define D_MOVE DROPEFFECT_MOVE#define D_LINK DROPEFFECT_LINK#define D_NONE_OR_COPY 0xAABBCCDD#define D_NONE_OR_MOVE 0x11223344#define D_NONE_OR_LINK 0x55667788
struct TEST_ENTRY{ int line; OP op; HRESULT hr1; HRESULT hr2; DWORD dwKeyState; DWORD dwEffects1; DWORD dwEffects2; DWORD dwEffects3;};
static const TEST_ENTRY s_TestEntries[] ={ // MK_LBUTTON { __LINE__, OP_NONE, S_OK, S_OK, MK_LBUTTON, D_NONE, D_NONE, D_NONE }, { __LINE__, OP_COPY, S_OK, S_OK, MK_LBUTTON, D_COPY, D_COPY, D_COPY }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON, D_COPY | D_MOVE, D_MOVE, D_NONE }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON, D_COPY | D_MOVE | D_LINK, D_MOVE, D_NONE }, { __LINE__, OP_COPY, S_OK, S_OK, MK_LBUTTON, D_COPY | D_LINK, D_COPY, D_COPY }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON, D_MOVE, D_MOVE, D_NONE }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON, D_MOVE | D_LINK, D_MOVE, D_NONE }, { __LINE__, OP_LINK, S_OK, S_OK, MK_LBUTTON, D_LINK, D_LINK, D_LINK },
// MK_LBUTTON | MK_SHIFT { __LINE__, OP_NONE, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_NONE, D_NONE, D_NONE }, { __LINE__, OP_NONE_OR_COPY, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_COPY, D_NONE_OR_COPY, D_NONE_OR_COPY }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_COPY | D_MOVE, D_MOVE, D_NONE }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_COPY | D_MOVE | D_LINK, D_MOVE, D_NONE }, { __LINE__, OP_NONE_OR_COPY, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_COPY | D_LINK, D_NONE_OR_COPY, D_NONE_OR_COPY }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_MOVE, D_MOVE, D_NONE }, { __LINE__, OP_MOVE, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_MOVE | D_LINK, D_MOVE, D_NONE }, { __LINE__, OP_NONE_OR_LINK, S_OK, S_OK, MK_LBUTTON | MK_SHIFT, D_LINK, D_NONE_OR_LINK, D_NONE_OR_LINK },
// MK_LBUTTON | MK_SHIFT | MK_CONTROL#define MK_LBUTTON_SHIFT_CTRL (MK_LBUTTON | MK_SHIFT | MK_CONTROL) { __LINE__, OP_NONE, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_NONE, D_NONE, D_NONE }, { __LINE__, OP_NONE_OR_COPY, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_COPY, D_NONE_OR_COPY, D_NONE_OR_COPY }, { __LINE__, OP_NONE_OR_COPY, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_COPY | D_MOVE, D_NONE_OR_COPY, D_NONE_OR_COPY }, { __LINE__, OP_LINK, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_COPY | D_MOVE | D_LINK, D_LINK, D_LINK }, { __LINE__, OP_LINK, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_COPY | D_LINK, D_LINK, D_LINK }, { __LINE__, OP_NONE_OR_MOVE, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_MOVE, D_NONE_OR_MOVE, D_NONE }, { __LINE__, OP_LINK, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_MOVE | D_LINK, D_LINK, D_LINK }, { __LINE__, OP_LINK, S_OK, S_OK, MK_LBUTTON_SHIFT_CTRL, D_LINK, D_LINK, D_LINK },#undef MK_LBUTTON_SHIFT_CTRL
// MK_LBUTTON | MK_CONTROL { __LINE__, OP_NONE, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_NONE, D_NONE, D_NONE }, { __LINE__, OP_COPY, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_COPY, D_COPY, D_COPY }, { __LINE__, OP_COPY, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_COPY | D_MOVE, D_COPY, D_COPY }, { __LINE__, OP_COPY, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_COPY | D_MOVE | D_LINK, D_COPY, D_COPY }, { __LINE__, OP_COPY, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_COPY | D_LINK, D_COPY, D_COPY }, { __LINE__, OP_NONE_OR_MOVE, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_MOVE, D_NONE_OR_MOVE, D_NONE }, { __LINE__, OP_NONE_OR_MOVE, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_MOVE | D_LINK, D_NONE_OR_MOVE, D_NONE }, { __LINE__, OP_NONE_OR_LINK, S_OK, S_OK, MK_LBUTTON | MK_CONTROL, D_LINK, D_NONE_OR_LINK, D_NONE_OR_LINK },};
static void DoCreateTestFile(LPCWSTR pszFileName){ FILE *fp = _wfopen(pszFileName, L"wb"); ok(fp != NULL, "fp is NULL for '%S'\n", pszFileName); fclose(fp);}
HRESULT DoCreateShortcut( LPCWSTR pszLnkFileName, LPCWSTR pszTargetPathName){ CComPtr<IPersistFile> ppf; CComPtr<IShellLinkW> psl; HRESULT hr;
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLinkW, (LPVOID *)&psl); if (SUCCEEDED(hr)) { psl->SetPath(pszTargetPathName);
hr = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf); if (SUCCEEDED(hr)) { hr = ppf->Save(pszLnkFileName, TRUE); } }
return hr;}
static HRESULTGetUIObjectOfAbsPidl(PIDLIST_ABSOLUTE pidl, REFIID riid, LPVOID *ppvOut){ *ppvOut = NULL;
LPCITEMIDLIST pidlLast; CComPtr<IShellFolder> psf; HRESULT hr = SHBindToParent(pidl, IID_IShellFolder, (LPVOID *)&psf, &pidlLast); if (FAILED(hr)) return hr;
hr = psf->GetUIObjectOf(NULL, 1, &pidlLast, riid, NULL, ppvOut); return hr;}
static HRESULTGetUIObjectOfPath(LPCWSTR pszPath, REFIID riid, LPVOID *ppvOut){ *ppvOut = NULL;
PIDLIST_ABSOLUTE pidl = ILCreateFromPathW(pszPath); if (!pidl) return E_FAIL;
HRESULT hr = GetUIObjectOfAbsPidl(pidl, riid, ppvOut);
CoTaskMemFree(pidl);
return hr;}
BOOL DoSpecExistsW(LPCWSTR pszSpec){ WIN32_FIND_DATAW find; HANDLE hFind = FindFirstFileW(pszSpec, &find); if (hFind != INVALID_HANDLE_VALUE) { FindClose(hFind); return TRUE; } return FALSE;}
void DoDeleteSpecW(LPCWSTR pszSpec){ WCHAR szPath[MAX_PATH], szFile[MAX_PATH]; lstrcpyW(szPath, pszSpec); PathRemoveFileSpecW(szPath);
WIN32_FIND_DATAW find; HANDLE hFind = FindFirstFileW(pszSpec, &find); if (hFind != INVALID_HANDLE_VALUE) { do { lstrcpyW(szFile, szPath); PathAppendW(szFile, find.cFileName); DeleteFileW(szFile); } while (FindNextFileW(hFind, &find));
FindClose(hFind); }}
static void DoTestEntry(const TEST_ENTRY *pEntry){ int line = pEntry->line; HRESULT hr; PIDLIST_ABSOLUTE pidlDesktop = NULL; CComPtr<IDropTarget> pDropTarget; CComPtr<IDataObject> pDataObject;
// get the desktop PIDL SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &pidlDesktop); ok(!!pidlDesktop, "pidlDesktop is NULL\n");
// build paths // SHGetPathFromIDListW(pidlDesktop, s_szDroppedToItem); PathAppendW(s_szDroppedToItem, DROPPED_ON_FILE);
GetModuleFileNameW(NULL, s_szSrcTestFile, _countof(s_szSrcTestFile)); PathRemoveFileSpecW(s_szSrcTestFile); PathAppendW(s_szSrcTestFile, TESTFILENAME);
lstrcpyW(s_szDestTestFile, s_szDestFolder); PathAppendW(s_szDestTestFile, TESTFILENAME);
lstrcpyW(s_szDestLinkSpec, s_szDestFolder); PathAppendW(s_szDestLinkSpec, L"*DragDropTest*.lnk");
//trace("s_szSrcTestFile: '%S'\n", s_szSrcTestFile); //trace("s_szDestTestFile: '%S'\n", s_szDestTestFile); //trace("s_szDestLinkSpec: '%S'\n", s_szDestLinkSpec); //trace("s_szDroppedToItem: '%S'\n", s_szDroppedToItem);
// create or delete files // DoCreateTestFile(s_szSrcTestFile); DeleteFileW(s_szDestTestFile); DoDeleteSpecW(s_szDestLinkSpec); DeleteFileW(s_szDroppedToItem); DoCreateShortcut(s_szDroppedToItem, s_szDestFolder);
// check file existence // ok(PathIsDirectoryW(s_szDestFolder), "s_szDestFolder is not directory\n"); ok(PathFileExistsW(s_szSrcTestFile), "s_szSrcTestFile doesn't exist\n"); ok(!DoSpecExistsW(s_szDestLinkSpec), "s_szDestLinkSpec doesn't exist\n"); ok(!PathFileExistsW(s_szDestTestFile), "s_szDestTestFile exists\n");
// get an IDataObject pDataObject = NULL; hr = GetUIObjectOfPath(s_szSrcTestFile, IID_IDataObject, (LPVOID *)&pDataObject); ok_long(hr, S_OK);
// get an IDropTarget CComPtr<IEnumIDList> pEnumIDList; PIDLIST_ABSOLUTE pidl = NULL; hr = s_pDesktop->EnumObjects(NULL, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS, &pEnumIDList); ok_long(hr, S_OK); while (pEnumIDList->Next(1, &pidl, NULL) == S_OK) { WCHAR szText[MAX_PATH]; SHGetPathFromIDListW(pidl, szText); if (wcsstr(szText, DROPPED_ON_FILE) != NULL) { break; } CoTaskMemFree(pidl); pidl = NULL; } ok(pidl != NULL, "Line %d: pidl is NULL\n", line); pDropTarget = NULL; PITEMID_CHILD pidlLast = ILFindLastID(pidl); hr = s_pDesktop->GetUIObjectOf(NULL, 1, &pidlLast, IID_IDropTarget, NULL, (LPVOID *)&pDropTarget); CoTaskMemFree(pidl); ok_long(hr, S_OK);
if (!pDropTarget) { skip("Line %d: pDropTarget was NULL\n", line);
// clean up DeleteFileW(s_szSrcTestFile); DeleteFileW(s_szDestTestFile); DoDeleteSpecW(s_szDestLinkSpec); ILFree(pidlDesktop);
return; }
// DragEnter POINTL ptl = { 0, 0 }; DWORD dwKeyState = pEntry->dwKeyState; DWORD dwEffects = pEntry->dwEffects1; hr = pDropTarget->DragEnter(pDataObject, dwKeyState, ptl, &dwEffects);
ok(hr == pEntry->hr1, "Line %d: hr1 was %08lX\n", line, hr);
switch (pEntry->dwEffects2) { case D_NONE_OR_COPY: ok((dwEffects == D_NONE || dwEffects == D_COPY), "Line %d: dwEffects2 was %08lX\n", line, dwEffects); break; case D_NONE_OR_MOVE: ok((dwEffects == D_NONE || dwEffects == D_MOVE), "Line %d: dwEffects2 was %08lX\n", line, dwEffects); break; case D_NONE_OR_LINK: ok((dwEffects == D_NONE || dwEffects == D_LINK), "Line %d: dwEffects2 was %08lX\n", line, dwEffects); break; default: ok(dwEffects == pEntry->dwEffects2, "Line %d: dwEffects2 was %08lX\n", line, dwEffects); break; }
// Drop hr = pDropTarget->Drop(pDataObject, dwKeyState, ptl, &dwEffects); ok(hr == pEntry->hr2, "Line %d: hr2 was %08lX\n", line, hr);
switch (pEntry->dwEffects3) { case D_NONE_OR_COPY: ok((dwEffects == D_NONE || dwEffects == D_COPY), "Line %d: dwEffects3 was %08lX\n", line, dwEffects); break; case D_NONE_OR_MOVE: ok((dwEffects == D_NONE || dwEffects == D_MOVE), "Line %d: dwEffects3 was %08lX\n", line, dwEffects); break; case D_NONE_OR_LINK: ok((dwEffects == D_NONE || dwEffects == D_LINK), "Line %d: dwEffects3 was %08lX\n", line, dwEffects); break; default: ok(dwEffects == pEntry->dwEffects3, "Line %d: dwEffects3 was %08lX\n", line, dwEffects); break; }
// check file existence by pEntry->op switch (pEntry->op) { case OP_NONE: ok(PathFileExistsW(s_szSrcTestFile), "Line %d: src not exists\n", line); ok(!PathFileExistsW(s_szDestTestFile), "Line %d: dest exists\n", line); ok(!DoSpecExistsW(s_szDestLinkSpec), "Line %d: link exists\n", line); break; case OP_COPY: ok(PathFileExistsW(s_szSrcTestFile), "Line %d: src not exists\n", line); ok(PathFileExistsW(s_szDestTestFile), "Line %d: dest not exists\n", line); ok(!DoSpecExistsW(s_szDestLinkSpec), "Line %d: link exists\n", line); break; case OP_MOVE: ok(!PathFileExistsW(s_szSrcTestFile), "Line %d: src exists\n", line); ok(PathFileExistsW(s_szDestTestFile), "Line %d: dest not exists\n", line); ok(!DoSpecExistsW(s_szDestLinkSpec), "Line %d: link exists\n", line); break; case OP_LINK: ok(PathFileExistsW(s_szSrcTestFile), "Line %d: src not exists\n", line); ok(!PathFileExistsW(s_szDestTestFile), "Line %d: dest not exists\n", line); ok(DoSpecExistsW(s_szDestLinkSpec), "Line %d: link not exists\n", line); break; case OP_NONE_OR_COPY: ok(PathFileExistsW(s_szSrcTestFile), "Line %d: src not exists\n", line); ok(!DoSpecExistsW(s_szDestLinkSpec), "Line %d: link exists\n", line); break; case OP_NONE_OR_MOVE: ok(PathFileExistsW(s_szSrcTestFile) != PathFileExistsW(s_szDestTestFile), "Line %d: It must be either None or Move\n", line); break; case OP_NONE_OR_LINK: ok(PathFileExistsW(s_szSrcTestFile), "Line %d: src not exists\n", line); ok(!PathFileExistsW(s_szDestTestFile), "Line %d: dest not exists\n", line); break; }
// clean up DeleteFileW(s_szSrcTestFile); DeleteFileW(s_szDestTestFile); DoDeleteSpecW(s_szDestLinkSpec); ILFree(pidlDesktop);}
START_TEST(DragDrop){ if (!winetest_interactive) { skip("Skipping the test due to crash. CORE-17057\n"); return; }
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); ok_int(SUCCEEDED(hr), TRUE);
SHGetDesktopFolder(&s_pDesktop); ok(!!s_pDesktop, "s_pDesktop is NULL\n");
BOOL ret = SHGetSpecialFolderPathW(NULL, s_szDestFolder, CSIDL_DESKTOP, FALSE); ok_int(ret, TRUE);
for (size_t i = 0; i < _countof(s_TestEntries); ++i) { DoTestEntry(&s_TestEntries[i]); }
DeleteFileW(s_szSrcTestFile); DeleteFileW(s_szDestTestFile); DoDeleteSpecW(s_szDestLinkSpec); DeleteFileW(s_szDroppedToItem);
CoUninitialize();}