2 * Implementation of hyperlinking (hlink.dll)
4 * Copyright 2006 Mike McCormack
5 * Copyright 2007-2008 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 #define DEFINE_EXPECT(func) \
32 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34 #define SET_EXPECT(func) \
35 expect_ ## func = TRUE
37 #define CHECK_EXPECT2(func) \
39 ok(expect_ ##func, "unexpected call " #func "\n"); \
40 called_ ## func = TRUE; \
43 #define CHECK_EXPECT(func) \
45 CHECK_EXPECT2(func); \
46 expect_ ## func = FALSE; \
49 #define CHECK_CALLED(func) \
51 ok(called_ ## func, "expected " #func "\n"); \
52 expect_ ## func = called_ ## func = FALSE; \
55 DEFINE_EXPECT(IsSystemMoniker);
56 DEFINE_EXPECT(BindToStorage);
57 DEFINE_EXPECT(GetDisplayName);
59 static const char *debugstr_w(LPCWSTR str)
61 static char buf[1024];
64 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
68 static const char *debugstr_guid(REFIID riid)
72 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
73 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
74 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
75 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
80 static void test_HlinkIsShortcut(void)
85 static const WCHAR file0[] = {'f','i','l','e',0};
86 static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
87 static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
88 static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
89 static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
90 static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
91 static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
92 static const WCHAR file7[] = {'.','u','r','l',0};
109 for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
110 hres = HlinkIsShortcut(shortcut_test[i].file);
111 ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
112 i, hres, shortcut_test[i].hres);
116 static void test_reference(void)
121 const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
122 const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
125 r = HlinkCreateFromString(url, NULL, NULL, NULL,
126 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
127 ok(r == S_OK, "failed to create link\n");
131 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
132 ok(r == S_OK, "failed\n");
134 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
135 ok(r == S_OK, "failed\n");
136 ok(mk != NULL, "no moniker\n");
137 ok(str == NULL, "string should be null\n");
139 r = IMoniker_Release(mk);
140 ok( r == 1, "moniker refcount wrong\n");
142 r = IHlink_GetStringReference(lnk, -1, &str, NULL);
143 ok(r == S_OK, "failed\n");
146 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
147 ok(r == S_OK, "failed\n");
149 ok(!lstrcmpW(str, url2), "url wrong\n");
153 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
154 ok(r == S_OK, "failed\n");
156 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
157 ok(r == S_OK, "failed\n");
158 ok(str == NULL, "string should be null\n");
164 static const unsigned char expected_hlink_data[] =
166 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
167 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
168 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
169 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
170 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
171 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
172 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
173 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
177 /* url + friendly name */
178 static const unsigned char expected_hlink_data2[] =
180 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
181 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
182 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
183 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
184 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
185 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
186 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
187 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
188 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
189 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
190 0x67,0x00,0x2f,0x00,0x00,0x00,
193 /* url + friendly name + location */
194 static const unsigned char expected_hlink_data3[] =
196 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
197 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
198 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
199 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
200 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
201 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
202 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
203 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
204 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
205 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
206 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
207 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
208 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
212 static const unsigned char expected_hlink_data4[] =
214 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
215 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
216 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
217 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
218 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
219 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
220 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
221 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222 0x00,0x00,0x00,0x00,0x00,
225 /* url + target frame name */
226 static const unsigned char expected_hlink_data5[] =
228 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
229 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
230 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
231 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
232 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
233 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
234 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
235 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
236 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
237 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
242 static const unsigned char expected_hlink_data6[] =
244 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
245 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
246 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
247 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
248 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
249 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
250 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
251 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
252 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
256 static void test_persist_save_data(const char *testname, IHlink *lnk,
257 const unsigned char *expected_data,
258 unsigned int expected_data_size)
265 const unsigned char *data;
269 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
270 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
272 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
273 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
275 hr = IPersistStream_Save(ps, stream, TRUE);
276 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
278 hr = GetHGlobalFromStream(stream, &hglobal);
279 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
281 data_size = GlobalSize(hglobal);
283 data = GlobalLock(hglobal);
285 /* first check we have the right amount of data */
286 ok(data_size == expected_data_size,
287 "%s: Size of saved data differs (expected %d, actual %d)\n",
288 testname, expected_data_size, data_size);
291 /* then do a byte-by-byte comparison */
292 for (i = 0; i < min(data_size, expected_data_size); i++)
294 if ((expected_data[i] != data[i]) &&
295 (((expected_data != expected_hlink_data2) &&
296 (expected_data != expected_hlink_data3)) ||
297 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
304 ok(same, "%s: Saved data differs\n", testname);
307 for (i = 0; i < data_size; i++)
309 if (i % 8 == 0) printf(" ");
310 printf("0x%02x,", data[i]);
311 if (i % 8 == 7) printf("\n");
316 GlobalUnlock(hglobal);
318 IStream_Release(stream);
319 IPersistStream_Release(ps);
322 static void test_persist(void)
324 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
325 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
326 static const WCHAR filename[] = { 'c',':','\\',0 };
327 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
328 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
329 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
333 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
334 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
335 ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr);
337 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
340 test_persist_save_data("url only", lnk, expected_hlink_data, sizeof(expected_hlink_data));
343 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
344 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
345 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
346 test_persist_save_data("url + friendly name", lnk, expected_hlink_data2, sizeof(expected_hlink_data2));
349 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
350 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
351 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
352 test_persist_save_data("url + friendly_name + location", lnk, expected_hlink_data3, sizeof(expected_hlink_data3));
355 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
356 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
357 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
358 test_persist_save_data("relative url", lnk, expected_hlink_data4, sizeof(expected_hlink_data4));
361 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
362 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
363 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
364 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
365 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
366 test_persist_save_data("url + target frame name", lnk, expected_hlink_data5, sizeof(expected_hlink_data5));
369 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
370 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
371 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
372 test_persist_save_data("filename", lnk, expected_hlink_data6, sizeof(expected_hlink_data6));
376 static void test_special_reference(void)
381 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
382 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
383 ok(ref != NULL, "ref == NULL\n");
386 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
387 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
388 ok(ref != NULL, "ref == NULL\n");
391 ref = (void*)0xdeadbeef;
392 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
393 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
394 ok(ref == NULL, "ref=%p\n", ref);
396 ref = (void*)0xdeadbeef;
397 hres = HlinkGetSpecialReference(4, &ref);
398 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
399 ok(ref == NULL, "ref=%p\n", ref);
402 static void test_HlinkCreateExtensionServices(void)
404 IAuthenticate *authenticate;
405 IHttpNegotiate *http_negotiate;
406 LPWSTR password, username, headers;
410 static const WCHAR usernameW[] = {'u','s','e','r',0};
411 static const WCHAR passwordW[] = {'p','a','s','s',0};
412 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
413 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
415 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
416 NULL, &IID_IAuthenticate, (void**)&authenticate);
417 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
418 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
420 password = username = (void*)0xdeadbeef;
421 hwnd = (void*)0xdeadbeef;
422 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
423 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
424 ok(!hwnd, "hwnd != NULL\n");
425 ok(!username, "username != NULL\n");
426 ok(!password, "password != NULL\n");
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(headers == NULL, "headers != NULL\n");
437 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
439 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
441 headers = (void*)0xdeadbeef;
442 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
443 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
444 ok(headers == NULL, "headers != NULL\n");
446 IHttpNegotiate_Release(http_negotiate);
447 IAuthenticate_Release(authenticate);
450 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
451 NULL, &IID_IAuthenticate, (void**)&authenticate);
452 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
453 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
455 password = username = NULL;
457 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
458 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
459 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
460 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
461 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
462 CoTaskMemFree(username);
463 CoTaskMemFree(password);
465 password = username = (void*)0xdeadbeef;
466 hwnd = (void*)0xdeadbeef;
467 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
468 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
469 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
470 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
472 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
473 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
475 headers = (void*)0xdeadbeef;
476 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
478 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
479 ok(!lstrcmpW(headers, headersexW), "unexpected headers \"%s\"\n", debugstr_w(headers));
480 CoTaskMemFree(headers);
482 headers = (void*)0xdeadbeef;
483 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
484 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
485 ok(headers == NULL, "unexpected headers \"%s\"\n", debugstr_w(headers));
487 IHttpNegotiate_Release(http_negotiate);
488 IAuthenticate_Release(authenticate);
491 static void test_HlinkParseDisplayName(void)
493 IMoniker *mon = NULL;
500 static const WCHAR winehq_urlW[] =
501 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
502 '/','s','i','t','e','/','a','b','o','u','t',0};
503 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
504 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
505 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
506 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
508 CreateBindCtx(0, &bctx);
510 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
511 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
512 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
513 ok(mon != NULL, "mon == NULL\n");
515 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
516 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
517 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", debugstr_w(name));
520 hres = IMoniker_IsSystemMoniker(mon, &issys);
521 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
522 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
524 IMoniker_Release(mon);
526 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
527 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
528 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
529 ok(mon != NULL, "mon == NULL\n");
531 hres = IMoniker_IsSystemMoniker(mon, &issys);
532 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
533 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
535 IMoniker_Release(mon);
537 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
538 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
539 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
540 ok(mon != NULL, "mon == NULL\n");
542 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
543 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
544 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", debugstr_w(name));
547 hres = IMoniker_IsSystemMoniker(mon, &issys);
548 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
549 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
551 IBindCtx_Release(bctx);
554 static IBindCtx *_bctx;
556 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
558 ok(0, "unexpected call\n");
559 return E_NOINTERFACE;
562 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
567 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
572 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
573 REFGUID guidService, REFIID riid, void **ppv)
575 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
576 return E_NOINTERFACE;
579 static IServiceProviderVtbl ServiceProviderVtbl = {
580 ServiceProvider_QueryInterface,
581 ServiceProvider_AddRef,
582 ServiceProvider_Release,
583 ServiceProvider_QueryService
586 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
588 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
592 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
593 *ppv = &ServiceProvider;
597 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
598 return E_NOINTERFACE;
601 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
606 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
611 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
614 ok(0, "unexpected call\n");
618 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
620 ok(0, "unexpected call\n");
624 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
626 ok(0, "unexpected call\n");
630 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
631 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
633 ok(0, "unexpected call\n");
637 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
639 ok(0, "unexpected call\n");
643 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
645 ok(0, "unexpected call\n");
649 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
650 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
652 ok(0, "unexpected call\n");
656 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
658 ok(0, "unexpected call\n");
662 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
663 BindStatusCallback_QueryInterface,
664 BindStatusCallback_AddRef,
665 BindStatusCallback_Release,
666 BindStatusCallback_OnStartBinding,
667 BindStatusCallback_GetPriority,
668 BindStatusCallback_OnLowResource,
669 BindStatusCallback_OnProgress,
670 BindStatusCallback_OnStopBinding,
671 BindStatusCallback_GetBindInfo,
672 BindStatusCallback_OnDataAvailable,
673 BindStatusCallback_OnObjectAvailable
676 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
678 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
682 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
683 return E_NOINTERFACE;
686 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
691 static ULONG WINAPI Moniker_Release(IMoniker *iface)
696 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
698 ok(0, "unexpected call\n");
702 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
704 ok(0, "unexpected call\n");
708 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
710 ok(0, "unexpected call\n");
714 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
716 ok(0, "unexpected call\n");
720 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
722 ok(0, "unexpected call\n");
726 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
727 REFIID riidResult, void **ppvResult)
729 ok(0, "unexpected call\n");
733 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
734 REFIID riid, void **ppv)
739 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
741 CHECK_EXPECT(BindToStorage);
743 ok(pbc == _bctx, "pbc != _bctx\n");
744 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
745 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
746 ok(ppv != NULL, "ppv == NULL\n");
747 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
749 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
750 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
751 ok(unk != NULL, "unk == NULL\n");
753 IUnknown_Release(unk);
758 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
759 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
761 ok(0, "unexpected call\n");
765 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
766 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
768 ok(0, "unexpected call\n");
772 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
774 ok(0, "unexpected call\n");
778 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
780 ok(0, "unexpected call\n");
784 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
786 ok(0, "unexpected call\n");
790 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
791 IMoniker *pmkNewlyRunning)
793 ok(0, "unexpected call\n");
797 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
798 IMoniker *pmkToLeft, FILETIME *pFileTime)
800 ok(0, "unexpected call\n");
804 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
806 ok(0, "unexpected call\n");
810 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
811 IMoniker **ppmkPrefix)
813 ok(0, "unexpected call\n");
817 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
818 IMoniker **pmkRelPath)
820 ok(0, "unexpected call\n");
824 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
825 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
827 static const WCHAR winehq_urlW[] =
828 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
829 '/','s','i','t','e','/','a','b','o','u','t',0};
831 CHECK_EXPECT(GetDisplayName);
833 ok(pbc != NULL, "pbc == NULL\n");
834 ok(pbc != _bctx, "pbc == _bctx\n");
835 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
837 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
838 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
842 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
843 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
845 ok(0, "unexpected call\n");
849 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
851 CHECK_EXPECT2(IsSystemMoniker);
853 *pdwMksys = MKSYS_URLMONIKER;
857 static IMonikerVtbl MonikerVtbl = {
858 Moniker_QueryInterface,
866 Moniker_BindToObject,
867 Moniker_BindToStorage,
874 Moniker_GetTimeOfLastChange,
876 Moniker_CommonPrefixWith,
877 Moniker_RelativePathTo,
878 Moniker_GetDisplayName,
879 Moniker_ParseDisplayName,
880 Moniker_IsSystemMoniker
883 static IMoniker Moniker = { &MonikerVtbl };
885 static void test_HlinkResolveMonikerForData(void)
890 CreateBindCtx(0, &bctx);
893 SET_EXPECT(IsSystemMoniker);
894 SET_EXPECT(GetDisplayName);
895 SET_EXPECT(BindToStorage);
897 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
898 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
900 CHECK_CALLED(IsSystemMoniker);
901 CHECK_CALLED(GetDisplayName);
902 CHECK_CALLED(BindToStorage);
904 IBindCtx_Release(bctx);
911 test_HlinkIsShortcut();
914 test_special_reference();
915 test_HlinkCreateExtensionServices();
916 test_HlinkParseDisplayName();
917 test_HlinkResolveMonikerForData();