[HLINK_WINETEST]
[reactos.git] / rostests / winetests / hlink / hlink.c
1 /*
2 * Implementation of hyperlinking (hlink.dll)
3 *
4 * Copyright 2006 Mike McCormack
5 * Copyright 2007-2008 Jacek Caban for CodeWeavers
6 *
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.
11 *
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.
16 *
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
20 */
21
22 #define COBJMACROS
23
24 #include <stdio.h>
25
26 #include <initguid.h>
27 #include <hlink.h>
28 #include <hlguids.h>
29
30 #include "wine/test.h"
31
32 #define DEFINE_EXPECT(func) \
33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
34
35 #define SET_EXPECT(func) \
36 expect_ ## func = TRUE
37
38 #define CHECK_EXPECT2(func) \
39 do { \
40 ok(expect_ ##func, "unexpected call " #func "\n"); \
41 called_ ## func = TRUE; \
42 }while(0)
43
44 #define CHECK_EXPECT(func) \
45 do { \
46 CHECK_EXPECT2(func); \
47 expect_ ## func = FALSE; \
48 }while(0)
49
50 #define CHECK_CALLED(func) \
51 do { \
52 ok(called_ ## func, "expected " #func "\n"); \
53 expect_ ## func = called_ ## func = FALSE; \
54 }while(0)
55
56 DEFINE_EXPECT(IsSystemMoniker);
57 DEFINE_EXPECT(BindToStorage);
58 DEFINE_EXPECT(BindToObject);
59 DEFINE_EXPECT(GetDisplayName);
60
61 DEFINE_EXPECT(ComposeWith);
62 DEFINE_EXPECT(OnNavigationComplete);
63 DEFINE_EXPECT(Enum);
64 DEFINE_EXPECT(Reduce);
65
66 DEFINE_EXPECT(GetClassID);
67 DEFINE_EXPECT(Save);
68
69 DEFINE_EXPECT(HBC_QueryInterface_IHlinkHistory);
70 DEFINE_EXPECT(HBC_GetObject);
71 DEFINE_EXPECT(HBC_UpdateHlink);
72
73 DEFINE_EXPECT(HT_SetBrowseContext);
74 DEFINE_EXPECT(HT_GetBrowseContext);
75 DEFINE_EXPECT(HT_Navigate);
76 DEFINE_EXPECT(HT_GetFriendlyName);
77
78 DEFINE_EXPECT(HLF_UpdateHlink);
79
80 DEFINE_GUID(IID_IHlinkHistory,0x79eac9c8,0xbaf9,0x11ce,0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b);
81
82 static const char *debugstr_guid(REFIID riid)
83 {
84 static char buf[50];
85
86 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
87 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
88 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
89 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
90
91 return buf;
92 }
93
94 static void test_HlinkIsShortcut(void)
95 {
96 UINT i;
97 HRESULT hres;
98
99 static const WCHAR file0[] = {'f','i','l','e',0};
100 static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
101 static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
102 static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
103 static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
104 static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
105 static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
106 static const WCHAR file7[] = {'.','u','r','l',0};
107
108 static struct {
109 LPCWSTR file;
110 HRESULT hres;
111 } shortcut_test[] = {
112 {file0, S_FALSE},
113 {file1, S_OK},
114 {file2, S_FALSE},
115 {file3, S_OK},
116 {file4, S_FALSE},
117 {file5, S_OK},
118 {file6, S_FALSE},
119 {file7, S_OK},
120 {NULL, E_INVALIDARG}
121 };
122
123 for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
124 hres = HlinkIsShortcut(shortcut_test[i].file);
125 ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
126 i, hres, shortcut_test[i].hres);
127 }
128 }
129
130 static void test_reference(void)
131 {
132 HRESULT r;
133 IHlink *lnk = NULL;
134 IMoniker *mk = NULL;
135 const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
136 const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
137 LPWSTR str = NULL;
138
139 r = HlinkCreateFromString(url, NULL, NULL, NULL,
140 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
141 ok(r == S_OK, "failed to create link\n");
142 if (FAILED(r))
143 return;
144
145 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
146 ok(r == S_OK, "failed\n");
147
148 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
149 ok(r == S_OK, "failed\n");
150 ok(mk != NULL, "no moniker\n");
151 ok(str == NULL, "string should be null\n");
152
153 r = IMoniker_Release(mk);
154 ok( r == 1, "moniker refcount wrong\n");
155
156 r = IHlink_GetStringReference(lnk, -1, &str, NULL);
157 ok(r == S_OK, "failed\n");
158 CoTaskMemFree(str);
159
160 r = IHlink_GetStringReference(lnk, -1, NULL, NULL);
161 ok(r == S_OK, "failed, r=%08x\n", r);
162
163 r = IHlink_GetStringReference(lnk, -1, NULL, &str);
164 ok(r == S_OK, "failed, r=%08x\n", r);
165 ok(str == NULL, "string should be null\n");
166
167 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
168 ok(r == S_OK, "failed\n");
169 ok(!lstrcmpW(str, url2), "url wrong\n");
170 CoTaskMemFree(str);
171
172 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
173 ok(r == S_OK, "failed\n");
174
175 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
176 ok(r == S_OK, "failed\n");
177 ok(str == NULL, "string should be null\n");
178
179 /* Unimplented functions checks */
180 r = IHlink_GetAdditionalParams(lnk, NULL);
181 ok(r == E_NOTIMPL, "failed\n");
182
183 r = IHlink_SetAdditionalParams(lnk, NULL);
184 ok(r == E_NOTIMPL, "failed\n");
185
186 IHlink_Release(lnk);
187 }
188
189 /* url only */
190 static const unsigned char expected_hlink_data[] =
191 {
192 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
193 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
194 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
195 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
196 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
197 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
198 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
199 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
200 0x00,0x00,
201 };
202
203 /* url only (IE7) */
204 static const unsigned char expected_hlink_data_ie7[] =
205 {
206 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
207 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
208 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
209 0x3e,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
210 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
211 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
212 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
213 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
214 0x00,0x00,0x79,0x58,0x81,0xf4,0x3b,0x1d,
215 0x7f,0x48,0xaf,0x2c,0x82,0x5d,0xc4,0x85,
216 0x27,0x63,0x00,0x00,0x00,0x00,0xa5,0xab,
217 0x00,0x00,
218 };
219
220 /* url + friendly name */
221 static const unsigned char expected_hlink_data2[] =
222 {
223 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
224 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
225 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
226 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
227 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
228 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
229 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
230 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
231 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
232 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
233 0x67,0x00,0x2f,0x00,0x00,0x00,
234 };
235
236 /* url + friendly name (IE7) */
237 static const unsigned char expected_hlink_data2_ie7[] =
238 {
239 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
240 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
241 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
242 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
243 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
244 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
245 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
246 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
247 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
248 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
249 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
250 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
251 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
252 0x00,0x00,0xa5,0xab,0x00,0x00,
253 };
254
255 /* url + friendly name + location */
256 static const unsigned char expected_hlink_data3[] =
257 {
258 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
259 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
260 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
261 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
262 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
263 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
264 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
265 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
266 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
267 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
268 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
269 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
270 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
271 };
272
273 /* url + friendly name + location (IE7) */
274 static const unsigned char expected_hlink_data3_ie7[] =
275 {
276 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
277 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
278 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
279 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
280 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
281 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
282 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
283 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
284 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
285 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
286 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
287 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
288 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
289 0x00,0x00,0xa5,0xab,0x00,0x00,0x07,0x00,
290 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
291 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
292 };
293
294 /* relative url */
295 static const unsigned char expected_hlink_data4[] =
296 {
297 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
298 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
299 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
300 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
301 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
302 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
303 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
304 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
305 0x00,0x00,0x00,0x00,0x00,
306 };
307
308 /* url + target frame name */
309 static const unsigned char expected_hlink_data5[] =
310 {
311 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
312 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
313 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
314 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
315 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
316 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
317 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
318 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
319 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
320 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
321 0x2f,0x00,0x00,0x00,
322 };
323
324 /* url + target frame name (IE7) */
325 static const unsigned char expected_hlink_data5_ie7[] =
326 {
327 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
328 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
329 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
330 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
331 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
332 0xa9,0x0b,0x3e,0x00,0x00,0x00,0x68,0x00,
333 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
334 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
335 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
336 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
337 0x2f,0x00,0x00,0x00,0x79,0x58,0x81,0xf4,
338 0x3b,0x1d,0x7f,0x48,0xaf,0x2c,0x82,0x5d,
339 0xc4,0x85,0x27,0x63,0x00,0x00,0x00,0x00,
340 0xa5,0xab,0x00,0x00,
341 };
342
343 /* filename */
344 static const unsigned char expected_hlink_data6[] =
345 {
346 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
347 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
348 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
349 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
350 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
351 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
352 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
353 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
354 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
355 0x5c,0x00,
356 };
357
358 static void test_persist_save_data(const char *testname, IHlink *lnk,
359 const unsigned char *expected_data,
360 unsigned int expected_data_size,
361 const unsigned char *expected_data_alt,
362 unsigned int expected_data_alt_size)
363 {
364 HRESULT hr;
365 IStream *stream;
366 IPersistStream *ps;
367 HGLOBAL hglobal;
368 DWORD data_size;
369 const unsigned char *data;
370 DWORD i;
371 BOOL same;
372
373 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
374 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
375
376 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
377 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
378
379 hr = IPersistStream_Save(ps, stream, TRUE);
380 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
381
382 hr = GetHGlobalFromStream(stream, &hglobal);
383 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
384
385 data_size = GlobalSize(hglobal);
386
387 data = GlobalLock(hglobal);
388
389 /* first check we have the right amount of data */
390 ok((data_size == expected_data_size) ||
391 (data_size == expected_data_alt_size),
392 "%s: Size of saved data differs (expected %d or %d, actual %d)\n",
393 testname, expected_data_size, expected_data_alt_size, data_size);
394
395 same = TRUE;
396 /* then do a byte-by-byte comparison */
397 for (i = 0; i < min(data_size, expected_data_size); i++)
398 {
399 if ((expected_data[i] != data[i]) &&
400 (((expected_data != expected_hlink_data2) &&
401 (expected_data != expected_hlink_data3)) ||
402 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
403 {
404 same = FALSE;
405 break;
406 }
407 }
408
409 if (!same && (expected_data_alt != expected_data))
410 {
411 /* then try the alternate data */
412 same = TRUE;
413 for (i = 0; i < min(data_size, expected_data_alt_size); i++)
414 {
415 if ((expected_data_alt[i] != data[i]) &&
416 (((expected_data_alt != expected_hlink_data2) &&
417 (expected_data_alt != expected_hlink_data3)) ||
418 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
419 {
420 same = FALSE;
421 break;
422 }
423 }
424 }
425
426 ok(same, "%s: Saved data differs\n", testname);
427 if (!same)
428 {
429 for (i = 0; i < data_size; i++)
430 {
431 if (i % 8 == 0) printf(" ");
432 printf("0x%02x,", data[i]);
433 if (i % 8 == 7) printf("\n");
434 }
435 printf("\n");
436 }
437
438 GlobalUnlock(hglobal);
439
440 IStream_Release(stream);
441 IPersistStream_Release(ps);
442 }
443
444 static void test_persist(void)
445 {
446 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
447 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
448 static const WCHAR filename[] = { 'c',':','\\',0 };
449 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
450 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
451 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
452 HRESULT hr;
453 IHlink *lnk;
454
455 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
456 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
457 ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr);
458 if (!lnk) {
459 skip("Can't create lnk, skipping test_persist.\n");
460 return;
461 }
462 test_persist_save_data("url only", lnk,
463 expected_hlink_data, sizeof(expected_hlink_data),
464 expected_hlink_data_ie7, sizeof(expected_hlink_data_ie7));
465 IHlink_Release(lnk);
466
467 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
468 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
469 ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr);
470 test_persist_save_data("url + friendly name", lnk,
471 expected_hlink_data2, sizeof(expected_hlink_data2),
472 expected_hlink_data2_ie7, sizeof(expected_hlink_data2_ie7));
473 IHlink_Release(lnk);
474
475 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
476 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
477 ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr);
478 test_persist_save_data("url + friendly_name + location", lnk,
479 expected_hlink_data3, sizeof(expected_hlink_data3),
480 expected_hlink_data3_ie7, sizeof(expected_hlink_data3_ie7));
481 IHlink_Release(lnk);
482
483 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
484 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
485 ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr);
486 test_persist_save_data("relative url", lnk,
487 expected_hlink_data4, sizeof(expected_hlink_data4),
488 expected_hlink_data4, sizeof(expected_hlink_data4));
489 IHlink_Release(lnk);
490
491 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
492 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
493 ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr);
494 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
495 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
496 test_persist_save_data("url + target frame name", lnk,
497 expected_hlink_data5, sizeof(expected_hlink_data5),
498 expected_hlink_data5_ie7, sizeof(expected_hlink_data5_ie7));
499 IHlink_Release(lnk);
500
501 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
502 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
503 ok(hr == S_OK, "HlinkCreateFromString failed with error 0x%08x\n", hr);
504 test_persist_save_data("filename", lnk,
505 expected_hlink_data6, sizeof(expected_hlink_data6),
506 expected_hlink_data6, sizeof(expected_hlink_data6));
507 IHlink_Release(lnk);
508 }
509
510 static void test_special_reference(void)
511 {
512 LPWSTR ref;
513 HRESULT hres;
514
515 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
516 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
517 ok(ref != NULL, "ref == NULL\n");
518 CoTaskMemFree(ref);
519
520 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
521 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
522 ok(ref != NULL, "ref == NULL\n");
523 CoTaskMemFree(ref);
524
525 ref = (void*)0xdeadbeef;
526 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
527 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
528 ok(ref == NULL, "ref=%p\n", ref);
529
530 ref = (void*)0xdeadbeef;
531 hres = HlinkGetSpecialReference(4, &ref);
532 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
533 ok(ref == NULL, "ref=%p\n", ref);
534 }
535
536 static void test_HlinkCreateExtensionServices(void)
537 {
538 IAuthenticate *authenticate;
539 IHttpNegotiate *http_negotiate;
540 LPWSTR password, username, headers;
541 HWND hwnd;
542 HRESULT hres;
543
544 static const WCHAR usernameW[] = {'u','s','e','r',0};
545 static const WCHAR passwordW[] = {'p','a','s','s',0};
546 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
547 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
548
549 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
550 NULL, &IID_IAuthenticate, (void**)&authenticate);
551 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
552 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
553
554 password = username = (void*)0xdeadbeef;
555 hwnd = (void*)0xdeadbeef;
556 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
557 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
558 ok(!hwnd, "hwnd != NULL\n");
559 ok(!username, "username != NULL\n");
560 ok(!password, "password != NULL\n");
561
562 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
563 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
564
565 headers = (void*)0xdeadbeef;
566 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
567 0, &headers);
568 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
569 ok(headers == NULL, "headers != NULL\n");
570
571 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
572 0, NULL);
573 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
574
575 headers = (void*)0xdeadbeef;
576 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
577 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
578 ok(headers == NULL, "headers != NULL\n");
579
580 IHttpNegotiate_Release(http_negotiate);
581 IAuthenticate_Release(authenticate);
582
583
584 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
585 NULL, &IID_IAuthenticate, (void**)&authenticate);
586 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
587 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
588
589 password = username = NULL;
590 hwnd = NULL;
591 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
592 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
593 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
594 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
595 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
596 CoTaskMemFree(username);
597 CoTaskMemFree(password);
598
599 password = username = (void*)0xdeadbeef;
600 hwnd = (void*)0xdeadbeef;
601 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
602 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
603 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
604 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
605
606 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
607 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
608
609 headers = (void*)0xdeadbeef;
610 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
611 0, &headers);
612 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
613 ok(!lstrcmpW(headers, headersexW), "unexpected headers %s\n", wine_dbgstr_w(headers));
614 CoTaskMemFree(headers);
615
616 headers = (void*)0xdeadbeef;
617 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
618 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
619 ok(headers == NULL, "unexpected headers %s\n", wine_dbgstr_w(headers));
620
621 IHttpNegotiate_Release(http_negotiate);
622 IAuthenticate_Release(authenticate);
623 }
624
625 static void test_HlinkParseDisplayName(void)
626 {
627 IMoniker *mon = NULL;
628 LPWSTR name;
629 DWORD issys;
630 ULONG eaten = 0;
631 IBindCtx *bctx;
632 HRESULT hres;
633
634 static const WCHAR winehq_urlW[] =
635 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
636 '/','s','i','t','e','/','a','b','o','u','t',0};
637 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
638 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
639 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
640 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
641
642 CreateBindCtx(0, &bctx);
643
644 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
645 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
646 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
647 ok(mon != NULL, "mon == NULL\n");
648
649 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
650 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
651 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
652 CoTaskMemFree(name);
653
654 hres = IMoniker_IsSystemMoniker(mon, &issys);
655 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
656 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
657
658 IMoniker_Release(mon);
659
660 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
661 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
662 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
663 ok(mon != NULL, "mon == NULL\n");
664
665 hres = IMoniker_IsSystemMoniker(mon, &issys);
666 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
667 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
668
669 IMoniker_Release(mon);
670
671 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
672 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
673 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
674 ok(mon != NULL, "mon == NULL\n");
675
676 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
677 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
678 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
679 CoTaskMemFree(name);
680
681 hres = IMoniker_IsSystemMoniker(mon, &issys);
682 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
683 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
684
685 IMoniker_Release(mon);
686 IBindCtx_Release(bctx);
687 }
688
689 static IBindCtx *_bctx;
690
691 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
692 {
693 ok(0, "unexpected call\n");
694 return E_NOINTERFACE;
695 }
696
697 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
698 {
699 return 2;
700 }
701
702 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
703 {
704 return 1;
705 }
706
707 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
708 REFGUID guidService, REFIID riid, void **ppv)
709 {
710 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
711 return E_NOINTERFACE;
712 }
713
714 static IServiceProviderVtbl ServiceProviderVtbl = {
715 ServiceProvider_QueryInterface,
716 ServiceProvider_AddRef,
717 ServiceProvider_Release,
718 ServiceProvider_QueryService
719 };
720
721 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
722
723 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
724 {
725 *ppv = NULL;
726
727 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
728 *ppv = &ServiceProvider;
729 return S_OK;
730 }
731
732 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
733 return E_NOINTERFACE;
734 }
735
736 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
737 {
738 return 2;
739 }
740
741 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
742 {
743 return 1;
744 }
745
746 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
747 IBinding *pib)
748 {
749 ok(0, "unexpected call\n");
750 return E_NOTIMPL;
751 }
752
753 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
754 {
755 ok(0, "unexpected call\n");
756 return E_NOTIMPL;
757 }
758
759 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
760 {
761 ok(0, "unexpected call\n");
762 return E_NOTIMPL;
763 }
764
765 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
766 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
767 {
768 ok(0, "unexpected call\n");
769 return E_NOTIMPL;
770 }
771
772 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
773 {
774 ok(0, "unexpected call\n");
775 return E_NOTIMPL;
776 }
777
778 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
779 {
780 ok(0, "unexpected call\n");
781 return E_NOTIMPL;
782 }
783
784 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
785 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
786 {
787 ok(0, "unexpected call\n");
788 return E_NOTIMPL;
789 }
790
791 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
792 {
793 ok(0, "unexpected call\n");
794 return E_NOTIMPL;
795 }
796
797 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
798 BindStatusCallback_QueryInterface,
799 BindStatusCallback_AddRef,
800 BindStatusCallback_Release,
801 BindStatusCallback_OnStartBinding,
802 BindStatusCallback_GetPriority,
803 BindStatusCallback_OnLowResource,
804 BindStatusCallback_OnProgress,
805 BindStatusCallback_OnStopBinding,
806 BindStatusCallback_GetBindInfo,
807 BindStatusCallback_OnDataAvailable,
808 BindStatusCallback_OnObjectAvailable
809 };
810
811 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
812
813 static HRESULT WINAPI HlinkBrowseContext_QueryInterface(
814 IHlinkBrowseContext *iface, REFIID riid, void **ppv)
815 {
816 *ppv = NULL;
817
818 if(IsEqualGUID(&IID_IHlinkHistory, riid)) {
819 CHECK_EXPECT(HBC_QueryInterface_IHlinkHistory);
820 return E_NOINTERFACE;
821 }
822
823 ok(0, "unexpected interface: %s\n", debugstr_guid(riid));
824 return E_NOINTERFACE;
825 }
826
827 static ULONG WINAPI HlinkBrowseContext_AddRef(IHlinkBrowseContext *iface)
828 {
829 return 2;
830 }
831
832 static ULONG WINAPI HlinkBrowseContext_Release(IHlinkBrowseContext *iface)
833 {
834 return 1;
835 }
836
837 static HRESULT WINAPI HlinkBrowseContext_Register(IHlinkBrowseContext *iface,
838 DWORD reserved, IUnknown *piunk, IMoniker *pimk, DWORD *pdwRegister)
839 {
840 ok(0, "unexpected call\n");
841 return E_NOTIMPL;
842 }
843
844 static IMoniker Moniker;
845 static HRESULT WINAPI HlinkBrowseContext_GetObject(IHlinkBrowseContext *iface,
846 IMoniker *pimk, BOOL fBindIfRootRegistered, IUnknown **ppiunk)
847 {
848 CHECK_EXPECT(HBC_GetObject);
849
850 ok(pimk == &Moniker, "pimk != &Moniker\n");
851 ok(fBindIfRootRegistered == 1, "fBindIfRootRegistered = %x\n", fBindIfRootRegistered);
852 *ppiunk = NULL;
853 return S_FALSE;
854 }
855
856 static HRESULT WINAPI HlinkBrowseContext_Revoke(IHlinkBrowseContext *iface, DWORD dwRegister)
857 {
858 ok(0, "unexpected call\n");
859 return E_NOTIMPL;
860 }
861
862 static HRESULT WINAPI HlinkBrowseContext_SetBrowseWindowInfo(
863 IHlinkBrowseContext *iface, HLBWINFO *phlbwi)
864 {
865 ok(0, "unexpected call\n");
866 return E_NOTIMPL;
867 }
868
869 static HRESULT WINAPI HlinkBrowseContext_GetBrowseWindowInfo(
870 IHlinkBrowseContext *iface, HLBWINFO *phlbwi)
871 {
872 ok(0, "unexpected call\n");
873 return E_NOTIMPL;
874 }
875
876 static HRESULT WINAPI HlinkBrowseContext_SetInitialHlink(IHlinkBrowseContext *iface,
877 IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
878 {
879 ok(0, "unexpected call\n");
880 return E_NOTIMPL;
881 }
882
883 static HRESULT WINAPI HlinkBrowseContext_OnNavigateHlink(IHlinkBrowseContext *iface, DWORD grfHLNF,
884 IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, ULONG *puHLID)
885 {
886 ok(0, "unexpected call\n");
887 return E_NOTIMPL;
888 }
889
890 static HRESULT WINAPI HlinkBrowseContext_UpdateHlink(IHlinkBrowseContext *iface, ULONG uHLID,
891 IMoniker *pimkTarget, LPCWSTR location, LPCWSTR friendly_name)
892 {
893 CHECK_EXPECT(HBC_UpdateHlink);
894 return S_OK;
895 }
896
897 static HRESULT WINAPI HlinkBrowseContext_EnumNavigationStack(IHlinkBrowseContext *iface,
898 DWORD dwReserved, DWORD grfHLFNAMEF, IEnumHLITEM **ppienumhlitem)
899 {
900 ok(0, "unexpected call\n");
901 return E_NOTIMPL;
902 }
903
904 static HRESULT WINAPI HlinkBrowseContext_QueryHlink(IHlinkBrowseContext *iface,
905 DWORD grfHLQF, ULONG uHLID)
906 {
907 ok(0, "unexpected call\n");
908 return E_NOTIMPL;
909 }
910
911 static HRESULT WINAPI HlinkBrowseContext_GetHlink(IHlinkBrowseContext *iface,
912 ULONG uHLID, IHlink **ppihl)
913 {
914 ok(0, "unexpected call\n");
915 return E_NOTIMPL;
916 }
917
918 static HRESULT WINAPI HlinkBrowseContext_SetCurrentHlink(
919 IHlinkBrowseContext *iface, ULONG uHLID)
920 {
921 ok(0, "unexpected call\n");
922 return E_NOTIMPL;
923 }
924
925 static HRESULT WINAPI HlinkBrowseContext_Clone(IHlinkBrowseContext *iface,
926 IUnknown *piunkOuter, REFIID riid, IUnknown **ppiunkObj)
927 {
928 ok(0, "unexpected call\n");
929 return E_NOTIMPL;
930 }
931
932 static HRESULT WINAPI HlinkBrowseContext_Close(IHlinkBrowseContext *iface, DWORD reserved)
933 {
934 ok(0, "unexpected call\n");
935 return E_NOTIMPL;
936 }
937
938 static IHlinkBrowseContextVtbl HlinkBrowseContextVtbl = {
939 HlinkBrowseContext_QueryInterface,
940 HlinkBrowseContext_AddRef,
941 HlinkBrowseContext_Release,
942 HlinkBrowseContext_Register,
943 HlinkBrowseContext_GetObject,
944 HlinkBrowseContext_Revoke,
945 HlinkBrowseContext_SetBrowseWindowInfo,
946 HlinkBrowseContext_GetBrowseWindowInfo,
947 HlinkBrowseContext_SetInitialHlink,
948 HlinkBrowseContext_OnNavigateHlink,
949 HlinkBrowseContext_UpdateHlink,
950 HlinkBrowseContext_EnumNavigationStack,
951 HlinkBrowseContext_QueryHlink,
952 HlinkBrowseContext_GetHlink,
953 HlinkBrowseContext_SetCurrentHlink,
954 HlinkBrowseContext_Clone,
955 HlinkBrowseContext_Close
956 };
957
958 static IHlinkBrowseContext HlinkBrowseContext = { &HlinkBrowseContextVtbl };
959
960 static HRESULT WINAPI HlinkTarget_QueryInterface(IHlinkTarget *iface, REFIID riid, void **ppv)
961 {
962 if(IsEqualGUID(&IID_IHlinkTarget, riid)) {
963 *ppv = iface;
964 return S_OK;
965 }
966
967 ok(0, "unexpected interface: %s\n", debugstr_guid(riid));
968 return E_NOINTERFACE;
969 }
970
971 static ULONG WINAPI HlinkTarget_AddRef(IHlinkTarget *iface)
972 {
973 return 2;
974 }
975
976 static ULONG WINAPI HlinkTarget_Release(IHlinkTarget *iface)
977 {
978 return 1;
979 }
980
981 static HRESULT WINAPI HlinkTarget_SetBrowseContext(IHlinkTarget *iface,
982 IHlinkBrowseContext *pihlbc)
983 {
984 CHECK_EXPECT(HT_SetBrowseContext);
985
986 ok(pihlbc == &HlinkBrowseContext, "pihlbc != &HlinkBrowseContext (%p)\n", pihlbc);
987 return S_OK;
988 }
989
990 static HRESULT WINAPI HlinkTarget_GetBrowseContext(IHlinkTarget *iface,
991 IHlinkBrowseContext **ppihlbc)
992 {
993 CHECK_EXPECT(HT_GetBrowseContext);
994
995 *ppihlbc = NULL;
996 return S_OK;
997 }
998
999 static HRESULT WINAPI HlinkTarget_Navigate(IHlinkTarget *iface,
1000 DWORD grfHLNF, LPCWSTR pwzJumpLocation)
1001 {
1002 CHECK_EXPECT(HT_Navigate);
1003
1004 ok(grfHLNF == 0, "grfHLNF = %x\n", grfHLNF);
1005 ok(pwzJumpLocation == NULL, "pwzJumpLocation = %s\n", wine_dbgstr_w(pwzJumpLocation));
1006 return S_OK;
1007 }
1008
1009 static HRESULT WINAPI HlinkTarget_GetMoniker(IHlinkTarget *iface,
1010 LPCWSTR pwzLocation, DWORD dwAssign, IMoniker **ppimkLocation)
1011 {
1012 ok(0, "unexpected call\n");
1013 return E_NOTIMPL;
1014 }
1015
1016 static HRESULT WINAPI HlinkTarget_GetFriendlyName(IHlinkTarget *iface,
1017 LPCWSTR pwzLocation, LPWSTR *ppwzFriendlyName)
1018 {
1019 CHECK_EXPECT(HT_GetFriendlyName);
1020 return E_NOTIMPL;
1021 }
1022
1023 static IHlinkTargetVtbl HlinkTargetVtbl = {
1024 HlinkTarget_QueryInterface,
1025 HlinkTarget_AddRef,
1026 HlinkTarget_Release,
1027 HlinkTarget_SetBrowseContext,
1028 HlinkTarget_GetBrowseContext,
1029 HlinkTarget_Navigate,
1030 HlinkTarget_GetMoniker,
1031 HlinkTarget_GetFriendlyName
1032 };
1033
1034 static IHlinkTarget HlinkTarget = { &HlinkTargetVtbl };
1035
1036 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
1037 {
1038 *ppv = NULL;
1039
1040 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
1041 return E_NOINTERFACE;
1042 }
1043
1044 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
1045 {
1046 return 2;
1047 }
1048
1049 static ULONG WINAPI Moniker_Release(IMoniker *iface)
1050 {
1051 return 1;
1052 }
1053
1054 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
1055 {
1056 CHECK_EXPECT(GetClassID);
1057 *pClassID = IID_IUnknown; /* not a valid CLSID */
1058 return S_OK;
1059 }
1060
1061 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
1062 {
1063 ok(0, "unexpected call\n");
1064 return E_NOTIMPL;
1065 }
1066
1067 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
1068 {
1069 ok(0, "unexpected call\n");
1070 return E_NOTIMPL;
1071 }
1072
1073 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
1074 {
1075 CHECK_EXPECT(Save);
1076 return S_OK;
1077 }
1078
1079 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
1080 {
1081 ok(0, "unexpected call\n");
1082 return E_NOTIMPL;
1083 }
1084
1085 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
1086 REFIID riid, void **ppv)
1087 {
1088 CHECK_EXPECT(BindToObject);
1089
1090 ok(pbc != _bctx, "pbc != _bctx\n");
1091 ok(pmkToLeft == NULL, "pmkToLeft = %p\n", pmkToLeft);
1092 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
1093 ok(ppv != NULL, "ppv == NULL\n");
1094 ok(*ppv == NULL, "*ppv = %p\n", *ppv);
1095
1096 *ppv = &HlinkTarget;
1097 return S_OK;
1098 }
1099
1100 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
1101 REFIID riid, void **ppv)
1102 {
1103 IUnknown *unk;
1104 HRESULT hres;
1105
1106 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
1107
1108 CHECK_EXPECT(BindToStorage);
1109
1110 ok(pbc == _bctx, "pbc != _bctx\n");
1111 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
1112 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
1113 ok(ppv != NULL, "ppv == NULL\n");
1114 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
1115
1116 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
1117 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
1118 ok(unk != NULL, "unk == NULL\n");
1119
1120 IUnknown_Release(unk);
1121
1122 return S_OK;
1123 }
1124
1125 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
1126 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
1127 {
1128 CHECK_EXPECT(Reduce);
1129 return E_NOTIMPL;
1130 }
1131
1132 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
1133 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
1134 {
1135 ok(0, "unexpected call\n");
1136 return E_NOTIMPL;
1137 }
1138
1139 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
1140 {
1141 CHECK_EXPECT(Enum);
1142 return E_NOTIMPL;
1143 }
1144
1145 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
1146 {
1147 ok(0, "unexpected call\n");
1148 return E_NOTIMPL;
1149 }
1150
1151 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
1152 {
1153 ok(0, "unexpected call\n");
1154 return E_NOTIMPL;
1155 }
1156
1157 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
1158 IMoniker *pmkNewlyRunning)
1159 {
1160 ok(0, "unexpected call\n");
1161 return E_NOTIMPL;
1162 }
1163
1164 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
1165 IMoniker *pmkToLeft, FILETIME *pFileTime)
1166 {
1167 ok(0, "unexpected call\n");
1168 return E_NOTIMPL;
1169 }
1170
1171 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
1172 {
1173 ok(0, "unexpected call\n");
1174 return E_NOTIMPL;
1175 }
1176
1177 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
1178 IMoniker **ppmkPrefix)
1179 {
1180 ok(0, "unexpected call\n");
1181 return E_NOTIMPL;
1182 }
1183
1184 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
1185 IMoniker **pmkRelPath)
1186 {
1187 ok(0, "unexpected call\n");
1188 return E_NOTIMPL;
1189 }
1190
1191 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
1192 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
1193 {
1194 static const WCHAR winehq_urlW[] =
1195 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
1196 '/','s','i','t','e','/','a','b','o','u','t',0};
1197
1198 CHECK_EXPECT2(GetDisplayName);
1199
1200 ok(pbc != NULL, "pbc == NULL\n");
1201 ok(pbc != _bctx, "pbc == _bctx\n");
1202 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
1203
1204 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
1205 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
1206 return S_OK;
1207 }
1208
1209 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
1210 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
1211 {
1212 ok(0, "unexpected call\n");
1213 return E_NOTIMPL;
1214 }
1215
1216 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
1217 {
1218 CHECK_EXPECT2(IsSystemMoniker);
1219
1220 *pdwMksys = MKSYS_URLMONIKER;
1221 return S_OK;
1222 }
1223
1224 static IMonikerVtbl MonikerVtbl = {
1225 Moniker_QueryInterface,
1226 Moniker_AddRef,
1227 Moniker_Release,
1228 Moniker_GetClassID,
1229 Moniker_IsDirty,
1230 Moniker_Load,
1231 Moniker_Save,
1232 Moniker_GetSizeMax,
1233 Moniker_BindToObject,
1234 Moniker_BindToStorage,
1235 Moniker_Reduce,
1236 Moniker_ComposeWith,
1237 Moniker_Enum,
1238 Moniker_IsEqual,
1239 Moniker_Hash,
1240 Moniker_IsRunning,
1241 Moniker_GetTimeOfLastChange,
1242 Moniker_Inverse,
1243 Moniker_CommonPrefixWith,
1244 Moniker_RelativePathTo,
1245 Moniker_GetDisplayName,
1246 Moniker_ParseDisplayName,
1247 Moniker_IsSystemMoniker
1248 };
1249
1250 static IMoniker Moniker = { &MonikerVtbl };
1251
1252 static void test_HlinkResolveMonikerForData(void)
1253 {
1254 IBindCtx *bctx;
1255 HRESULT hres;
1256
1257 CreateBindCtx(0, &bctx);
1258 _bctx = bctx;
1259
1260 SET_EXPECT(IsSystemMoniker);
1261 SET_EXPECT(GetDisplayName);
1262 SET_EXPECT(BindToStorage);
1263
1264 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
1265 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
1266
1267 CHECK_CALLED(IsSystemMoniker);
1268 CHECK_CALLED(GetDisplayName);
1269 CHECK_CALLED(BindToStorage);
1270
1271 IBindCtx_Release(bctx);
1272 _bctx = NULL;
1273 }
1274
1275 static void test_HlinkGetSetMonikerReference(void)
1276 {
1277 IMoniker *found_trgt, *dummy, *dummy2;
1278 IHlink *hlink;
1279 HRESULT hres;
1280 const WCHAR one[] = {'1',0};
1281 const WCHAR two[] = {'2',0};
1282 const WCHAR name[] = {'a',0};
1283 WCHAR *found_loc;
1284
1285 /* create two dummy monikers to use as targets */
1286 hres = CreateItemMoniker(one, one, &dummy);
1287 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1288
1289 hres = CreateItemMoniker(two, two, &dummy2);
1290 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1291
1292 /* create a new hlink: target => dummy, location => one */
1293 hres = HlinkCreateFromMoniker(dummy, one, name, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1294 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1295
1296 /* validate the target and location */
1297 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1298 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1299 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1300 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1301 IMoniker_Release(found_trgt);
1302 CoTaskMemFree(found_loc);
1303
1304 /* set location => two */
1305 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_LOCATION, dummy2, two);
1306 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1307
1308 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1309 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1310 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1311 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1312 IMoniker_Release(found_trgt);
1313 CoTaskMemFree(found_loc);
1314
1315 /* set target => dummy2 */
1316 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, dummy2, one);
1317 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1318
1319 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1320 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1321 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1322 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1323 IMoniker_Release(found_trgt);
1324 CoTaskMemFree(found_loc);
1325
1326 /* set target => dummy, location => one */
1327 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, dummy, one);
1328 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1329
1330 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1331 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1332 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1333 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1334 IMoniker_Release(found_trgt);
1335 CoTaskMemFree(found_loc);
1336
1337 /* no HLINKSETF flags */
1338 hres = IHlink_SetMonikerReference(hlink, 0, dummy2, two);
1339 ok(hres == E_INVALIDARG, "IHlink_SetMonikerReference should've failed with E_INVALIDARG (0x%08x), failed with 0x%08x\n", E_INVALIDARG, hres);
1340
1341 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1342 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1343 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1344 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1345 IMoniker_Release(found_trgt);
1346 CoTaskMemFree(found_loc);
1347
1348 /* invalid HLINKSETF flags */
1349 /* Windows returns garbage; on 32-bit it returns the flags probably because the compiler happened to store them in %eax at some point */
1350 if (0)
1351 IHlink_SetMonikerReference(hlink, 12, dummy2, two);
1352
1353 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1354 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1355 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1356 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1357 IMoniker_Release(found_trgt);
1358 CoTaskMemFree(found_loc);
1359
1360 /* valid & invalid HLINKSETF flags */
1361 hres = IHlink_SetMonikerReference(hlink, 12 | HLINKSETF_TARGET, dummy2, two);
1362 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1363
1364 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1365 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1366 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1367 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1368 IMoniker_Release(found_trgt);
1369 CoTaskMemFree(found_loc);
1370
1371 /* NULL args */
1372 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, NULL, NULL);
1373 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1374
1375 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1376 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1377 ok(found_trgt == NULL, "Found target should've been %p, was: %p\n", NULL, found_trgt);
1378 ok(found_loc == NULL, "Found location should've been %s, was: %s\n", wine_dbgstr_w(NULL), wine_dbgstr_w(found_loc));
1379 if(found_trgt)
1380 IMoniker_Release(found_trgt);
1381
1382 IHlink_Release(hlink);
1383 IMoniker_Release(dummy2);
1384 IMoniker_Release(dummy);
1385
1386 SET_EXPECT(Reduce);
1387 SET_EXPECT(Enum);
1388 SET_EXPECT(IsSystemMoniker);
1389 SET_EXPECT(GetDisplayName);
1390 hres = HlinkCreateFromMoniker(&Moniker, NULL, NULL, NULL, 0, NULL,
1391 &IID_IHlink, (void **)&hlink);
1392 ok(hres == S_OK, "CreateFromMoniker failed: %08x\n", hres);
1393
1394 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_ABSOLUTE,
1395 &found_trgt, &found_loc);
1396 ok(hres == S_OK, "CreateFromMoniker failed: %08x\n", hres);
1397 ok(found_trgt == &Moniker, "Got unexpected moniker: %p\n", found_trgt);
1398 ok(found_loc == NULL, "Got unexpected location: %p\n", found_loc);
1399 todo_wine CHECK_CALLED(Reduce);
1400 todo_wine CHECK_CALLED(Enum);
1401 CHECK_CALLED(IsSystemMoniker);
1402 CHECK_CALLED(GetDisplayName);
1403
1404 IHlink_Release(hlink);
1405 }
1406
1407 static void test_HlinkGetSetStringReference(void)
1408 {
1409 IHlink *link;
1410 static const WCHAR one[] = {'1',0};
1411 static const WCHAR two[] = {'2',0};
1412 static const WCHAR three[] = {'3',0};
1413 static const WCHAR empty[] = {0};
1414 WCHAR *fnd_tgt, *fnd_loc;
1415 HRESULT hres;
1416
1417 /* create a new hlink: target => NULL, location => one */
1418 hres = HlinkCreateFromMoniker(NULL, one, empty, NULL, 0, NULL, &IID_IHlink, (void**)&link);
1419 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1420
1421 /* test setting/getting location */
1422 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1423 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1424 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1425 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1426 CoTaskMemFree(fnd_tgt);
1427 CoTaskMemFree(fnd_loc);
1428
1429 hres = IHlink_SetStringReference(link, HLINKSETF_LOCATION, one, two);
1430 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1431
1432 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1433 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1434 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1435 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1436 CoTaskMemFree(fnd_tgt);
1437 CoTaskMemFree(fnd_loc);
1438
1439 hres = IHlink_SetStringReference(link, -HLINKSETF_LOCATION, two, one);
1440 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1441
1442 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1443 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1444 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1445 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1446 CoTaskMemFree(fnd_tgt);
1447 CoTaskMemFree(fnd_loc);
1448
1449 /* test setting/getting target */
1450 hres = IHlink_SetStringReference(link, HLINKSETF_TARGET, two, three);
1451 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1452
1453 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1454 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1455 ok(!lstrcmpW(fnd_tgt, two), "Found target should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_tgt));
1456 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1457 CoTaskMemFree(fnd_tgt);
1458 CoTaskMemFree(fnd_loc);
1459
1460 hres = IHlink_SetStringReference(link, -HLINKSETF_TARGET, three, two);
1461 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1462
1463 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1464 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1465 ok(!lstrcmpW(fnd_tgt, three), "Found target should have been %s, was: %s\n", wine_dbgstr_w(three), wine_dbgstr_w(fnd_tgt));
1466 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1467 CoTaskMemFree(fnd_tgt);
1468 CoTaskMemFree(fnd_loc);
1469
1470 /* test setting/getting both */
1471 hres = IHlink_SetStringReference(link, HLINKSETF_TARGET | HLINKSETF_LOCATION, one, two);
1472 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1473
1474 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1475 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1476 ok(!lstrcmpW(fnd_tgt, one), "Found target should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_tgt));
1477 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1478 CoTaskMemFree(fnd_tgt);
1479 CoTaskMemFree(fnd_loc);
1480
1481 hres = IHlink_SetStringReference(link, -(HLINKSETF_TARGET | HLINKSETF_LOCATION), three, one);
1482 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1483
1484 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1485 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1486 ok(!lstrcmpW(fnd_tgt, three), "Found target should have been %s, was: %s\n", wine_dbgstr_w(three), wine_dbgstr_w(fnd_tgt));
1487 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1488 CoTaskMemFree(fnd_tgt);
1489 CoTaskMemFree(fnd_loc);
1490
1491 /* test invalid flags/params */
1492 hres = IHlink_GetStringReference(link, 4, &fnd_tgt, &fnd_loc);
1493 ok(hres == E_INVALIDARG, "IHlink_GetStringReference should have failed "
1494 "with E_INVALIDARG (0x%08x), instead: 0x%08x\n", E_INVALIDARG, hres);
1495 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1496 ok(fnd_loc == NULL, "Found location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1497 CoTaskMemFree(fnd_tgt);
1498 CoTaskMemFree(fnd_loc);
1499
1500 hres = IHlink_GetStringReference(link, -1, &fnd_tgt, NULL);
1501 todo_wine ok(hres == E_FAIL, "IHlink_GetStringReference should have failed "
1502 "with E_FAIL (0x%08x), instead: 0x%08x\n", E_FAIL, hres);
1503 CoTaskMemFree(fnd_tgt);
1504
1505 hres = IHlink_GetStringReference(link, -1, NULL, NULL);
1506 ok(hres == S_OK, "failed, hres=%08x\n", hres);
1507
1508 hres = IHlink_GetStringReference(link, -1, NULL, &fnd_loc);
1509 ok(hres == S_OK, "failed, hres=%08x\n", hres);
1510 CoTaskMemFree(fnd_loc);
1511
1512 hres = IHlink_GetStringReference(link, -1, &fnd_tgt, &fnd_loc);
1513 todo_wine ok(hres == E_FAIL, "IHlink_GetStringReference should have failed "
1514 "with E_FAIL (0x%08x), instead: 0x%08x\n", E_FAIL, hres);
1515 CoTaskMemFree(fnd_tgt);
1516 CoTaskMemFree(fnd_loc);
1517
1518 hres = IHlink_GetStringReference(link, -2, &fnd_tgt, &fnd_loc);
1519 ok(hres == E_INVALIDARG, "IHlink_GetStringReference should have failed "
1520 "with E_INVALIDARG (0x%08x), instead: 0x%08x\n", E_INVALIDARG, hres);
1521 CoTaskMemFree(fnd_tgt);
1522 CoTaskMemFree(fnd_loc);
1523
1524 if (0)
1525 {
1526 /* Windows returns garbage; on 32-bit it returns the flags probably because the compiler happened to store them in %eax at some point */
1527 IHlink_SetStringReference(link, 4, NULL, NULL);
1528 IHlink_SetStringReference(link, -4, NULL, NULL);
1529 }
1530
1531 IHlink_Release(link);
1532 }
1533
1534 #define setStringRef(h,f,t,l) r_setStringRef(__LINE__,h,f,t,l)
1535 static void r_setStringRef(unsigned line, IHlink *hlink, DWORD flags, const WCHAR *tgt, const WCHAR *loc)
1536 {
1537 HRESULT hres;
1538 hres = IHlink_SetStringReference(hlink, flags, tgt, loc);
1539 ok_(__FILE__,line) (hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1540 }
1541
1542 #define getStringRef(h,t,l) r_getStringRef(__LINE__,h,t,l)
1543 static void r_getStringRef(unsigned line, IHlink *hlink, const WCHAR *exp_tgt, const WCHAR *exp_loc)
1544 {
1545 HRESULT hres;
1546 WCHAR *fnd_tgt, *fnd_loc;
1547
1548 hres = IHlink_GetStringReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1549 ok_(__FILE__,line) (hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1550
1551 if(exp_tgt)
1552 ok_(__FILE__,line) (!lstrcmpW(fnd_tgt, exp_tgt), "Found string target should have been %s, was: %s\n", wine_dbgstr_w(exp_tgt), wine_dbgstr_w(fnd_tgt));
1553 else
1554 ok_(__FILE__,line) (fnd_tgt == NULL, "Found string target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1555
1556 if(exp_loc)
1557 ok_(__FILE__,line) (!lstrcmpW(fnd_loc, exp_loc), "Found string location should have been %s, was: %s\n", wine_dbgstr_w(exp_loc), wine_dbgstr_w(fnd_loc));
1558 else
1559 ok_(__FILE__,line) (fnd_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1560
1561 CoTaskMemFree(fnd_tgt);
1562 CoTaskMemFree(fnd_loc);
1563 }
1564
1565 #define setMonikerRef(h,f,t,l) r_setMonikerRef(__LINE__,h,f,t,l)
1566 static void r_setMonikerRef(unsigned line, IHlink *hlink, DWORD flags, IMoniker *tgt, const WCHAR *loc)
1567 {
1568 HRESULT hres;
1569 hres = IHlink_SetMonikerReference(hlink, flags, tgt, loc);
1570 ok_(__FILE__,line) (hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1571 }
1572
1573 /* passing 0xFFFFFFFF as exp_tgt will return the retrieved target & not test it */
1574 #define getMonikerRef(h,t,l,r) r_getMonikerRef(__LINE__,h,t,l,r)
1575 static IMoniker *r_getMonikerRef(unsigned line, IHlink *hlink, IMoniker *exp_tgt, const WCHAR *exp_loc, DWORD ref)
1576 {
1577 HRESULT hres;
1578 IMoniker *fnd_tgt;
1579 WCHAR *fnd_loc;
1580
1581 hres = IHlink_GetMonikerReference(hlink, ref, &fnd_tgt, &fnd_loc);
1582 ok_(__FILE__,line) (hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1583
1584 if(exp_loc)
1585 ok_(__FILE__,line) (!lstrcmpW(fnd_loc, exp_loc), "Found string location should have been %s, was: %s\n", wine_dbgstr_w(exp_loc), wine_dbgstr_w(fnd_loc));
1586 else
1587 ok_(__FILE__,line) (fnd_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1588
1589 CoTaskMemFree(fnd_loc);
1590
1591 if(exp_tgt == (IMoniker*)0xFFFFFFFF)
1592 return fnd_tgt;
1593
1594 ok_(__FILE__,line) (fnd_tgt == exp_tgt, "Found moniker target should have been %p, was: %p\n", exp_tgt, fnd_tgt);
1595
1596 if(fnd_tgt)
1597 IMoniker_Release(fnd_tgt);
1598
1599 return NULL;
1600 }
1601
1602 static void test_HlinkMoniker(void)
1603 {
1604 IHlink *hlink;
1605 IMoniker *aMon, *file_mon;
1606 static const WCHAR emptyW[] = {0};
1607 static const WCHAR wordsW[] = {'w','o','r','d','s',0};
1608 static const WCHAR aW[] = {'a',0};
1609 static const WCHAR bW[] = {'b',0};
1610 HRESULT hres;
1611
1612 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1613 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1614 getStringRef(hlink, NULL, NULL);
1615 getMonikerRef(hlink, NULL, NULL, HLINKGETREF_RELATIVE);
1616
1617 /* setting a string target creates a moniker reference */
1618 setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, aW, wordsW);
1619 getStringRef(hlink, aW, wordsW);
1620 aMon = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, wordsW, HLINKGETREF_RELATIVE);
1621 ok(aMon != NULL, "Moniker from %s target should not be NULL\n", wine_dbgstr_w(aW));
1622 if(aMon)
1623 IMoniker_Release(aMon);
1624
1625 /* setting target & location to the empty string deletes the moniker
1626 * reference */
1627 setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, emptyW, emptyW);
1628 getStringRef(hlink, NULL, NULL);
1629 getMonikerRef(hlink, NULL, NULL, HLINKGETREF_RELATIVE);
1630
1631 /* setting a moniker target also sets the target string to that moniker's
1632 * display name */
1633 hres = CreateFileMoniker(bW, &file_mon);
1634 ok(hres == S_OK, "CreateFileMoniker failed: 0x%08x\n", hres);
1635
1636 setMonikerRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, file_mon, wordsW);
1637 getStringRef(hlink, bW, wordsW);
1638 getMonikerRef(hlink, file_mon, wordsW, HLINKGETREF_RELATIVE);
1639
1640 IMoniker_Release(file_mon);
1641
1642 IHlink_Release(hlink);
1643 }
1644
1645 static void test_HashLink(void)
1646 {
1647 IHlink *hlink;
1648 IMoniker *pmk;
1649 const WCHAR hash_targetW[] = {'a','f','i','l','e','#','a','n','a','n','c','h','o','r',0};
1650 const WCHAR two_hash_targetW[] = {'a','f','i','l','e','#','a','n','a','n','c','h','o','r','#','a','n','o','t','h','e','r',0};
1651 const WCHAR hash_no_tgtW[] = {'#','a','n','a','n','c','h','o','r',0};
1652 const WCHAR tgt_partW[] = {'a','f','i','l','e',0};
1653 const WCHAR loc_partW[] = {'a','n','a','n','c','h','o','r',0};
1654 const WCHAR two_hash_loc_partW[] = {'a','n','a','n','c','h','o','r','#','a','n','o','t','h','e','r',0};
1655 const WCHAR test_locW[] = {'t','e','s','t','l','o','c',0};
1656 HRESULT hres;
1657
1658 /* simple single hash test */
1659 hres = HlinkCreateFromString(hash_targetW, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1660 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1661 ok(hlink != NULL, "Didn't get an hlink\n");
1662
1663 if(hlink){
1664 getStringRef(hlink, tgt_partW, loc_partW);
1665 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, loc_partW, HLINKGETREF_RELATIVE);
1666 ok(pmk != NULL, "Found moniker should not be NULL\n");
1667 if(pmk)
1668 IMoniker_Release(pmk);
1669
1670 setStringRef(hlink, HLINKSETF_TARGET, hash_targetW, NULL);
1671 getStringRef(hlink, hash_targetW, loc_partW);
1672
1673 IHlink_Release(hlink);
1674 }
1675
1676 /* two hashes in the target */
1677 hres = HlinkCreateFromString(two_hash_targetW, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1678 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1679 ok(hlink != NULL, "Didn't get an hlink\n");
1680
1681 if(hlink){
1682 getStringRef(hlink, tgt_partW, two_hash_loc_partW);
1683 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, two_hash_loc_partW, HLINKGETREF_RELATIVE);
1684 ok(pmk != NULL, "Found moniker should not be NULL\n");
1685 if(pmk)
1686 IMoniker_Release(pmk);
1687
1688 IHlink_Release(hlink);
1689 }
1690
1691 /* target with hash plus a location string */
1692 hres = HlinkCreateFromString(hash_targetW, test_locW, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1693 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1694 ok(hlink != NULL, "Didn't get an hlink\n");
1695
1696 if(hlink){
1697 getStringRef(hlink, tgt_partW, test_locW);
1698 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, test_locW, HLINKGETREF_RELATIVE);
1699 ok(pmk != NULL, "Found moniker should not be NULL\n");
1700 if(pmk)
1701 IMoniker_Release(pmk);
1702
1703 IHlink_Release(hlink);
1704 }
1705
1706 /* target with hash containing no "target part" */
1707 hres = HlinkCreateFromString(hash_no_tgtW, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1708 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1709 ok(hlink != NULL, "Didn't get an hlink\n");
1710
1711 if(hlink){
1712 getStringRef(hlink, NULL, loc_partW);
1713 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, loc_partW, HLINKGETREF_RELATIVE);
1714 ok(pmk == NULL, "Found moniker should be NULL\n");
1715 if(pmk)
1716 IMoniker_Release(pmk);
1717
1718 IHlink_Release(hlink);
1719 }
1720 }
1721
1722 static WCHAR site_monikerW[] = {'S','I','T','E','_','M','O','N','I','K','E','R',0};
1723 static WCHAR ref_monikerW[] = {'R','E','F','_','M','O','N','I','K','E','R',0};
1724
1725 static HRESULT WINAPI hls_test_Moniker_BindToStorage(IMoniker *iface,
1726 IBindCtx *pbc, IMoniker *toLeft, REFIID riid, void **obj)
1727 {
1728 ok(0, "BTS: %p %p %p %p %p\n", iface, pbc, toLeft, riid, obj);
1729 return E_NOTIMPL;
1730 }
1731
1732 static HRESULT WINAPI hls_site_Moniker_ComposeWith(IMoniker *iface,
1733 IMoniker *right, BOOL onlyIfNotGeneric, IMoniker **composite)
1734 {
1735 LPOLESTR rightName;
1736 HRESULT hres;
1737
1738 ok(onlyIfNotGeneric == 0, "Expected onlyIfNotGeneric to be FALSE\n");
1739
1740 CHECK_EXPECT(ComposeWith);
1741
1742 hres = IMoniker_GetDisplayName(right, NULL, NULL, &rightName);
1743 ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
1744 ok(!lstrcmpW(rightName, ref_monikerW),
1745 "Expected to get moniker set via SetMonikerReference, instead got: %s\n",
1746 wine_dbgstr_w(rightName));
1747 CoTaskMemFree(rightName);
1748
1749 *composite = NULL;
1750
1751 /* unlikely error code to verify this return result is used */
1752 return E_OUTOFMEMORY;
1753 }
1754
1755 static HRESULT WINAPI hls_site_Moniker_GetDisplayName(IMoniker *iface,
1756 IBindCtx *pbc, IMoniker *toLeft, LPOLESTR *displayName)
1757 {
1758 *displayName = CoTaskMemAlloc(sizeof(site_monikerW));
1759 memcpy(*displayName, site_monikerW, sizeof(site_monikerW));
1760 return S_OK;
1761 }
1762
1763 static HRESULT WINAPI hls_ref_Moniker_GetDisplayName(IMoniker *iface,
1764 IBindCtx *pbc, IMoniker *toLeft, LPOLESTR *displayName)
1765 {
1766 *displayName = CoTaskMemAlloc(sizeof(ref_monikerW));
1767 memcpy(*displayName, ref_monikerW, sizeof(ref_monikerW));
1768 return S_OK;
1769 }
1770
1771 static HRESULT WINAPI hls_test_Moniker_IsSystemMoniker(IMoniker *iface,
1772 DWORD *mksys)
1773 {
1774 return S_FALSE;
1775 }
1776
1777 static IMonikerVtbl hls_site_MonikerVtbl = {
1778 Moniker_QueryInterface,
1779 Moniker_AddRef,
1780 Moniker_Release,
1781 Moniker_GetClassID,
1782 Moniker_IsDirty,
1783 Moniker_Load,
1784 Moniker_Save,
1785 Moniker_GetSizeMax,
1786 Moniker_BindToObject,
1787 hls_test_Moniker_BindToStorage,
1788 Moniker_Reduce,
1789 hls_site_Moniker_ComposeWith,
1790 Moniker_Enum,
1791 Moniker_IsEqual,
1792 Moniker_Hash,
1793 Moniker_IsRunning,
1794 Moniker_GetTimeOfLastChange,
1795 Moniker_Inverse,
1796 Moniker_CommonPrefixWith,
1797 Moniker_RelativePathTo,
1798 hls_site_Moniker_GetDisplayName,
1799 Moniker_ParseDisplayName,
1800 hls_test_Moniker_IsSystemMoniker
1801 };
1802
1803 static IMonikerVtbl hls_ref_MonikerVtbl = {
1804 Moniker_QueryInterface,
1805 Moniker_AddRef,
1806 Moniker_Release,
1807 Moniker_GetClassID,
1808 Moniker_IsDirty,
1809 Moniker_Load,
1810 Moniker_Save,
1811 Moniker_GetSizeMax,
1812 Moniker_BindToObject,
1813 hls_test_Moniker_BindToStorage,
1814 Moniker_Reduce,
1815 Moniker_ComposeWith,
1816 Moniker_Enum,
1817 Moniker_IsEqual,
1818 Moniker_Hash,
1819 Moniker_IsRunning,
1820 Moniker_GetTimeOfLastChange,
1821 Moniker_Inverse,
1822 Moniker_CommonPrefixWith,
1823 Moniker_RelativePathTo,
1824 hls_ref_Moniker_GetDisplayName,
1825 Moniker_ParseDisplayName,
1826 hls_test_Moniker_IsSystemMoniker
1827 };
1828
1829 static IMoniker hls_site_Moniker = { &hls_site_MonikerVtbl };
1830 static IMoniker hls_ref_Moniker = { &hls_ref_MonikerVtbl };
1831
1832 static HRESULT WINAPI hls_QueryInterface(IHlinkSite *iface, REFGUID iid,
1833 void **obj)
1834 {
1835 ok(0, "QI: %p %s %p\n", iface, debugstr_guid(iid), obj);
1836 return E_NOTIMPL;
1837 }
1838
1839 static ULONG WINAPI hls_AddRef(IHlinkSite *iface)
1840 {
1841 return 2;
1842 }
1843
1844 static ULONG WINAPI hls_Release(IHlinkSite *iface)
1845 {
1846 return 1;
1847 }
1848
1849 static HRESULT WINAPI hls_QueryService(IHlinkSite *iface, DWORD siteData,
1850 REFGUID service, REFIID riid, IUnknown **punk)
1851 {
1852 ok(0, "QS: %p %x %s %s %p\n", iface, siteData, debugstr_guid(service),
1853 debugstr_guid(riid), punk);
1854 return E_NOTIMPL;
1855 }
1856
1857 #define SITEDATA_SUCCESS 1
1858 #define SITEDATA_NOTIMPL 2
1859
1860 static HRESULT WINAPI hls_GetMoniker(IHlinkSite *iface, DWORD siteData,
1861 DWORD assign, DWORD which, IMoniker **pmk)
1862 {
1863 ok(siteData == SITEDATA_NOTIMPL ||
1864 siteData == SITEDATA_SUCCESS, "Unexpected site data: %u\n", siteData);
1865
1866 if(siteData == SITEDATA_SUCCESS){
1867 *pmk = &hls_site_Moniker;
1868 return S_OK;
1869 }
1870
1871 return E_NOTIMPL;
1872 }
1873
1874 static HRESULT WINAPI hls_ReadyToNavigate(IHlinkSite *iface, DWORD siteData,
1875 DWORD reserved)
1876 {
1877 ok(0, "RTN: %p %x %x\n", iface, siteData, reserved);
1878 return E_NOTIMPL;
1879 }
1880
1881 static HRESULT WINAPI hls_OnNavigationComplete(IHlinkSite *iface,
1882 DWORD siteData, DWORD reserved, HRESULT error, LPCWSTR errorStr)
1883 {
1884 CHECK_EXPECT(OnNavigationComplete);
1885 ok(siteData == SITEDATA_SUCCESS, "Unexpected site data: %u\n", siteData);
1886 ok(error == E_OUTOFMEMORY, "Expected E_OUTOFMEMORY, got: %08x\n", error);
1887 return E_NOTIMPL;
1888 }
1889
1890 static IHlinkSiteVtbl HlinkSiteVtbl = {
1891 hls_QueryInterface,
1892 hls_AddRef,
1893 hls_Release,
1894 hls_QueryService,
1895 hls_GetMoniker,
1896 hls_ReadyToNavigate,
1897 hls_OnNavigationComplete
1898 };
1899
1900 static IHlinkSite HlinkSite = { &HlinkSiteVtbl };
1901
1902 static void test_HlinkSite(void)
1903 {
1904 IHlink *hl;
1905 IMoniker *mon_ref;
1906 IBindCtx *pbc;
1907 HRESULT hres;
1908
1909 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL,
1910 &IID_IHlink, (LPVOID*)&hl);
1911 ok(hres == S_OK, "HlinkCreateFromString failed: %08x\n", hres);
1912 getMonikerRef(hl, NULL, NULL, HLINKGETREF_RELATIVE);
1913
1914 hres = IHlink_SetHlinkSite(hl, &HlinkSite, SITEDATA_SUCCESS);
1915 ok(hres == S_OK, "SetHlinkSite failed: %08x\n", hres);
1916 getMonikerRef(hl, NULL, NULL, HLINKGETREF_RELATIVE);
1917 getStringRef(hl, NULL, NULL);
1918
1919 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_RELATIVE, &mon_ref, NULL);
1920 ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres);
1921 ok(mon_ref == NULL, "Didn't get expected moniker, instead: %p\n", mon_ref);
1922
1923 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_ABSOLUTE, &mon_ref, NULL);
1924 ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres);
1925 ok(mon_ref == &hls_site_Moniker, "Didn't get expected moniker, instead: %p\n", mon_ref);
1926
1927 SET_EXPECT(Reduce);
1928 SET_EXPECT(Enum);
1929 hres = IHlink_SetMonikerReference(hl, HLINKSETF_TARGET, &hls_ref_Moniker, NULL);
1930 ok(hres == S_OK, "SetMonikerReference failed: %08x\n", hres);
1931 todo_wine CHECK_CALLED(Reduce);
1932 todo_wine CHECK_CALLED(Enum);
1933
1934 getMonikerRef(hl, &hls_ref_Moniker, NULL, HLINKGETREF_RELATIVE);
1935
1936 SET_EXPECT(Enum);
1937 getStringRef(hl, ref_monikerW, NULL);
1938 todo_wine CHECK_CALLED(Enum);
1939
1940 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_RELATIVE, &mon_ref, NULL);
1941 ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres);
1942 ok(mon_ref == &hls_ref_Moniker, "Didn't get expected moniker, instead: %p\n", mon_ref);
1943 IMoniker_Release(mon_ref);
1944
1945 SET_EXPECT(ComposeWith);
1946 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_ABSOLUTE, &mon_ref, NULL);
1947 ok(hres == E_OUTOFMEMORY, "Expected E_OUTOFMEMORY, got: %08x\n", hres);
1948 ok(mon_ref == NULL, "Shouldn't have got a Moniker, got: %p\n", mon_ref);
1949 CHECK_CALLED(ComposeWith);
1950
1951 hres = CreateBindCtx(0, &pbc);
1952 ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres);
1953
1954 SET_EXPECT(ComposeWith);
1955 SET_EXPECT(OnNavigationComplete);
1956 hres = IHlink_Navigate(hl, 0, pbc, NULL, NULL);
1957 ok(hres == E_OUTOFMEMORY, "Navigate should've failed: %08x\n", hres);
1958 CHECK_CALLED(ComposeWith);
1959 CHECK_CALLED(OnNavigationComplete);
1960
1961 IBindCtx_Release(pbc);
1962 IHlink_Release(hl);
1963
1964 SET_EXPECT(Reduce);
1965 SET_EXPECT(Enum);
1966 hres = HlinkCreateFromMoniker(&hls_ref_Moniker, NULL, NULL, &HlinkSite, SITEDATA_SUCCESS,
1967 NULL, &IID_IHlink, (LPVOID*)&hl);
1968 ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres);
1969 todo_wine CHECK_CALLED(Reduce);
1970 todo_wine CHECK_CALLED(Enum);
1971 getMonikerRef(hl, &hls_ref_Moniker, NULL, HLINKGETREF_RELATIVE);
1972 IHlink_Release(hl);
1973
1974 hres = HlinkCreateFromMoniker(NULL, NULL, NULL, &HlinkSite, SITEDATA_SUCCESS,
1975 NULL, &IID_IHlink, (LPVOID*)&hl);
1976 ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres);
1977 getMonikerRef(hl, NULL, NULL, HLINKGETREF_RELATIVE);
1978 IHlink_Release(hl);
1979
1980 SET_EXPECT(Reduce);
1981 SET_EXPECT(Enum);
1982 SET_EXPECT(IsSystemMoniker);
1983 SET_EXPECT(GetDisplayName);
1984 hres = HlinkCreateFromMoniker(&Moniker, NULL, NULL, &HlinkSite, SITEDATA_NOTIMPL,
1985 NULL, &IID_IHlink, (LPVOID*)&hl);
1986 ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres);
1987 getMonikerRef(hl, &Moniker, NULL, HLINKGETREF_ABSOLUTE);
1988 IHlink_Release(hl);
1989 todo_wine CHECK_CALLED(Reduce);
1990 todo_wine CHECK_CALLED(Enum);
1991 CHECK_CALLED(IsSystemMoniker);
1992 CHECK_CALLED(GetDisplayName);
1993 }
1994
1995 static void test_HlinkClone(void)
1996 {
1997 HRESULT hres;
1998 IHlink *hl, *cloned = NULL;
1999 IMoniker *dummy, *fnd_mk;
2000 IHlinkSite *fnd_site;
2001 WCHAR *fnd_name;
2002 DWORD fnd_data;
2003 const WCHAR one[] = {'1',0};
2004 const WCHAR two[] = {'2',0};
2005 const WCHAR name[] = {'a',0};
2006
2007 hres = HlinkClone(NULL, NULL, NULL, 0, NULL);
2008 ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
2009
2010 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL,
2011 &IID_IHlink, (void**)&hl);
2012 ok(hres == S_OK, "HlinkCreateFromString failed: %08x\n", hres);
2013
2014 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, NULL);
2015 ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
2016
2017 if (0)
2018 {
2019 /* crash on Windows XP */
2020 HlinkClone(hl, NULL, NULL, 0, NULL);
2021
2022 HlinkClone(hl, NULL, NULL, 0, (void**)&cloned);
2023 }
2024
2025 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
2026 ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
2027 ok(cloned != NULL, "Didn't get a clone\n");
2028 getMonikerRef(cloned, NULL, NULL, HLINKGETREF_RELATIVE);
2029 IHlink_Release(cloned);
2030
2031 IHlink_Release(hl);
2032
2033 SET_EXPECT(Reduce);
2034 SET_EXPECT(Enum);
2035 hres = HlinkCreateFromMoniker(&hls_ref_Moniker, two, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hl);
2036 todo_wine CHECK_CALLED(Reduce);
2037 todo_wine CHECK_CALLED(Enum);
2038 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
2039 getMonikerRef(hl, &hls_ref_Moniker, two, HLINKGETREF_RELATIVE);
2040
2041 SET_EXPECT(Save);
2042 SET_EXPECT(GetClassID);
2043 cloned = (IHlink*)0xdeadbeef;
2044 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
2045 /* fails because of invalid CLSID given by Moniker_GetClassID */
2046 ok(hres == REGDB_E_CLASSNOTREG, "Wrong error code: %08x\n", hres);
2047 ok(cloned == NULL, "Shouldn't have gotten a clone\n");
2048 CHECK_CALLED(Save);
2049 CHECK_CALLED(GetClassID);
2050
2051 IHlink_Release(hl);
2052
2053 hres = CreateItemMoniker(one, one, &dummy);
2054 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
2055
2056 hres = HlinkCreateFromMoniker(dummy, two, name, &HlinkSite, SITEDATA_SUCCESS, NULL, &IID_IHlink, (void**)&hl);
2057 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
2058 getMonikerRef(hl, dummy, two, HLINKGETREF_RELATIVE);
2059
2060 cloned = NULL;
2061 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
2062 ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
2063 ok(cloned != NULL, "Should have gotten a clone\n");
2064
2065 fnd_mk = getMonikerRef(cloned, (IMoniker*)0xFFFFFFFF, two, HLINKGETREF_RELATIVE);
2066 ok(fnd_mk != NULL, "Expected non-null Moniker\n");
2067 ok(fnd_mk != dummy, "Expected a new Moniker to be created\n");
2068
2069 fnd_name = NULL;
2070 hres = IHlink_GetFriendlyName(cloned, HLFNAMEF_DEFAULT, &fnd_name);
2071 ok(hres == S_OK, "GetFriendlyName failed: %08x\n", hres);
2072 ok(fnd_name != NULL, "Expected friendly name to be non-NULL\n");
2073 ok(lstrcmpW(fnd_name, name) == 0, "Expected friendly name to be %s, was %s\n",
2074 wine_dbgstr_w(name), wine_dbgstr_w(fnd_name));
2075 CoTaskMemFree(fnd_name);
2076
2077 fnd_site = (IHlinkSite*)0xdeadbeef;
2078 fnd_data = 4;
2079 hres = IHlink_GetHlinkSite(cloned, &fnd_site, &fnd_data);
2080 ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres);
2081 ok(fnd_site == NULL, "Expected NULL site\n");
2082 ok(fnd_data == 4, "Expected site data to be 4, was: %d\n", fnd_data);
2083
2084 IHlink_Release(cloned);
2085 IHlink_Release(hl);
2086
2087 hres = HlinkCreateFromMoniker(dummy, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hl);
2088 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
2089 getMonikerRef(hl, dummy, NULL, HLINKGETREF_RELATIVE);
2090
2091 cloned = NULL;
2092 hres = HlinkClone(hl, &IID_IHlink, &HlinkSite, SITEDATA_SUCCESS, (void**)&cloned);
2093 ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
2094 ok(cloned != NULL, "Should have gotten a clone\n");
2095
2096 fnd_mk = getMonikerRef(cloned, (IMoniker*)0xFFFFFFFF, NULL, HLINKGETREF_RELATIVE);
2097 ok(fnd_mk != NULL, "Expected non-null Moniker\n");
2098 ok(fnd_mk != dummy, "Expected a new Moniker to be created\n");
2099
2100 fnd_site = (IHlinkSite*)0xdeadbeef;
2101 fnd_data = 4;
2102 hres = IHlink_GetHlinkSite(cloned, &fnd_site, &fnd_data);
2103 ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres);
2104 ok(fnd_site == &HlinkSite, "Expected found site to be HlinkSite, was: %p\n", fnd_site);
2105 ok(fnd_data == SITEDATA_SUCCESS, "Unexpected site data: %u\n", fnd_data);
2106
2107 IHlink_Release(cloned);
2108 IHlink_Release(hl);
2109
2110 IMoniker_Release(dummy);
2111 }
2112
2113 static void test_StdHlink(void)
2114 {
2115 IHlink *hlink;
2116 WCHAR *str;
2117 HRESULT hres;
2118
2119 static const WCHAR testW[] = {'t','e','s','t',0};
2120
2121 hres = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
2122 &IID_IHlink, (void**)&hlink);
2123 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
2124
2125 str = (void*)0xdeadbeef;
2126 hres = IHlink_GetTargetFrameName(hlink, &str);
2127 ok(hres == S_FALSE, "GetTargetFrameName failed: %08x\n", hres);
2128 ok(!str, "str = %s\n", wine_dbgstr_w(str));
2129
2130 hres = IHlink_SetTargetFrameName(hlink, testW);
2131 ok(hres == S_OK, "SetTargetFrameName failed: %08x\n", hres);
2132
2133 str = (void*)0xdeadbeef;
2134 hres = IHlink_GetTargetFrameName(hlink, &str);
2135 ok(hres == S_OK, "GetTargetFrameName failed: %08x\n", hres);
2136 ok(!lstrcmpW(str, testW), "str = %s\n", wine_dbgstr_w(str));
2137 CoTaskMemFree(str);
2138
2139 hres = IHlink_SetTargetFrameName(hlink, NULL);
2140 ok(hres == S_OK, "SetTargetFrameName failed: %08x\n", hres);
2141
2142 str = (void*)0xdeadbeef;
2143 hres = IHlink_GetTargetFrameName(hlink, &str);
2144 ok(hres == S_FALSE, "GetTargetFrameName failed: %08x\n", hres);
2145 ok(!str, "str = %s\n", wine_dbgstr_w(str));
2146
2147 IHlink_Release(hlink);
2148 }
2149
2150 static void test_Hlink_Navigate(void)
2151 {
2152 IHlink *hlink;
2153 IBindCtx *pbc;
2154 HRESULT hres;
2155
2156 hres = CreateBindCtx(0, &pbc);
2157 ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres);
2158 _bctx = pbc;
2159
2160 SET_EXPECT(Reduce);
2161 SET_EXPECT(Enum);
2162 SET_EXPECT(IsSystemMoniker);
2163 SET_EXPECT(GetDisplayName);
2164 hres = HlinkCreateFromMoniker(&Moniker, NULL, NULL, NULL,
2165 0, NULL, &IID_IHlink, (void**)&hlink);
2166 ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres);
2167 todo_wine CHECK_CALLED(Reduce);
2168 todo_wine CHECK_CALLED(Enum);
2169 todo_wine CHECK_CALLED(IsSystemMoniker);
2170 CHECK_CALLED(GetDisplayName);
2171
2172 SET_EXPECT(IsSystemMoniker);
2173 SET_EXPECT(GetDisplayName);
2174 SET_EXPECT(HBC_GetObject);
2175 SET_EXPECT(Reduce);
2176 SET_EXPECT(BindToObject);
2177 SET_EXPECT(HT_GetBrowseContext);
2178 SET_EXPECT(HT_SetBrowseContext);
2179 SET_EXPECT(HBC_QueryInterface_IHlinkHistory);
2180 SET_EXPECT(HT_Navigate);
2181 SET_EXPECT(HT_GetFriendlyName);
2182 hres = IHlink_Navigate(hlink, 0, pbc, NULL, &HlinkBrowseContext);
2183 ok(hres == S_OK, "Navigate failed: %08x\n", hres);
2184 CHECK_CALLED(IsSystemMoniker);
2185 todo_wine CHECK_CALLED(GetDisplayName);
2186 todo_wine CHECK_CALLED(HBC_GetObject);
2187 todo_wine CHECK_CALLED(Reduce);
2188 CHECK_CALLED(BindToObject);
2189 todo_wine CHECK_CALLED(HT_GetBrowseContext);
2190 CHECK_CALLED(HT_SetBrowseContext);
2191 todo_wine CHECK_CALLED(HBC_QueryInterface_IHlinkHistory);
2192 CHECK_CALLED(HT_Navigate);
2193 todo_wine CHECK_CALLED(HT_GetFriendlyName);
2194
2195 IHlink_Release(hlink);
2196 IBindCtx_Release(pbc);
2197 _bctx = NULL;
2198 }
2199
2200 static HRESULT WINAPI hlinkframe_QueryInterface(IHlinkFrame *iface, REFIID riid, void **obj)
2201 {
2202 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IHlinkFrame))
2203 {
2204 *obj = iface;
2205 return S_OK;
2206 }
2207
2208 *obj = NULL;
2209 return E_NOINTERFACE;
2210 }
2211
2212 static ULONG WINAPI hlinkframe_AddRef(IHlinkFrame *iface)
2213 {
2214 return 2;
2215 }
2216
2217 static ULONG WINAPI hlinkframe_Release(IHlinkFrame *iface)
2218 {
2219 return 1;
2220 }
2221
2222 static HRESULT WINAPI hlinkframe_SetBrowseContext(IHlinkFrame *iface, IHlinkBrowseContext *bc)
2223 {
2224 ok(0, "unexpected %p\n", bc);
2225 return E_NOTIMPL;
2226 }
2227
2228 static HRESULT WINAPI hlinkframe_GetBrowseContext(IHlinkFrame *iface, IHlinkBrowseContext **bc)
2229 {
2230 *bc = NULL;
2231 ok(0, "unexpected %p\n", bc);
2232 return E_NOTIMPL;
2233 }
2234
2235 static HRESULT WINAPI hlinkframe_Navigate(IHlinkFrame *iface, DWORD grfHLNF, LPBC pbc, IBindStatusCallback *bsc, IHlink *navigate)
2236 {
2237 ok(0, "unexpected\n");
2238 return E_NOTIMPL;
2239 }
2240
2241 static HRESULT WINAPI hlinkframe_OnNavigate(IHlinkFrame *iface, DWORD grfHLNF, IMoniker *target, LPCWSTR location, LPCWSTR friendly_name,
2242 DWORD reserved)
2243 {
2244 ok(0, "unexpected\n");
2245 return E_NOTIMPL;
2246 }
2247
2248 static HRESULT WINAPI hlinkframe_UpdateHlink(IHlinkFrame *iface, ULONG uHLID, IMoniker *target, LPCWSTR location, LPCWSTR friendly_name)
2249 {
2250 CHECK_EXPECT(HLF_UpdateHlink);
2251 return S_OK;
2252 }
2253
2254 static IHlinkFrameVtbl hlinkframevtbl = {
2255 hlinkframe_QueryInterface,
2256 hlinkframe_AddRef,
2257 hlinkframe_Release,
2258 hlinkframe_SetBrowseContext,
2259 hlinkframe_GetBrowseContext,
2260 hlinkframe_Navigate,
2261 hlinkframe_OnNavigate,
2262 hlinkframe_UpdateHlink
2263 };
2264
2265 static IHlinkFrame testframe = { &hlinkframevtbl };
2266
2267 static void test_HlinkUpdateStackItem(void)
2268 {
2269 static const WCHAR location[] = {'l','o','c','a','t','i','o','n',0};
2270 HRESULT hr;
2271
2272 hr = HlinkUpdateStackItem(NULL, NULL, HLID_CURRENT, &Moniker, location, NULL);
2273 ok(hr == E_INVALIDARG, "got 0x%08x\n", hr);
2274
2275 SET_EXPECT(HBC_UpdateHlink);
2276 hr = HlinkUpdateStackItem(NULL, &HlinkBrowseContext, HLID_CURRENT, &Moniker, location, NULL);
2277 ok(hr == S_OK, "got 0x%08x\n", hr);
2278 CHECK_CALLED(HBC_UpdateHlink);
2279
2280 SET_EXPECT(HLF_UpdateHlink);
2281 hr = HlinkUpdateStackItem(&testframe, &HlinkBrowseContext, HLID_CURRENT, &Moniker, location, NULL);
2282 ok(hr == S_OK, "got 0x%08x\n", hr);
2283 CHECK_CALLED(HLF_UpdateHlink);
2284 }
2285
2286 START_TEST(hlink)
2287 {
2288 CoInitialize(NULL);
2289
2290 test_HlinkIsShortcut();
2291 test_reference();
2292 test_persist();
2293 test_special_reference();
2294 test_HlinkCreateExtensionServices();
2295 test_HlinkParseDisplayName();
2296 test_HlinkResolveMonikerForData();
2297 test_HlinkGetSetMonikerReference();
2298 test_HlinkGetSetStringReference();
2299 test_HlinkMoniker();
2300 test_HashLink();
2301 test_HlinkSite();
2302 test_HlinkClone();
2303 test_StdHlink();
2304 test_Hlink_Navigate();
2305 test_HlinkUpdateStackItem();
2306
2307 CoUninitialize();
2308 }