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