push 553a83299288f61678d62ade87a3a2a5489a8ad8
[wine/hacks.git] / dlls / hlink / tests / hlink.c
blob9e4c5a32ec1465e89f5e8c1182093b43a4f8c92f
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 <initguid.h>
27 #include <hlink.h>
28 #include <hlguids.h>
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) \
39 do { \
40 ok(expect_ ##func, "unexpected call " #func "\n"); \
41 called_ ## func = TRUE; \
42 }while(0)
44 #define CHECK_EXPECT(func) \
45 do { \
46 CHECK_EXPECT2(func); \
47 expect_ ## func = FALSE; \
48 }while(0)
50 #define CHECK_CALLED(func) \
51 do { \
52 ok(called_ ## func, "expected " #func "\n"); \
53 expect_ ## func = called_ ## func = FALSE; \
54 }while(0)
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];
63 if(!str)
64 return "(null)";
65 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
66 return buf;
69 static const char *debugstr_guid(REFIID riid)
71 static char buf[50];
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]);
78 return buf;
81 static void test_HlinkIsShortcut(void)
83 int i;
84 HRESULT hres;
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};
95 static struct {
96 LPCWSTR file;
97 HRESULT hres;
98 } shortcut_test[] = {
99 {file0, S_FALSE},
100 {file1, S_OK},
101 {file2, S_FALSE},
102 {file3, S_OK},
103 {file4, S_FALSE},
104 {file5, S_OK},
105 {file6, S_FALSE},
106 {file7, S_OK},
107 {NULL, E_INVALIDARG}
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)
119 HRESULT r;
120 IHlink *lnk = NULL;
121 IMoniker *mk = NULL;
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 };
124 LPWSTR str = NULL;
126 r = HlinkCreateFromString(url, NULL, NULL, NULL,
127 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
128 ok(r == S_OK, "failed to create link\n");
129 if (FAILED(r))
130 return;
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");
145 CoTaskMemFree(str);
147 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
148 ok(r == S_OK, "failed\n");
149 todo_wine {
150 ok(!lstrcmpW(str, url2), "url wrong\n");
152 CoTaskMemFree(str);
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");
161 IHlink_Release(lnk);
164 /* url only */
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,
175 0x00,0x00,
178 /* url only (IE7) */
179 static const unsigned char expected_hlink_data_ie7[] =
181 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
182 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
183 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
184 0x3e,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
185 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
186 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
187 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
188 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
189 0x00,0x00,0x79,0x58,0x81,0xf4,0x3b,0x1d,
190 0x7f,0x48,0xaf,0x2c,0x82,0x5d,0xc4,0x85,
191 0x27,0x63,0x00,0x00,0x00,0x00,0xa5,0xab,
192 0x00,0x00,
195 /* url + friendly name */
196 static const unsigned char expected_hlink_data2[] =
198 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
199 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
200 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
201 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
202 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
203 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
204 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
205 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
206 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
207 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
208 0x67,0x00,0x2f,0x00,0x00,0x00,
211 /* url + friendly name (IE7) */
212 static const unsigned char expected_hlink_data2_ie7[] =
214 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
215 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
216 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
217 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
218 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
219 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
220 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
221 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
222 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
223 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
224 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
225 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
226 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
227 0x00,0x00,0xa5,0xab,0x00,0x00,
230 /* url + friendly name + location */
231 static const unsigned char expected_hlink_data3[] =
233 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
234 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
235 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
236 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
237 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
238 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
239 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
240 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
241 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
242 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
243 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
244 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
245 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
248 /* url + friendly name + location (IE7) */
249 static const unsigned char expected_hlink_data3_ie7[] =
251 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
252 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
253 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
254 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
255 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
256 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
257 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
258 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
259 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
260 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
261 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
262 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
263 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
264 0x00,0x00,0xa5,0xab,0x00,0x00,0x07,0x00,
265 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
266 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
269 /* relative url */
270 static const unsigned char expected_hlink_data4[] =
272 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
273 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
274 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
275 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
276 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
277 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
278 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
279 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
280 0x00,0x00,0x00,0x00,0x00,
283 /* url + target frame name */
284 static const unsigned char expected_hlink_data5[] =
286 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
287 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
288 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
289 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
290 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
291 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
292 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
293 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
294 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
295 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
296 0x2f,0x00,0x00,0x00,
299 /* url + target frame name (IE7) */
300 static const unsigned char expected_hlink_data5_ie7[] =
302 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
303 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
304 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
305 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
306 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
307 0xa9,0x0b,0x3e,0x00,0x00,0x00,0x68,0x00,
308 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
309 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
310 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
311 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
312 0x2f,0x00,0x00,0x00,0x79,0x58,0x81,0xf4,
313 0x3b,0x1d,0x7f,0x48,0xaf,0x2c,0x82,0x5d,
314 0xc4,0x85,0x27,0x63,0x00,0x00,0x00,0x00,
315 0xa5,0xab,0x00,0x00,
318 /* filename */
319 static const unsigned char expected_hlink_data6[] =
321 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
322 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
323 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
324 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
325 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
326 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
327 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
328 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
329 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
330 0x5c,0x00,
333 static void test_persist_save_data(const char *testname, IHlink *lnk,
334 const unsigned char *expected_data,
335 unsigned int expected_data_size,
336 const unsigned char *expected_data_alt,
337 unsigned int expected_data_alt_size)
339 HRESULT hr;
340 IStream *stream;
341 IPersistStream *ps;
342 HGLOBAL hglobal;
343 DWORD data_size;
344 const unsigned char *data;
345 DWORD i;
346 BOOL same;
348 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
349 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
351 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
352 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
354 hr = IPersistStream_Save(ps, stream, TRUE);
355 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
357 hr = GetHGlobalFromStream(stream, &hglobal);
358 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
360 data_size = GlobalSize(hglobal);
362 data = GlobalLock(hglobal);
364 /* first check we have the right amount of data */
365 ok((data_size == expected_data_size) || (data_size == expected_data_alt_size),
366 "%s: Size of saved data differs (expected %d or %d, actual %d)\n",
367 testname, expected_data_size, expected_data_alt_size, data_size);
369 same = TRUE;
370 /* then do a byte-by-byte comparison */
371 for (i = 0; i < min(data_size, expected_data_size); i++)
373 if ((expected_data[i] != data[i]) &&
374 (((expected_data != expected_hlink_data2) &&
375 (expected_data != expected_hlink_data3)) ||
376 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
378 same = FALSE;
379 break;
383 if (!same && (expected_data_alt != expected_data))
385 /* then try the alternate data */
386 same = TRUE;
387 for (i = 0; i < min(data_size, expected_data_alt_size); i++)
389 if ((expected_data_alt[i] != data[i]) &&
390 (((expected_data_alt != expected_hlink_data2) &&
391 (expected_data_alt != expected_hlink_data3)) ||
392 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
394 same = FALSE;
395 break;
400 ok(same, "%s: Saved data differs\n", testname);
401 if (!same)
403 for (i = 0; i < data_size; i++)
405 if (i % 8 == 0) printf(" ");
406 printf("0x%02x,", data[i]);
407 if (i % 8 == 7) printf("\n");
409 printf("\n");
412 GlobalUnlock(hglobal);
414 IStream_Release(stream);
415 IPersistStream_Release(ps);
418 static void test_persist(void)
420 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
421 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
422 static const WCHAR filename[] = { 'c',':','\\',0 };
423 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
424 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
425 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
426 HRESULT hr;
427 IHlink *lnk;
429 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
430 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
431 ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr);
432 if (!lnk) {
433 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
434 return;
436 test_persist_save_data("url only", lnk,
437 expected_hlink_data, sizeof(expected_hlink_data),
438 expected_hlink_data_ie7, sizeof(expected_hlink_data_ie7));
439 IHlink_Release(lnk);
441 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
442 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
443 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
444 test_persist_save_data("url + friendly name", lnk,
445 expected_hlink_data2, sizeof(expected_hlink_data2),
446 expected_hlink_data2_ie7, sizeof(expected_hlink_data2_ie7));
447 IHlink_Release(lnk);
449 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
450 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
451 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
452 test_persist_save_data("url + friendly_name + location", lnk,
453 expected_hlink_data3, sizeof(expected_hlink_data3),
454 expected_hlink_data3_ie7, sizeof(expected_hlink_data3_ie7));
455 IHlink_Release(lnk);
457 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
458 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
459 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
460 test_persist_save_data("relative url", lnk,
461 expected_hlink_data4, sizeof(expected_hlink_data4),
462 expected_hlink_data4, sizeof(expected_hlink_data4));
463 IHlink_Release(lnk);
465 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
466 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
467 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
468 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
469 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
470 test_persist_save_data("url + target frame name", lnk,
471 expected_hlink_data5, sizeof(expected_hlink_data5),
472 expected_hlink_data5_ie7, sizeof(expected_hlink_data5_ie7));
473 IHlink_Release(lnk);
475 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
476 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
477 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
478 test_persist_save_data("filename", lnk,
479 expected_hlink_data6, sizeof(expected_hlink_data6),
480 expected_hlink_data6, sizeof(expected_hlink_data6));
481 IHlink_Release(lnk);
484 static void test_special_reference(void)
486 LPWSTR ref;
487 HRESULT hres;
489 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
490 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
491 ok(ref != NULL, "ref == NULL\n");
492 CoTaskMemFree(ref);
494 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
495 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
496 ok(ref != NULL, "ref == NULL\n");
497 CoTaskMemFree(ref);
499 ref = (void*)0xdeadbeef;
500 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
501 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
502 ok(ref == NULL, "ref=%p\n", ref);
504 ref = (void*)0xdeadbeef;
505 hres = HlinkGetSpecialReference(4, &ref);
506 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
507 ok(ref == NULL, "ref=%p\n", ref);
510 static void test_HlinkCreateExtensionServices(void)
512 IAuthenticate *authenticate;
513 IHttpNegotiate *http_negotiate;
514 LPWSTR password, username, headers;
515 HWND hwnd;
516 HRESULT hres;
518 static const WCHAR usernameW[] = {'u','s','e','r',0};
519 static const WCHAR passwordW[] = {'p','a','s','s',0};
520 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
521 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
523 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
524 NULL, &IID_IAuthenticate, (void**)&authenticate);
525 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
526 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
528 password = username = (void*)0xdeadbeef;
529 hwnd = (void*)0xdeadbeef;
530 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
531 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
532 ok(!hwnd, "hwnd != NULL\n");
533 ok(!username, "username != NULL\n");
534 ok(!password, "password != NULL\n");
536 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
537 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
539 headers = (void*)0xdeadbeef;
540 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
541 0, &headers);
542 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
543 ok(headers == NULL, "headers != NULL\n");
545 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
546 0, NULL);
547 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
549 headers = (void*)0xdeadbeef;
550 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
551 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
552 ok(headers == NULL, "headers != NULL\n");
554 IHttpNegotiate_Release(http_negotiate);
555 IAuthenticate_Release(authenticate);
558 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
559 NULL, &IID_IAuthenticate, (void**)&authenticate);
560 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
561 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
563 password = username = NULL;
564 hwnd = NULL;
565 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
566 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
567 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
568 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
569 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
570 CoTaskMemFree(username);
571 CoTaskMemFree(password);
573 password = username = (void*)0xdeadbeef;
574 hwnd = (void*)0xdeadbeef;
575 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
576 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
577 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
578 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
580 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
581 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
583 headers = (void*)0xdeadbeef;
584 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
585 0, &headers);
586 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
587 ok(!lstrcmpW(headers, headersexW), "unexpected headers \"%s\"\n", debugstr_w(headers));
588 CoTaskMemFree(headers);
590 headers = (void*)0xdeadbeef;
591 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
592 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
593 ok(headers == NULL, "unexpected headers \"%s\"\n", debugstr_w(headers));
595 IHttpNegotiate_Release(http_negotiate);
596 IAuthenticate_Release(authenticate);
599 static void test_HlinkParseDisplayName(void)
601 IMoniker *mon = NULL;
602 LPWSTR name;
603 DWORD issys;
604 ULONG eaten = 0;
605 IBindCtx *bctx;
606 HRESULT hres;
608 static const WCHAR winehq_urlW[] =
609 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
610 '/','s','i','t','e','/','a','b','o','u','t',0};
611 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
612 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
613 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
614 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
616 CreateBindCtx(0, &bctx);
618 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
619 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
620 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
621 ok(mon != NULL, "mon == NULL\n");
623 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
624 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
625 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", debugstr_w(name));
626 CoTaskMemFree(name);
628 hres = IMoniker_IsSystemMoniker(mon, &issys);
629 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
630 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
632 IMoniker_Release(mon);
634 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
635 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
636 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
637 ok(mon != NULL, "mon == NULL\n");
639 hres = IMoniker_IsSystemMoniker(mon, &issys);
640 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
641 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
643 IMoniker_Release(mon);
645 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
646 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
647 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
648 ok(mon != NULL, "mon == NULL\n");
650 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
651 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
652 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", debugstr_w(name));
653 CoTaskMemFree(name);
655 hres = IMoniker_IsSystemMoniker(mon, &issys);
656 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
657 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
659 IBindCtx_Release(bctx);
662 static IBindCtx *_bctx;
664 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
666 ok(0, "unexpected call\n");
667 return E_NOINTERFACE;
670 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
672 return 2;
675 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
677 return 1;
680 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
681 REFGUID guidService, REFIID riid, void **ppv)
683 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
684 return E_NOINTERFACE;
687 static IServiceProviderVtbl ServiceProviderVtbl = {
688 ServiceProvider_QueryInterface,
689 ServiceProvider_AddRef,
690 ServiceProvider_Release,
691 ServiceProvider_QueryService
694 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
696 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
698 *ppv = NULL;
700 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
701 *ppv = &ServiceProvider;
702 return S_OK;
705 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
706 return E_NOINTERFACE;
709 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
711 return 2;
714 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
716 return 1;
719 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
720 IBinding *pib)
722 ok(0, "unexpected call\n");
723 return E_NOTIMPL;
726 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
728 ok(0, "unexpected call\n");
729 return E_NOTIMPL;
732 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
734 ok(0, "unexpected call\n");
735 return E_NOTIMPL;
738 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
739 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
741 ok(0, "unexpected call\n");
742 return E_NOTIMPL;
745 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
747 ok(0, "unexpected call\n");
748 return E_NOTIMPL;
751 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
753 ok(0, "unexpected call\n");
754 return E_NOTIMPL;
757 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
758 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
760 ok(0, "unexpected call\n");
761 return E_NOTIMPL;
764 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
766 ok(0, "unexpected call\n");
767 return E_NOTIMPL;
770 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
771 BindStatusCallback_QueryInterface,
772 BindStatusCallback_AddRef,
773 BindStatusCallback_Release,
774 BindStatusCallback_OnStartBinding,
775 BindStatusCallback_GetPriority,
776 BindStatusCallback_OnLowResource,
777 BindStatusCallback_OnProgress,
778 BindStatusCallback_OnStopBinding,
779 BindStatusCallback_GetBindInfo,
780 BindStatusCallback_OnDataAvailable,
781 BindStatusCallback_OnObjectAvailable
784 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
786 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
788 *ppv = NULL;
790 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
791 return E_NOINTERFACE;
794 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
796 return 2;
799 static ULONG WINAPI Moniker_Release(IMoniker *iface)
801 return 1;
804 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
806 ok(0, "unexpected call\n");
807 return E_NOTIMPL;
810 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
812 ok(0, "unexpected call\n");
813 return E_NOTIMPL;
816 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
818 ok(0, "unexpected call\n");
819 return E_NOTIMPL;
822 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
824 ok(0, "unexpected call\n");
825 return E_NOTIMPL;
828 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
830 ok(0, "unexpected call\n");
831 return E_NOTIMPL;
834 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
835 REFIID riidResult, void **ppvResult)
837 ok(0, "unexpected call\n");
838 return E_NOTIMPL;
841 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
842 REFIID riid, void **ppv)
844 IUnknown *unk;
845 HRESULT hres;
847 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
849 CHECK_EXPECT(BindToStorage);
851 ok(pbc == _bctx, "pbc != _bctx\n");
852 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
853 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
854 ok(ppv != NULL, "ppv == NULL\n");
855 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
857 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
858 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
859 ok(unk != NULL, "unk == NULL\n");
861 IUnknown_Release(unk);
863 return S_OK;
866 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
867 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
869 ok(0, "unexpected call\n");
870 return E_NOTIMPL;
873 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
874 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
876 ok(0, "unexpected call\n");
877 return E_NOTIMPL;
880 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
882 ok(0, "unexpected call\n");
883 return E_NOTIMPL;
886 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
888 ok(0, "unexpected call\n");
889 return E_NOTIMPL;
892 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
894 ok(0, "unexpected call\n");
895 return E_NOTIMPL;
898 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
899 IMoniker *pmkNewlyRunning)
901 ok(0, "unexpected call\n");
902 return E_NOTIMPL;
905 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
906 IMoniker *pmkToLeft, FILETIME *pFileTime)
908 ok(0, "unexpected call\n");
909 return E_NOTIMPL;
912 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
914 ok(0, "unexpected call\n");
915 return E_NOTIMPL;
918 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
919 IMoniker **ppmkPrefix)
921 ok(0, "unexpected call\n");
922 return E_NOTIMPL;
925 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
926 IMoniker **pmkRelPath)
928 ok(0, "unexpected call\n");
929 return E_NOTIMPL;
932 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
933 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
935 static const WCHAR winehq_urlW[] =
936 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
937 '/','s','i','t','e','/','a','b','o','u','t',0};
939 CHECK_EXPECT(GetDisplayName);
941 ok(pbc != NULL, "pbc == NULL\n");
942 ok(pbc != _bctx, "pbc == _bctx\n");
943 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
945 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
946 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
947 return S_OK;
950 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
951 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
953 ok(0, "unexpected call\n");
954 return E_NOTIMPL;
957 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
959 CHECK_EXPECT2(IsSystemMoniker);
961 *pdwMksys = MKSYS_URLMONIKER;
962 return S_OK;
965 static IMonikerVtbl MonikerVtbl = {
966 Moniker_QueryInterface,
967 Moniker_AddRef,
968 Moniker_Release,
969 Moniker_GetClassID,
970 Moniker_IsDirty,
971 Moniker_Load,
972 Moniker_Save,
973 Moniker_GetSizeMax,
974 Moniker_BindToObject,
975 Moniker_BindToStorage,
976 Moniker_Reduce,
977 Moniker_ComposeWith,
978 Moniker_Enum,
979 Moniker_IsEqual,
980 Moniker_Hash,
981 Moniker_IsRunning,
982 Moniker_GetTimeOfLastChange,
983 Moniker_Inverse,
984 Moniker_CommonPrefixWith,
985 Moniker_RelativePathTo,
986 Moniker_GetDisplayName,
987 Moniker_ParseDisplayName,
988 Moniker_IsSystemMoniker
991 static IMoniker Moniker = { &MonikerVtbl };
993 static void test_HlinkResolveMonikerForData(void)
995 IBindCtx *bctx;
996 HRESULT hres;
998 CreateBindCtx(0, &bctx);
999 _bctx = bctx;
1001 SET_EXPECT(IsSystemMoniker);
1002 SET_EXPECT(GetDisplayName);
1003 SET_EXPECT(BindToStorage);
1005 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
1006 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
1008 CHECK_CALLED(IsSystemMoniker);
1009 CHECK_CALLED(GetDisplayName);
1010 CHECK_CALLED(BindToStorage);
1012 IBindCtx_Release(bctx);
1015 START_TEST(hlink)
1017 CoInitialize(NULL);
1019 test_HlinkIsShortcut();
1020 test_reference();
1021 test_persist();
1022 test_special_reference();
1023 test_HlinkCreateExtensionServices();
1024 test_HlinkParseDisplayName();
1025 test_HlinkResolveMonikerForData();
1027 CoUninitialize();