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