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