diff --git a/dlls/shell32/tests/shelllink.c b/dlls/shell32/tests/shelllink.c index c3f2104ee6a..8c88e8448f6 100644 --- a/dlls/shell32/tests/shelllink.c +++ b/dlls/shell32/tests/shelllink.c @@ -30,50 +30,506 @@ #include "winbase.h" #include "shlguid.h" #include "shobjidl.h" +#include "shlobj.h" #include "wine/test.h" -static void test_empty_shelllink() +static const WCHAR lnkfile[]= { 'C',':','\\','t','e','s','t','.','l','n','k',0 }; +static const WCHAR notafile[]= { 'C',':','\\','n','o','n','e','x','i','s','t','e','n','t','\\','f','i','l','e',0 }; + + +/* For some reason SHILCreateFromPath does not work on Win98 and + * SHSimpleIDListFromPathA does not work on NT4. But if we call both we + * get what we want on all platforms. + */ +static LPITEMIDLIST (WINAPI *pSHSimpleIDListFromPathA)(LPCSTR)=NULL; + +static LPITEMIDLIST path_to_pidl(const char* path) +{ + LPITEMIDLIST pidl; + + if (!pSHSimpleIDListFromPathA) + { + HMODULE hdll=LoadLibraryA("shell32.dll"); + pSHSimpleIDListFromPathA=(void*)GetProcAddress(hdll, (char*)162); + if (!pSHSimpleIDListFromPathA) + trace("SHSimpleIDListFromPathA not found in shell32.dll"); + } + + pidl=NULL; + if (pSHSimpleIDListFromPathA) + pidl=pSHSimpleIDListFromPathA(path); + + if (!pidl) + { + WCHAR* pathW; + HRESULT r; + int len; + + len=MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); + pathW=HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR)); + MultiByteToWideChar(CP_ACP, 0, path, -1, pathW, len); + + r=SHILCreateFromPath(pathW, &pidl, NULL); + todo_wine { + ok(SUCCEEDED(r), "SHILCreateFromPath failed (0x%08lx)\n", r); + } + HeapFree(GetProcessHeap(), 0, pathW); + } + return pidl; +} + + +/* + * Test manipulation of an IShellLink's properties. + */ + +static void test_get_set() { HRESULT r; - IShellLinkW *sl; - WCHAR buffer[0x100]; + IShellLinkA *sl; + char mypath[MAX_PATH]; + char buffer[INFOTIPSIZE]; + LPITEMIDLIST pidl, tmp_pidl; + char * str; + int i; + WORD w; + + r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkA, (LPVOID*)&sl); + ok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08lx)\n", r); + if (!SUCCEEDED(r)) + return; + + /* Test Getting / Setting the description */ + strcpy(buffer,"garbage"); + r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); + ok(SUCCEEDED(r), "GetDescription failed (0x%08lx)\n", r); + ok(*buffer=='\0', "GetDescription returned '%s'\n", buffer); + + str="Some description"; + r = IShellLinkA_SetDescription(sl, str); + ok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r); + + strcpy(buffer,"garbage"); + r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); + ok(SUCCEEDED(r), "GetDescription failed (0x%08lx)\n", r); + ok(lstrcmp(buffer,str)==0, "GetDescription returned '%s'\n", buffer); + + /* Test Getting / Setting the work directory */ + strcpy(buffer,"garbage"); + r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); + ok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08lx)\n", r); + ok(*buffer=='\0', "GetWorkingDirectory returned '%s'\n", buffer); + + str="c:\\nonexistent\\directory"; + r = IShellLinkA_SetWorkingDirectory(sl, str); + ok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r); + + strcpy(buffer,"garbage"); + r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); + ok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08lx)\n", r); + ok(lstrcmpi(buffer,str)==0, "GetWorkingDirectory returned '%s'\n", buffer); + + /* Test Getting / Setting the work directory */ + strcpy(buffer,"garbage"); + r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); + ok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r); + ok(*buffer=='\0', "GetPath returned '%s'\n", buffer); + + str="c:\\nonexistent\\file"; + r = IShellLinkA_SetPath(sl, str); + ok(SUCCEEDED(r), "SetPath failed (0x%08lx)\n", r); + + strcpy(buffer,"garbage"); + r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); + ok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r); + ok(lstrcmpi(buffer,str)==0, "GetPath returned '%s'\n", buffer); + + /* Get some a real path to play with */ + r=GetModuleFileName(NULL, mypath, sizeof(mypath)); + ok(r>=0 && rdescription) { - static const WCHAR lnk[]= { 'C',':','\\','t','e','s','t','.','l','n','k',0 }; - - buffer[0]='x'; - buffer[1]=0; - r = IShellLinkW_GetPath(sl, buffer, 0x100, NULL, SLGP_RAWPATH ); - ok (r == S_OK, "GetPath failed\n"); - ok (buffer[0]==0, "path wrong\n"); - - r = IShellLinkW_QueryInterface(sl, &IID_IPersistFile, (LPVOID*) &pf ); - ok (r == S_OK, "no IPersistFile\n"); - todo_wine - { - if (r == S_OK ) - { - r = IPersistFile_Save(pf, lnk, TRUE); - ok (r == S_OK, "save failed\n"); - IPersistFile_Release(pf); - } - - IShellLinkW_Release(sl); - - ok (DeleteFileW(lnk), "failed to delete link\n"); - } + r = IShellLinkA_SetDescription(sl, desc->description); + lok(SUCCEEDED(r), "SetDescription failed (0x%08lx)\n", r); } + if (desc->workdir) + { + r = IShellLinkA_SetWorkingDirectory(sl, desc->workdir); + lok(SUCCEEDED(r), "SetWorkingDirectory failed (0x%08lx)\n", r); + } + if (desc->path) + { + r = IShellLinkA_SetPath(sl, desc->path); + lok(SUCCEEDED(r), "SetPath failed (0x%08lx)\n", r); + } + if (desc->pidl) + { + r = IShellLinkA_SetIDList(sl, desc->pidl); + lok(SUCCEEDED(r), "SetIDList failed (0x%08lx)\n", r); + } + if (desc->arguments) + { + r = IShellLinkA_SetArguments(sl, desc->arguments); + lok(SUCCEEDED(r), "SetArguments failed (0x%08lx)\n", r); + } + if (desc->showcmd) + { + r = IShellLinkA_SetShowCmd(sl, desc->showcmd); + lok(SUCCEEDED(r), "SetShowCmd failed (0x%08lx)\n", r); + } + if (desc->icon) + { + r = IShellLinkA_SetIconLocation(sl, desc->icon, desc->icon_id); + lok(SUCCEEDED(r), "SetIconLocation failed (0x%08lx)\n", r); + } + if (desc->hotkey) + { + r = IShellLinkA_SetHotkey(sl, desc->hotkey); + lok(SUCCEEDED(r), "SetHotkey failed (0x%08lx)\n", r); + } + + r = IShellLinkW_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf); + lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r); + if (SUCCEEDED(r)) + { + r = IPersistFile_Save(pf, path, TRUE); + if (save_fails) + { + todo_wine { + lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r); + } + } + else + { + lok(SUCCEEDED(r), "save failed (0x%08lx)\n", r); + } + IPersistFile_Release(pf); + } + + IShellLinkA_Release(sl); +} + +static void check_lnk_(int line, const WCHAR* path, lnk_desc_t* desc) +{ + HRESULT r; + IShellLinkA *sl; + IPersistFile *pf; + char buffer[INFOTIPSIZE]; + + r = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, + &IID_IShellLinkA, (LPVOID*)&sl); + lok(SUCCEEDED(r), "no IID_IShellLinkA (0x%08lx)\n", r); + if (!SUCCEEDED(r)) + return; + + r = IShellLinkA_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf); + lok(SUCCEEDED(r), "no IID_IPersistFile (0x%08lx)\n", r); + if (!SUCCEEDED(r)) + { + IShellLinkA_Release(sl); + return; + } + + r = IPersistFile_Load(pf, path, STGM_READ); + todo_wine { + lok(SUCCEEDED(r), "load failed (0x%08lx)\n", r); + } + IPersistFile_Release(pf); + if (!SUCCEEDED(r)) + { + IShellLinkA_Release(sl); + return; + } + + if (desc->description) + { + strcpy(buffer,"garbage"); + r = IShellLinkA_GetDescription(sl, buffer, sizeof(buffer)); + lok(SUCCEEDED(r), "GetDescription failed (0x%08lx)\n", r); + lok(lstrcmp(buffer, desc->description)==0, + "GetDescription returned '%s' instead of '%s'\n", + buffer, desc->description); + } + if (desc->workdir) + { + strcpy(buffer,"garbage"); + r = IShellLinkA_GetWorkingDirectory(sl, buffer, sizeof(buffer)); + lok(SUCCEEDED(r), "GetWorkingDirectory failed (0x%08lx)\n", r); + lok(lstrcmpi(buffer, desc->workdir)==0, + "GetWorkingDirectory returned '%s' instead of '%s'\n", + buffer, desc->workdir); + } + if (desc->path) + { + strcpy(buffer,"garbage"); + r = IShellLinkA_GetPath(sl, buffer, sizeof(buffer), NULL, SLGP_RAWPATH); + lok(SUCCEEDED(r), "GetPath failed (0x%08lx)\n", r); + lok(lstrcmpi(buffer, desc->path)==0, + "GetPath returned '%s' instead of '%s'\n", + buffer, desc->path); + } + if (desc->pidl) + { + LPITEMIDLIST pidl=NULL; + r = IShellLinkA_GetIDList(sl, &pidl); + lok(SUCCEEDED(r), "GetIDList failed (0x%08lx)\n", r); + lok(ILIsEqual(pidl, desc->pidl), + "GetIDList returned an incorrect pidl\n"); + } + if (desc->showcmd) + { + int i=0xdeadbeef; + r = IShellLinkA_GetShowCmd(sl, &i); + lok(SUCCEEDED(r), "GetShowCmd failed (0x%08lx)\n", r); + lok(i==desc->showcmd, + "GetShowCmd returned 0x%0x instead of 0x%0x\n", + i, desc->showcmd); + } + if (desc->icon) + { + int i=0xdeadbeef; + strcpy(buffer,"garbage"); + r = IShellLinkA_GetIconLocation(sl, buffer, sizeof(buffer), &i); + lok(SUCCEEDED(r), "GetIconLocation failed (0x%08lx)\n", r); + lok(lstrcmpi(buffer, desc->icon)==0, + "GetIconLocation returned '%s' instead of '%s'\n", + buffer, desc->icon); + lok(i==desc->icon_id, + "GetIconLocation returned 0x%0x instead of 0x%0x\n", + i, desc->icon_id); + } + if (desc->hotkey) + { + WORD i=0xbeef; + r = IShellLinkA_GetHotkey(sl, &i); + lok(SUCCEEDED(r), "GetHotkey failed (0x%08lx)\n", r); + lok(i==desc->hotkey, + "GetHotkey returned 0x%04x instead of 0x%04x\n", + i, desc->hotkey); + } + + IShellLinkA_Release(sl); +} + +static void test_load_save() +{ + lnk_desc_t desc; + char mypath[MAX_PATH]; + char mydir[MAX_PATH]; + char* p; + DWORD r; + + /* Save an empty .lnk file */ + memset(&desc, 0, sizeof(desc)); + create_lnk(lnkfile, &desc, 1); + + /* It should come back as a bunch of empty strings */ + desc.description=""; + desc.workdir=""; + desc.path=""; + desc.arguments=""; + desc.icon=""; + check_lnk(lnkfile, &desc); + + + /* Point a .lnk file to nonexistent files */ + desc.description=""; + desc.workdir="c:\\Nonexitent\\work\\directory"; + desc.path="c:\\nonexistent\\path"; + desc.pidl=NULL; + desc.arguments=""; + desc.showcmd=0; + desc.icon="c:\\nonexistent\\icon\\file"; + desc.icon_id=1234; + desc.hotkey=0; + create_lnk(lnkfile, &desc, 0); + check_lnk(lnkfile, &desc); + + r=GetModuleFileName(NULL, mypath, sizeof(mypath)); + ok(r>=0 && r