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