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