2 * Implementation of hyperlinking (hlink.dll)
4 * Copyright 2006 Mike McCormack
5 * Copyright 2007 Jacek Caban for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/test.h"
31 static const char *debugstr_w(LPCWSTR str)
33 static char buf[1024];
36 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
40 static void test_HlinkIsShortcut(void)
45 static const WCHAR file0[] = {'f','i','l','e',0};
46 static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
47 static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
48 static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
49 static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
50 static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
51 static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
52 static const WCHAR file7[] = {'.','u','r','l',0};
69 for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
70 hres = HlinkIsShortcut(shortcut_test[i].file);
71 ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
72 i, hres, shortcut_test[i].hres);
76 static void test_reference(void)
81 const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
82 const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
85 r = HlinkCreateFromString(url, NULL, NULL, NULL,
86 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
87 ok(r == S_OK, "failed to create link\n");
91 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
92 ok(r == S_OK, "failed\n");
94 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
95 ok(r == S_OK, "failed\n");
96 ok(mk != NULL, "no moniker\n");
97 ok(str == NULL, "string should be null\n");
99 r = IMoniker_Release(mk);
100 ok( r == 1, "moniker refcount wrong\n");
102 r = IHlink_GetStringReference(lnk, -1, &str, NULL);
103 ok(r == S_OK, "failed\n");
106 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
107 ok(r == S_OK, "failed\n");
109 ok(!lstrcmpW(str, url2), "url wrong\n");
113 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
114 ok(r == S_OK, "failed\n");
116 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
117 ok(r == S_OK, "failed\n");
118 ok(str == NULL, "string should be null\n");
124 static const unsigned char expected_hlink_data[] =
126 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
127 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
128 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
129 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
130 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
131 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
132 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
133 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
137 /* url + friendly name */
138 static const unsigned char expected_hlink_data2[] =
140 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
141 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
142 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
143 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
144 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
145 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
146 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
147 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
148 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
149 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
150 0x67,0x00,0x2f,0x00,0x00,0x00,
153 /* url + friendly name + location */
154 static const unsigned char expected_hlink_data3[] =
156 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
157 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
158 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
159 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
160 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
161 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
162 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
163 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
164 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
165 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
166 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
167 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
168 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
172 static const unsigned char expected_hlink_data4[] =
174 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
175 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
176 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
177 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
178 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
179 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
180 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
181 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
182 0x00,0x00,0x00,0x00,0x00,
185 /* url + target frame name */
186 static const unsigned char expected_hlink_data5[] =
188 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
189 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
190 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
191 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
192 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
193 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
194 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
195 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
196 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
197 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
202 static const unsigned char expected_hlink_data6[] =
204 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
205 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
206 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
207 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
208 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
209 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
210 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
211 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
212 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
216 static void test_persist_save_data(const char *testname, IHlink *lnk,
217 const unsigned char *expected_data,
218 unsigned int expected_data_size)
225 const unsigned char *data;
229 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
230 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
232 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
233 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
235 hr = IPersistStream_Save(ps, stream, TRUE);
236 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
238 hr = GetHGlobalFromStream(stream, &hglobal);
239 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
241 data_size = GlobalSize(hglobal);
243 data = GlobalLock(hglobal);
245 /* first check we have the right amount of data */
246 ok(data_size == expected_data_size,
247 "%s: Size of saved data differs (expected %d, actual %d)\n",
248 testname, expected_data_size, data_size);
251 /* then do a byte-by-byte comparison */
252 for (i = 0; i < min(data_size, expected_data_size); i++)
254 if ((expected_data[i] != data[i]) &&
255 (((expected_data != expected_hlink_data2) &&
256 (expected_data != expected_hlink_data3)) ||
257 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
264 ok(same, "%s: Saved data differs\n", testname);
267 for (i = 0; i < data_size; i++)
269 if (i % 8 == 0) printf(" ");
270 printf("0x%02x,", data[i]);
271 if (i % 8 == 7) printf("\n");
276 GlobalUnlock(hglobal);
278 IStream_Release(stream);
279 IPersistStream_Release(ps);
282 static void test_persist(void)
284 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
285 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
286 static const WCHAR filename[] = { 'c',':','\\',0 };
287 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
288 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
289 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
293 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
294 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
295 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
296 test_persist_save_data("url only", lnk, expected_hlink_data, sizeof(expected_hlink_data));
299 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
300 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
301 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
302 test_persist_save_data("url + friendly name", lnk, expected_hlink_data2, sizeof(expected_hlink_data2));
305 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
306 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
307 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
308 test_persist_save_data("url + friendly_name + location", lnk, expected_hlink_data3, sizeof(expected_hlink_data3));
311 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
312 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
313 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
314 test_persist_save_data("relative url", lnk, expected_hlink_data4, sizeof(expected_hlink_data4));
317 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
318 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
319 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
320 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
321 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
322 test_persist_save_data("url + target frame name", lnk, expected_hlink_data5, sizeof(expected_hlink_data5));
325 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
326 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
327 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
328 test_persist_save_data("filename", lnk, expected_hlink_data6, sizeof(expected_hlink_data6));
332 static void test_special_reference(void)
337 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
338 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
339 ok(ref != NULL, "ref == NULL\n");
342 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
343 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
344 ok(ref != NULL, "ref == NULL\n");
347 ref = (void*)0xdeadbeef;
348 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
349 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
350 ok(ref == NULL, "ref=%p\n", ref);
352 ref = (void*)0xdeadbeef;
353 hres = HlinkGetSpecialReference(4, &ref);
354 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
355 ok(ref == NULL, "ref=%p\n", ref);
358 static void test_HlinkCreateExtensionServices(void)
360 IAuthenticate *authenticate;
361 IHttpNegotiate *http_negotiate;
362 LPWSTR password, username, headers;
366 static const WCHAR usernameW[] = {'u','s','e','r',0};
367 static const WCHAR passwordW[] = {'p','a','s','s',0};
368 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
369 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
371 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
372 NULL, &IID_IAuthenticate, (void**)&authenticate);
373 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
374 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
376 password = username = (void*)0xdeadbeef;
377 hwnd = (void*)0xdeadbeef;
378 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
379 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
380 ok(!hwnd, "hwnd != NULL\n");
381 ok(!username, "username != NULL\n");
382 ok(!password, "password != NULL\n");
384 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
385 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
387 headers = (void*)0xdeadbeef;
388 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
390 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
391 ok(headers == NULL, "headers != NULL\n");
393 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
395 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
397 headers = (void*)0xdeadbeef;
398 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
399 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
400 ok(headers == NULL, "headers != NULL\n");
402 IHttpNegotiate_Release(http_negotiate);
403 IAuthenticate_Release(authenticate);
406 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
407 NULL, &IID_IAuthenticate, (void**)&authenticate);
408 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
409 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
411 password = username = NULL;
413 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
414 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
415 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
416 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
417 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
418 CoTaskMemFree(username);
419 CoTaskMemFree(password);
421 password = username = (void*)0xdeadbeef;
422 hwnd = (void*)0xdeadbeef;
423 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
424 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
425 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
426 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
428 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
429 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
431 headers = (void*)0xdeadbeef;
432 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
434 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
435 ok(!lstrcmpW(headers, headersexW), "unexpected headers \"%s\"\n", debugstr_w(headers));
436 CoTaskMemFree(headers);
438 headers = (void*)0xdeadbeef;
439 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
440 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
441 ok(headers == NULL, "unexpected headers \"%s\"\n", debugstr_w(headers));
443 IHttpNegotiate_Release(http_negotiate);
444 IAuthenticate_Release(authenticate);
451 test_HlinkIsShortcut();
454 test_special_reference();
455 test_HlinkCreateExtensionServices();