push 88671f85dcf7a7cd89c63d6e9f34ad6b6ad2ae64
[wine/hacks.git] / dlls / hlink / tests / hlink.c
blob6c3dff0591ac8171ab5c35a0e0767c5b97dca07e
1 /*
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
22 #define COBJMACROS
24 #include <stdio.h>
26 #include <hlink.h>
27 #include <hlguids.h>
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) \
38 do { \
39 ok(expect_ ##func, "unexpected call " #func "\n"); \
40 called_ ## func = TRUE; \
41 }while(0)
43 #define CHECK_EXPECT(func) \
44 do { \
45 CHECK_EXPECT2(func); \
46 expect_ ## func = FALSE; \
47 }while(0)
49 #define CHECK_CALLED(func) \
50 do { \
51 ok(called_ ## func, "expected " #func "\n"); \
52 expect_ ## func = called_ ## func = FALSE; \
53 }while(0)
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];
62 if(!str)
63 return "(null)";
64 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
65 return buf;
68 static const char *debugstr_guid(REFIID riid)
70 static char buf[50];
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]);
77 return buf;
80 static void test_HlinkIsShortcut(void)
82 int i;
83 HRESULT hres;
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};
94 static struct {
95 LPCWSTR file;
96 HRESULT hres;
97 } shortcut_test[] = {
98 {file0, S_FALSE},
99 {file1, S_OK},
100 {file2, S_FALSE},
101 {file3, S_OK},
102 {file4, S_FALSE},
103 {file5, S_OK},
104 {file6, S_FALSE},
105 {file7, S_OK},
106 {NULL, E_INVALIDARG}
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)
118 HRESULT r;
119 IHlink *lnk = NULL;
120 IMoniker *mk = NULL;
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 };
123 LPWSTR str = NULL;
125 r = HlinkCreateFromString(url, NULL, NULL, NULL,
126 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
127 ok(r == S_OK, "failed to create link\n");
128 if (FAILED(r))
129 return;
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");
144 CoTaskMemFree(str);
146 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
147 ok(r == S_OK, "failed\n");
148 todo_wine {
149 ok(!lstrcmpW(str, url2), "url wrong\n");
151 CoTaskMemFree(str);
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");
160 IHlink_Release(lnk);
163 /* url only */
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,
174 0x00,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,
211 /* relative url */
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,
238 0x2f,0x00,0x00,0x00,
241 /* filename */
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,
253 0x5c,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)
260 HRESULT hr;
261 IStream *stream;
262 IPersistStream *ps;
263 HGLOBAL hglobal;
264 DWORD data_size;
265 const unsigned char *data;
266 DWORD i;
267 BOOL same;
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);
290 same = TRUE;
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))))
299 same = FALSE;
300 break;
304 ok(same, "%s: Saved data differs\n", testname);
305 if (!same)
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");
313 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 };
330 HRESULT hr;
331 IHlink *lnk;
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);
336 if (!lnk) {
337 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
338 return;
340 test_persist_save_data("url only", lnk, expected_hlink_data, sizeof(expected_hlink_data));
341 IHlink_Release(lnk);
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));
347 IHlink_Release(lnk);
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));
353 IHlink_Release(lnk);
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));
359 IHlink_Release(lnk);
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));
367 IHlink_Release(lnk);
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));
373 IHlink_Release(lnk);
376 static void test_special_reference(void)
378 LPWSTR ref;
379 HRESULT hres;
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");
384 CoTaskMemFree(ref);
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");
389 CoTaskMemFree(ref);
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;
407 HWND hwnd;
408 HRESULT hres;
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,
433 0, &headers);
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,
438 0, NULL);
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;
456 hwnd = 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,
477 0, &headers);
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;
494 LPWSTR name;
495 DWORD issys;
496 ULONG eaten = 0;
497 IBindCtx *bctx;
498 HRESULT hres;
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));
518 CoTaskMemFree(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));
545 CoTaskMemFree(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)
564 return 2;
567 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
569 return 1;
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)
590 *ppv = NULL;
592 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
593 *ppv = &ServiceProvider;
594 return S_OK;
597 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
598 return E_NOINTERFACE;
601 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
603 return 2;
606 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
608 return 1;
611 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
612 IBinding *pib)
614 ok(0, "unexpected call\n");
615 return E_NOTIMPL;
618 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
620 ok(0, "unexpected call\n");
621 return E_NOTIMPL;
624 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
626 ok(0, "unexpected call\n");
627 return E_NOTIMPL;
630 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
631 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
633 ok(0, "unexpected call\n");
634 return E_NOTIMPL;
637 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
639 ok(0, "unexpected call\n");
640 return E_NOTIMPL;
643 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
645 ok(0, "unexpected call\n");
646 return E_NOTIMPL;
649 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
650 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
652 ok(0, "unexpected call\n");
653 return E_NOTIMPL;
656 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
658 ok(0, "unexpected call\n");
659 return E_NOTIMPL;
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)
680 *ppv = NULL;
682 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
683 return E_NOINTERFACE;
686 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
688 return 2;
691 static ULONG WINAPI Moniker_Release(IMoniker *iface)
693 return 1;
696 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
698 ok(0, "unexpected call\n");
699 return E_NOTIMPL;
702 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
704 ok(0, "unexpected call\n");
705 return E_NOTIMPL;
708 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
710 ok(0, "unexpected call\n");
711 return E_NOTIMPL;
714 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
716 ok(0, "unexpected call\n");
717 return E_NOTIMPL;
720 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
722 ok(0, "unexpected call\n");
723 return E_NOTIMPL;
726 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
727 REFIID riidResult, void **ppvResult)
729 ok(0, "unexpected call\n");
730 return E_NOTIMPL;
733 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
734 REFIID riid, void **ppv)
736 IUnknown *unk;
737 HRESULT hres;
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);
755 return S_OK;
758 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
759 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
761 ok(0, "unexpected call\n");
762 return E_NOTIMPL;
765 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
766 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
768 ok(0, "unexpected call\n");
769 return E_NOTIMPL;
772 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
774 ok(0, "unexpected call\n");
775 return E_NOTIMPL;
778 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
780 ok(0, "unexpected call\n");
781 return E_NOTIMPL;
784 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
786 ok(0, "unexpected call\n");
787 return E_NOTIMPL;
790 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
791 IMoniker *pmkNewlyRunning)
793 ok(0, "unexpected call\n");
794 return E_NOTIMPL;
797 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
798 IMoniker *pmkToLeft, FILETIME *pFileTime)
800 ok(0, "unexpected call\n");
801 return E_NOTIMPL;
804 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
806 ok(0, "unexpected call\n");
807 return E_NOTIMPL;
810 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
811 IMoniker **ppmkPrefix)
813 ok(0, "unexpected call\n");
814 return E_NOTIMPL;
817 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
818 IMoniker **pmkRelPath)
820 ok(0, "unexpected call\n");
821 return E_NOTIMPL;
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));
839 return S_OK;
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");
846 return E_NOTIMPL;
849 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
851 CHECK_EXPECT2(IsSystemMoniker);
853 *pdwMksys = MKSYS_URLMONIKER;
854 return S_OK;
857 static IMonikerVtbl MonikerVtbl = {
858 Moniker_QueryInterface,
859 Moniker_AddRef,
860 Moniker_Release,
861 Moniker_GetClassID,
862 Moniker_IsDirty,
863 Moniker_Load,
864 Moniker_Save,
865 Moniker_GetSizeMax,
866 Moniker_BindToObject,
867 Moniker_BindToStorage,
868 Moniker_Reduce,
869 Moniker_ComposeWith,
870 Moniker_Enum,
871 Moniker_IsEqual,
872 Moniker_Hash,
873 Moniker_IsRunning,
874 Moniker_GetTimeOfLastChange,
875 Moniker_Inverse,
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)
887 IBindCtx *bctx;
888 HRESULT hres;
890 CreateBindCtx(0, &bctx);
891 _bctx = 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);
907 START_TEST(hlink)
909 CoInitialize(NULL);
911 test_HlinkIsShortcut();
912 test_reference();
913 test_persist();
914 test_special_reference();
915 test_HlinkCreateExtensionServices();
916 test_HlinkParseDisplayName();
917 test_HlinkResolveMonikerForData();
919 CoUninitialize();