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
30 #include "wine/test.h"
32 #define DEFINE_EXPECT(func) \
33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
35 #define SET_EXPECT(func) \
36 expect_ ## func = TRUE
38 #define CHECK_EXPECT2(func) \
40 ok(expect_ ##func, "unexpected call " #func "\n"); \
41 called_ ## func = TRUE; \
44 #define CHECK_EXPECT(func) \
46 CHECK_EXPECT2(func); \
47 expect_ ## func = FALSE; \
50 #define CHECK_CALLED(func) \
52 ok(called_ ## func, "expected " #func "\n"); \
53 expect_ ## func = called_ ## func = FALSE; \
56 DEFINE_EXPECT(IsSystemMoniker);
57 DEFINE_EXPECT(BindToStorage);
58 DEFINE_EXPECT(GetDisplayName);
60 static const char *debugstr_w(LPCWSTR str)
62 static char buf[1024];
65 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
69 static const char *debugstr_guid(REFIID riid)
73 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
74 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
75 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
76 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
81 static void test_HlinkIsShortcut(void)
86 static const WCHAR file0[] = {'f','i','l','e',0};
87 static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
88 static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
89 static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
90 static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
91 static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
92 static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
93 static const WCHAR file7[] = {'.','u','r','l',0};
110 for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
111 hres = HlinkIsShortcut(shortcut_test[i].file);
112 ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
113 i, hres, shortcut_test[i].hres);
117 static void test_reference(void)
122 const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
123 const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
126 r = HlinkCreateFromString(url, NULL, NULL, NULL,
127 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
128 ok(r == S_OK, "failed to create link\n");
132 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
133 ok(r == S_OK, "failed\n");
135 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
136 ok(r == S_OK, "failed\n");
137 ok(mk != NULL, "no moniker\n");
138 ok(str == NULL, "string should be null\n");
140 r = IMoniker_Release(mk);
141 ok( r == 1, "moniker refcount wrong\n");
143 r = IHlink_GetStringReference(lnk, -1, &str, NULL);
144 ok(r == S_OK, "failed\n");
147 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
148 ok(r == S_OK, "failed\n");
150 ok(!lstrcmpW(str, url2), "url wrong\n");
154 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
155 ok(r == S_OK, "failed\n");
157 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
158 ok(r == S_OK, "failed\n");
159 ok(str == NULL, "string should be null\n");
165 static const unsigned char expected_hlink_data[] =
167 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
168 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
169 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
170 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
171 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
172 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
173 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
174 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
178 /* url + friendly name */
179 static const unsigned char expected_hlink_data2[] =
181 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
182 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
183 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
184 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
185 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
186 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
187 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
188 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
189 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
190 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
191 0x67,0x00,0x2f,0x00,0x00,0x00,
194 /* url + friendly name + location */
195 static const unsigned char expected_hlink_data3[] =
197 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
198 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
199 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
200 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
201 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
202 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
203 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
204 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
205 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
206 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
207 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
208 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
209 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
213 static const unsigned char expected_hlink_data4[] =
215 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
216 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
217 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
218 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
219 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
220 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
221 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
222 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
223 0x00,0x00,0x00,0x00,0x00,
226 /* url + target frame name */
227 static const unsigned char expected_hlink_data5[] =
229 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
230 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
231 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
232 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
233 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
234 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
235 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
236 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
237 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
238 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
243 static const unsigned char expected_hlink_data6[] =
245 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
246 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
247 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
248 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
249 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
250 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
251 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
252 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
253 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
257 static void test_persist_save_data(const char *testname, IHlink *lnk,
258 const unsigned char *expected_data,
259 unsigned int expected_data_size)
266 const unsigned char *data;
270 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
271 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
273 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
274 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
276 hr = IPersistStream_Save(ps, stream, TRUE);
277 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
279 hr = GetHGlobalFromStream(stream, &hglobal);
280 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
282 data_size = GlobalSize(hglobal);
284 data = GlobalLock(hglobal);
286 /* first check we have the right amount of data */
287 ok(data_size == expected_data_size,
288 "%s: Size of saved data differs (expected %d, actual %d)\n",
289 testname, expected_data_size, data_size);
292 /* then do a byte-by-byte comparison */
293 for (i = 0; i < min(data_size, expected_data_size); i++)
295 if ((expected_data[i] != data[i]) &&
296 (((expected_data != expected_hlink_data2) &&
297 (expected_data != expected_hlink_data3)) ||
298 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
305 ok(same, "%s: Saved data differs\n", testname);
308 for (i = 0; i < data_size; i++)
310 if (i % 8 == 0) printf(" ");
311 printf("0x%02x,", data[i]);
312 if (i % 8 == 7) printf("\n");
317 GlobalUnlock(hglobal);
319 IStream_Release(stream);
320 IPersistStream_Release(ps);
323 static void test_persist(void)
325 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
326 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
327 static const WCHAR filename[] = { 'c',':','\\',0 };
328 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
329 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
330 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
334 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
335 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
336 ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr);
338 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
341 test_persist_save_data("url only", lnk, expected_hlink_data, sizeof(expected_hlink_data));
344 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
345 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
346 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
347 test_persist_save_data("url + friendly name", lnk, expected_hlink_data2, sizeof(expected_hlink_data2));
350 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
351 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
352 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
353 test_persist_save_data("url + friendly_name + location", lnk, expected_hlink_data3, sizeof(expected_hlink_data3));
356 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
357 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
358 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
359 test_persist_save_data("relative url", lnk, expected_hlink_data4, sizeof(expected_hlink_data4));
362 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
363 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
364 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
365 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
366 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
367 test_persist_save_data("url + target frame name", lnk, expected_hlink_data5, sizeof(expected_hlink_data5));
370 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
371 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
372 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
373 test_persist_save_data("filename", lnk, expected_hlink_data6, sizeof(expected_hlink_data6));
377 static void test_special_reference(void)
382 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
383 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
384 ok(ref != NULL, "ref == NULL\n");
387 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
388 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
389 ok(ref != NULL, "ref == NULL\n");
392 ref = (void*)0xdeadbeef;
393 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
394 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
395 ok(ref == NULL, "ref=%p\n", ref);
397 ref = (void*)0xdeadbeef;
398 hres = HlinkGetSpecialReference(4, &ref);
399 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
400 ok(ref == NULL, "ref=%p\n", ref);
403 static void test_HlinkCreateExtensionServices(void)
405 IAuthenticate *authenticate;
406 IHttpNegotiate *http_negotiate;
407 LPWSTR password, username, headers;
411 static const WCHAR usernameW[] = {'u','s','e','r',0};
412 static const WCHAR passwordW[] = {'p','a','s','s',0};
413 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
414 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
416 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
417 NULL, &IID_IAuthenticate, (void**)&authenticate);
418 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
419 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
421 password = username = (void*)0xdeadbeef;
422 hwnd = (void*)0xdeadbeef;
423 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
424 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
425 ok(!hwnd, "hwnd != NULL\n");
426 ok(!username, "username != NULL\n");
427 ok(!password, "password != NULL\n");
429 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
430 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
432 headers = (void*)0xdeadbeef;
433 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
435 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
436 ok(headers == NULL, "headers != NULL\n");
438 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
440 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
442 headers = (void*)0xdeadbeef;
443 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
444 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
445 ok(headers == NULL, "headers != NULL\n");
447 IHttpNegotiate_Release(http_negotiate);
448 IAuthenticate_Release(authenticate);
451 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
452 NULL, &IID_IAuthenticate, (void**)&authenticate);
453 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
454 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
456 password = username = NULL;
458 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
459 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
460 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
461 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
462 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
463 CoTaskMemFree(username);
464 CoTaskMemFree(password);
466 password = username = (void*)0xdeadbeef;
467 hwnd = (void*)0xdeadbeef;
468 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
469 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
470 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
471 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
473 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
474 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
476 headers = (void*)0xdeadbeef;
477 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
479 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
480 ok(!lstrcmpW(headers, headersexW), "unexpected headers \"%s\"\n", debugstr_w(headers));
481 CoTaskMemFree(headers);
483 headers = (void*)0xdeadbeef;
484 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
485 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
486 ok(headers == NULL, "unexpected headers \"%s\"\n", debugstr_w(headers));
488 IHttpNegotiate_Release(http_negotiate);
489 IAuthenticate_Release(authenticate);
492 static void test_HlinkParseDisplayName(void)
494 IMoniker *mon = NULL;
501 static const WCHAR winehq_urlW[] =
502 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
503 '/','s','i','t','e','/','a','b','o','u','t',0};
504 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
505 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
506 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
507 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
509 CreateBindCtx(0, &bctx);
511 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
512 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
513 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
514 ok(mon != NULL, "mon == NULL\n");
516 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
517 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
518 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", debugstr_w(name));
521 hres = IMoniker_IsSystemMoniker(mon, &issys);
522 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
523 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
525 IMoniker_Release(mon);
527 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
528 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
529 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
530 ok(mon != NULL, "mon == NULL\n");
532 hres = IMoniker_IsSystemMoniker(mon, &issys);
533 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
534 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
536 IMoniker_Release(mon);
538 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
539 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
540 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
541 ok(mon != NULL, "mon == NULL\n");
543 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
544 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
545 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", debugstr_w(name));
548 hres = IMoniker_IsSystemMoniker(mon, &issys);
549 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
550 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
552 IBindCtx_Release(bctx);
555 static IBindCtx *_bctx;
557 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
559 ok(0, "unexpected call\n");
560 return E_NOINTERFACE;
563 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
568 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
573 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
574 REFGUID guidService, REFIID riid, void **ppv)
576 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
577 return E_NOINTERFACE;
580 static IServiceProviderVtbl ServiceProviderVtbl = {
581 ServiceProvider_QueryInterface,
582 ServiceProvider_AddRef,
583 ServiceProvider_Release,
584 ServiceProvider_QueryService
587 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
589 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
593 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
594 *ppv = &ServiceProvider;
598 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
599 return E_NOINTERFACE;
602 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
607 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
612 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
615 ok(0, "unexpected call\n");
619 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
621 ok(0, "unexpected call\n");
625 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
627 ok(0, "unexpected call\n");
631 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
632 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
634 ok(0, "unexpected call\n");
638 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
640 ok(0, "unexpected call\n");
644 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
646 ok(0, "unexpected call\n");
650 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
651 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
653 ok(0, "unexpected call\n");
657 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
659 ok(0, "unexpected call\n");
663 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
664 BindStatusCallback_QueryInterface,
665 BindStatusCallback_AddRef,
666 BindStatusCallback_Release,
667 BindStatusCallback_OnStartBinding,
668 BindStatusCallback_GetPriority,
669 BindStatusCallback_OnLowResource,
670 BindStatusCallback_OnProgress,
671 BindStatusCallback_OnStopBinding,
672 BindStatusCallback_GetBindInfo,
673 BindStatusCallback_OnDataAvailable,
674 BindStatusCallback_OnObjectAvailable
677 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
679 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
683 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
684 return E_NOINTERFACE;
687 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
692 static ULONG WINAPI Moniker_Release(IMoniker *iface)
697 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
699 ok(0, "unexpected call\n");
703 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
705 ok(0, "unexpected call\n");
709 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
711 ok(0, "unexpected call\n");
715 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
717 ok(0, "unexpected call\n");
721 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
723 ok(0, "unexpected call\n");
727 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
728 REFIID riidResult, void **ppvResult)
730 ok(0, "unexpected call\n");
734 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
735 REFIID riid, void **ppv)
740 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
742 CHECK_EXPECT(BindToStorage);
744 ok(pbc == _bctx, "pbc != _bctx\n");
745 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
746 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
747 ok(ppv != NULL, "ppv == NULL\n");
748 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
750 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
751 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
752 ok(unk != NULL, "unk == NULL\n");
754 IUnknown_Release(unk);
759 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
760 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
762 ok(0, "unexpected call\n");
766 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
767 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
769 ok(0, "unexpected call\n");
773 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
775 ok(0, "unexpected call\n");
779 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
781 ok(0, "unexpected call\n");
785 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
787 ok(0, "unexpected call\n");
791 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
792 IMoniker *pmkNewlyRunning)
794 ok(0, "unexpected call\n");
798 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
799 IMoniker *pmkToLeft, FILETIME *pFileTime)
801 ok(0, "unexpected call\n");
805 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
807 ok(0, "unexpected call\n");
811 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
812 IMoniker **ppmkPrefix)
814 ok(0, "unexpected call\n");
818 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
819 IMoniker **pmkRelPath)
821 ok(0, "unexpected call\n");
825 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
826 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
828 static const WCHAR winehq_urlW[] =
829 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
830 '/','s','i','t','e','/','a','b','o','u','t',0};
832 CHECK_EXPECT(GetDisplayName);
834 ok(pbc != NULL, "pbc == NULL\n");
835 ok(pbc != _bctx, "pbc == _bctx\n");
836 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
838 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
839 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
843 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
844 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
846 ok(0, "unexpected call\n");
850 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
852 CHECK_EXPECT2(IsSystemMoniker);
854 *pdwMksys = MKSYS_URLMONIKER;
858 static IMonikerVtbl MonikerVtbl = {
859 Moniker_QueryInterface,
867 Moniker_BindToObject,
868 Moniker_BindToStorage,
875 Moniker_GetTimeOfLastChange,
877 Moniker_CommonPrefixWith,
878 Moniker_RelativePathTo,
879 Moniker_GetDisplayName,
880 Moniker_ParseDisplayName,
881 Moniker_IsSystemMoniker
884 static IMoniker Moniker = { &MonikerVtbl };
886 static void test_HlinkResolveMonikerForData(void)
891 CreateBindCtx(0, &bctx);
894 SET_EXPECT(IsSystemMoniker);
895 SET_EXPECT(GetDisplayName);
896 SET_EXPECT(BindToStorage);
898 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
899 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
901 CHECK_CALLED(IsSystemMoniker);
902 CHECK_CALLED(GetDisplayName);
903 CHECK_CALLED(BindToStorage);
905 IBindCtx_Release(bctx);
912 test_HlinkIsShortcut();
915 test_special_reference();
916 test_HlinkCreateExtensionServices();
917 test_HlinkParseDisplayName();
918 test_HlinkResolveMonikerForData();