#include <debug.h>
#include <shellutils.h>
-typedef
-struct _TestShellLinkDef
+/* Test IShellLink::SetPath with environment-variables, existing, non-existing, ...*/
+typedef struct
{
- const WCHAR* pathIn;
+ PCWSTR pathIn;
HRESULT hrSetPath;
+
/* Test 1 - hrGetPathX = IShellLink::GetPath(pathOutX, ... , flagsX); */
- const WCHAR* pathOut1;
+ PCWSTR pathOut1;
DWORD flags1;
HRESULT hrGetPath1;
- bool expandPathOut1;
+ BOOL expandPathOut1;
+
/* Test 2 */
- const WCHAR* pathOut2;
+ PCWSTR pathOut2;
DWORD flags2;
HRESULT hrGetPath2;
- bool expandPathOut2;
-} TestShellLinkDef;
+ BOOL expandPathOut2;
+} TEST_SHELL_LINK_DEF;
-/* Test IShellLink::SetPath with environment-variables, existing, non-existing, ...*/
-static struct _TestShellLinkDef linkTestList[] =
+static TEST_SHELL_LINK_DEF linkTestList[] =
{
{
L"%comspec%", S_OK,
},
{
L"%anyvar%", E_INVALIDARG,
- L"", SLGP_SHORTPATH, ERROR_INVALID_FUNCTION, FALSE,
- L"", SLGP_RAWPATH, ERROR_INVALID_FUNCTION, FALSE
+ L"", SLGP_SHORTPATH, S_FALSE, FALSE,
+ L"", SLGP_RAWPATH, S_FALSE, FALSE
},
{
L"%anyvar%%comspec%", S_OK,
},
{
L"non-existent-file", E_INVALIDARG,
- L"", SLGP_SHORTPATH, ERROR_INVALID_FUNCTION, FALSE,
- L"", SLGP_RAWPATH, ERROR_INVALID_FUNCTION, FALSE
+ L"", SLGP_SHORTPATH, S_FALSE, FALSE,
+ L"", SLGP_RAWPATH, S_FALSE, FALSE
},
- { NULL, 0, NULL, 0, 0, NULL, 0, 0 }
};
-static const UINT evVarChLen = 255;
-static WCHAR evVar[evVarChLen];
-
static
VOID
-test_checklinkpath(TestShellLinkDef* testDef)
+test_checklinkpath(UINT i, TEST_SHELL_LINK_DEF* testDef)
{
+static WCHAR evVar[MAX_PATH];
+
HRESULT hr, expectedHr;
- WCHAR wPathOut[255];
- bool expandPathOut;
- const WCHAR* expectedPathOut;
+ WCHAR wPathOut[MAX_PATH];
+ BOOL expandPathOut;
+ PCWSTR expectedPathOut;
IShellLinkW *psl;
UINT i1;
DWORD flags;
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARG(IShellLinkW, &psl));
- ok(hr == S_OK, "CoCreateInstance, hr = %lx\n", hr);
+ ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
if (FAILED(hr))
{
skip("Could not instantiate CShellLink\n");
}
hr = psl->SetPath(testDef->pathIn);
- ok(hr == testDef->hrSetPath, "IShellLink::SetPath, got hr = %lx, expected %lx\n", hr, testDef->hrSetPath);
+ ok(hr == testDef->hrSetPath, "IShellLink::SetPath(%d), got hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrSetPath);
expectedPathOut = NULL;
- for (i1 = 0; i1 <= 1; i1++ )
+ for (i1 = 0; i1 <= 1; i1++)
{
- if (i1 == 1)
+ if (i1 == 1) /* Usually SLGP_RAWPATH */
{
flags = testDef->flags1;
expandPathOut = testDef->expandPathOut1;
expectedPathOut = testDef->pathOut1;
expectedHr = testDef->hrGetPath1;
}
- else
+ else /* Usually SLGP_SHORTPATH */
{
flags = testDef->flags2;
expandPathOut = testDef->expandPathOut2;
}
/* Patch some variables */
- if (expandPathOut == TRUE)
+ if (expandPathOut)
{
- ExpandEnvironmentStringsW(expectedPathOut,evVar,evVarChLen);
+ ExpandEnvironmentStringsW(expectedPathOut, evVar, _countof(evVar));
DPRINT("** %S **\n",evVar);
expectedPathOut = evVar;
}
- hr = psl->GetPath(wPathOut,sizeof(wPathOut),NULL,flags);
+ hr = psl->GetPath(wPathOut, _countof(wPathOut), NULL, flags);
ok(hr == expectedHr,
- "IShellLink::GetPath, flags %lx, got hr = %lx, expected %lx\n",
- flags, hr, expectedHr);
- ok(wcsicmp(wPathOut,expectedPathOut) == 0,
- "IShellLink::GetPath, flags %lx, in %S, got %S, expected %S\n",
- flags,testDef->pathIn,wPathOut,expectedPathOut);
+ "IShellLink::GetPath(%d), flags 0x%lx, got hr = 0x%lx, expected 0x%lx\n",
+ i, flags, hr, expectedHr);
+ ok(wcsicmp(wPathOut, expectedPathOut) == 0,
+ "IShellLink::GetPath(%d), flags 0x%lx, in %S, got %S, expected %S\n",
+ i, flags, testDef->pathIn, wPathOut, expectedPathOut);
}
psl->Release();
VOID
TestShellLink(void)
{
- TestShellLinkDef *testDef;
- UINT i1 = 0;
+ UINT i;
- /* needed for test */
- SetEnvironmentVariableW(L"shell",L"cmd.exe");
+ /* Needed for test */
+ SetEnvironmentVariableW(L"shell", L"cmd.exe");
- testDef = &linkTestList[i1];
- while (testDef->pathIn != NULL)
+ for (i = 0; i < _countof(linkTestList); ++i)
{
-
- DPRINT("IShellLink-Test: %S\n", testDef->pathIn);
- test_checklinkpath(testDef);
- i1++;
- testDef = &linkTestList[i1];
+ DPRINT("IShellLink-Test(%d): %S\n", i, linkTestList[i].pathIn);
+ test_checklinkpath(i, &linkTestList[i]);
}
SetEnvironmentVariableW(L"shell",NULL);
}
+static
+VOID
+TestDescription(void)
+{
+ HRESULT hr;
+ IShellLinkW *psl;
+ WCHAR buffer[64];
+ PCWSTR testDescription = L"This is a test description";
+
+ /* Test SetDescription */
+ hr = CoCreateInstance(CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARG(IShellLinkW, &psl));
+ ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
+ if (FAILED(hr))
+ {
+ skip("Could not instantiate CShellLink\n");
+ return;
+ }
+
+ memset(buffer, 0x55, sizeof(buffer));
+ hr = psl->GetDescription(buffer, RTL_NUMBER_OF(buffer));
+ ok(hr == S_OK, "IShellLink::GetDescription returned hr = 0x%lx\n", hr);
+ ok(buffer[0] == 0, "buffer[0] = %x\n", buffer[0]);
+ ok(buffer[1] == 0x5555, "buffer[1] = %x\n", buffer[1]);
+
+ hr = psl->SetDescription(testDescription);
+ ok(hr == S_OK, "IShellLink::SetDescription returned hr = 0x%lx\n", hr);
+
+ memset(buffer, 0x55, sizeof(buffer));
+ hr = psl->GetDescription(buffer, RTL_NUMBER_OF(buffer));
+ ok(hr == S_OK, "IShellLink::GetDescription returned hr = 0x%lx\n", hr);
+ ok(buffer[wcslen(testDescription)] == 0, "buffer[n] = %x\n", buffer[wcslen(testDescription)]);
+ ok(buffer[wcslen(testDescription) + 1] == 0x5555, "buffer[n+1] = %x\n", buffer[wcslen(testDescription) + 1]);
+ ok(!wcscmp(buffer, testDescription), "buffer = '%ls'\n", buffer);
+
+ hr = psl->SetDescription(NULL);
+ ok(hr == S_OK, "IShellLink::SetDescription returned hr = 0x%lx\n", hr);
+
+ memset(buffer, 0x55, sizeof(buffer));
+ hr = psl->GetDescription(buffer, RTL_NUMBER_OF(buffer));
+ ok(hr == S_OK, "IShellLink::GetDescription returned hr = 0x%lx\n", hr);
+ ok(buffer[0] == 0, "buffer[0] = %x\n", buffer[0]);
+ ok(buffer[1] == 0x5555, "buffer[1] = %x\n", buffer[1]);
+
+ psl->Release();
+}
+
+
+/* Test IShellLink::Get/SetIconLocation and IExtractIcon::GetIconLocation */
+typedef struct
+{
+ PCWSTR FilePath;
+
+ /* Expected results */
+ HRESULT hrDefIcon; // Return value for GIL_DEFAULTICON
+ HRESULT hrForShrt; // Return value for GIL_FORSHORTCUT
+ /* Return values for GIL_FORSHELL */
+ HRESULT hrForShell;
+ PCWSTR IconPath;
+ UINT Flags;
+} TEST_SHELL_ICON;
+
+static TEST_SHELL_ICON ShIconTests[] =
+{
+ /* Executable with icons */
+ {L"%SystemRoot%\\system32\\cmd.exe", S_FALSE, E_INVALIDARG,
+ S_OK, L"%SystemRoot%\\system32\\cmd.exe", GIL_NOTFILENAME | GIL_PERINSTANCE},
+
+ /* Executable without icon */
+ {L"%SystemRoot%\\system32\\autochk.exe", S_FALSE, E_INVALIDARG,
+ S_OK, L"%SystemRoot%\\system32\\autochk.exe", GIL_NOTFILENAME | GIL_PERINSTANCE},
+
+ /* Existing file */
+ {L"%SystemRoot%\\system32\\shell32.dll", S_FALSE, E_INVALIDARG,
+ S_OK, L"%SystemRoot%\\system32\\shell32.dll", GIL_NOTFILENAME | GIL_PERCLASS},
+
+ /* Non-existing file */
+ {L"c:\\non-existent-path\\non-existent-file.sdf", S_FALSE, E_INVALIDARG,
+ S_OK, L"c:\\non-existent-path\\non-existent-file.sdf", GIL_NOTFILENAME | GIL_PERCLASS},
+};
+
+static
+VOID
+test_iconlocation(UINT i, TEST_SHELL_ICON* testDef)
+{
+ HRESULT hr;
+ IShellLinkW *psl;
+ IExtractIconW *pei;
+ INT iIcon;
+ UINT wFlags;
+ WCHAR szPath[MAX_PATH];
+
+ hr = CoCreateInstance(CLSID_ShellLink,
+ NULL,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARG(IShellLinkW, &psl));
+ ok(hr == S_OK, "CoCreateInstance, hr = 0x%lx\n", hr);
+ if (FAILED(hr))
+ {
+ skip("Could not instantiate CShellLink\n");
+ return;
+ }
+
+ /* Set the path to a file */
+ ExpandEnvironmentStringsW(testDef->FilePath, szPath, _countof(szPath));
+ hr = psl->SetPath(szPath);
+ ok(hr == S_OK, "IShellLink::SetPath failed, hr = 0x%lx\n", hr);
+
+ /*
+ * This test shows that this does not imply that the icon is automatically
+ * set and be retrieved naively by a call to IShellLink::GetIconLocation.
+ */
+ iIcon = 0xdeadbeef;
+ wcscpy(szPath, L"garbage");
+ hr = psl->GetIconLocation(szPath, _countof(szPath), &iIcon);
+ ok(hr == S_OK, "IShellLink::GetIconLocation(%d) failed, hr = 0x%lx\n", i, hr);
+ ok(*szPath == L'\0', "IShellLink::GetIconLocation(%d) returned '%S'\n", i, szPath);
+ ok(iIcon == 0, "IShellLink::GetIconLocation(%d) returned %d\n", i, iIcon);
+
+ /* Try to grab the IExtractIconW interface */
+ hr = psl->QueryInterface(IID_PPV_ARG(IExtractIconW, &pei));
+ ok(hr == S_OK, "IShellLink::QueryInterface(IExtractIconW)(%d) failed, hr = 0x%lx\n", i, hr);
+ if (!pei)
+ {
+ win_skip("No IExtractIconW interface\n");
+ psl->Release();
+ return;
+ }
+
+ iIcon = wFlags = 0xdeadbeef;
+ wcscpy(szPath, L"garbage");
+ hr = pei->GetIconLocation(GIL_DEFAULTICON, szPath, _countof(szPath), &iIcon, &wFlags);
+ ok(hr == testDef->hrDefIcon, "IShellLink::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrDefIcon);
+ ok(*szPath == L'\0', "IShellLink::GetIconLocation(%d) returned '%S'\n", i, szPath);
+ // ok(iIcon == 0, "IShellLink::GetIconLocation(%d) returned %d\n", i, iIcon);
+
+ iIcon = wFlags = 0xdeadbeef;
+ wcscpy(szPath, L"garbage");
+ hr = pei->GetIconLocation(GIL_FORSHORTCUT, szPath, _countof(szPath), &iIcon, &wFlags);
+ ok(hr == testDef->hrForShrt, "IShellLink::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrForShrt);
+ // Here, both szPath and iIcon are untouched...
+
+ iIcon = wFlags = 0xdeadbeef;
+ wcscpy(szPath, L"garbage");
+ hr = pei->GetIconLocation(GIL_FORSHELL, szPath, _countof(szPath), &iIcon, &wFlags);
+ ok(hr == testDef->hrForShell, "IShellLink::GetIconLocation(%d) returned hr = 0x%lx, expected 0x%lx\n", i, hr, testDef->hrForShell);
+ ok(wFlags == testDef->Flags, "IShellLink::GetIconLocation(%d) returned wFlags = 0x%lx, expected 0x%lx\n", i, wFlags, testDef->Flags);
+ // ok(*szPath == L'\0', "IShellLink::GetIconLocation returned '%S'\n", szPath);
+ // ok(iIcon == 0, "IShellLink::GetIconLocation returned %d\n", iIcon);
+ // ok(FALSE, "hr = 0x%lx, szPath = '%S', iIcon = %d, wFlags = %d\n", hr, szPath, iIcon, wFlags);
+
+ /* Release the interfaces */
+ pei->Release();
+ psl->Release();
+}
+
+static
+VOID
+TestIconLocation(void)
+{
+ UINT i;
+
+ for (i = 0; i < _countof(ShIconTests); ++i)
+ {
+ test_iconlocation(i, &ShIconTests[i]);
+ }
+}
+
START_TEST(CShellLink)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
TestShellLink();
+ TestDescription();
+ TestIconLocation();
+
+ CoUninitialize();
}