15191dfe6dafd0878e8c5ea5a5906678e22eb637
[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 }
1028
1029 static void test_HlinkGetSetMonikerReference(void)
1030 {
1031 IMoniker *found_trgt, *dummy, *dummy2;
1032 IHlink *hlink;
1033 HRESULT hres;
1034 const WCHAR one[] = {'1',0};
1035 const WCHAR two[] = {'2',0};
1036 const WCHAR name[] = {'a',0};
1037 WCHAR *found_loc;
1038
1039 /* create two dummy monikers to use as targets */
1040 hres = CreateItemMoniker(one, one, &dummy);
1041 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1042
1043 hres = CreateItemMoniker(two, two, &dummy2);
1044 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1045
1046 /* create a new hlink: target => dummy, location => one */
1047 hres = HlinkCreateFromMoniker(dummy, one, name, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1048 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1049
1050 /* validate the target and location */
1051 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1052 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1053 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1054 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1055 IMoniker_Release(found_trgt);
1056 CoTaskMemFree(found_loc);
1057
1058 /* set location => two */
1059 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_LOCATION, dummy2, two);
1060 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1061
1062 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1063 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1064 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1065 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1066 IMoniker_Release(found_trgt);
1067 CoTaskMemFree(found_loc);
1068
1069 /* set target => dummy2 */
1070 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, dummy2, one);
1071 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1072
1073 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1074 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1075 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1076 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1077 IMoniker_Release(found_trgt);
1078 CoTaskMemFree(found_loc);
1079
1080 /* set target => dummy, location => one */
1081 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, dummy, one);
1082 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1083
1084 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1085 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1086 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1087 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1088 IMoniker_Release(found_trgt);
1089 CoTaskMemFree(found_loc);
1090
1091 /* no HLINKSETF flags */
1092 hres = IHlink_SetMonikerReference(hlink, 0, dummy2, two);
1093 ok(hres == E_INVALIDARG, "IHlink_SetMonikerReference should've failed with E_INVALIDARG (0x%08x), failed with 0x%08x\n", E_INVALIDARG, hres);
1094
1095 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1096 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1097 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1098 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1099 IMoniker_Release(found_trgt);
1100 CoTaskMemFree(found_loc);
1101
1102 /* invalid HLINKSETF flags */
1103 /* Windows returns garbage; on 32-bit it returns the flags probably because the compiler happened to store them in %eax at some point */
1104 if (0)
1105 IHlink_SetMonikerReference(hlink, 12, dummy2, two);
1106
1107 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1108 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1109 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1110 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1111 IMoniker_Release(found_trgt);
1112 CoTaskMemFree(found_loc);
1113
1114 /* valid & invalid HLINKSETF flags */
1115 hres = IHlink_SetMonikerReference(hlink, 12 | HLINKSETF_TARGET, dummy2, two);
1116 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1117
1118 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1119 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1120 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1121 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1122 IMoniker_Release(found_trgt);
1123 CoTaskMemFree(found_loc);
1124
1125 /* NULL args */
1126 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, NULL, NULL);
1127 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1128
1129 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1130 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1131 ok(found_trgt == NULL, "Found target should've been %p, was: %p\n", NULL, found_trgt);
1132 ok(found_loc == NULL, "Found location should've been %s, was: %s\n", wine_dbgstr_w(NULL), wine_dbgstr_w(found_loc));
1133 if(found_trgt)
1134 IMoniker_Release(found_trgt);
1135
1136 IHlink_Release(hlink);
1137 IMoniker_Release(dummy2);
1138 IMoniker_Release(dummy);
1139 }
1140
1141 static void test_HlinkGetSetStringReference(void)
1142 {
1143 IHlink *link;
1144 static const WCHAR one[] = {'1',0};
1145 static const WCHAR two[] = {'2',0};
1146 static const WCHAR three[] = {'3',0};
1147 static const WCHAR empty[] = {0};
1148 WCHAR *fnd_tgt, *fnd_loc;
1149 HRESULT hres;
1150
1151 /* create a new hlink: target => NULL, location => one */
1152 hres = HlinkCreateFromMoniker(NULL, one, empty, NULL, 0, NULL, &IID_IHlink, (void**)&link);
1153 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1154
1155 /* test setting/getting location */
1156 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1157 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1158 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1159 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1160 CoTaskMemFree(fnd_tgt);
1161 CoTaskMemFree(fnd_loc);
1162
1163 hres = IHlink_SetStringReference(link, HLINKSETF_LOCATION, one, two);
1164 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1165
1166 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1167 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1168 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1169 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1170 CoTaskMemFree(fnd_tgt);
1171 CoTaskMemFree(fnd_loc);
1172
1173 hres = IHlink_SetStringReference(link, -HLINKSETF_LOCATION, two, one);
1174 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1175
1176 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1177 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1178 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1179 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1180 CoTaskMemFree(fnd_tgt);
1181 CoTaskMemFree(fnd_loc);
1182
1183 /* test setting/getting target */
1184 hres = IHlink_SetStringReference(link, HLINKSETF_TARGET, two, three);
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(!lstrcmpW(fnd_tgt, two), "Found target should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_tgt));
1190 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1191 CoTaskMemFree(fnd_tgt);
1192 CoTaskMemFree(fnd_loc);
1193
1194 hres = IHlink_SetStringReference(link, -HLINKSETF_TARGET, three, two);
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(!lstrcmpW(fnd_tgt, three), "Found target should have been %s, was: %s\n", wine_dbgstr_w(three), wine_dbgstr_w(fnd_tgt));
1200 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1201 CoTaskMemFree(fnd_tgt);
1202 CoTaskMemFree(fnd_loc);
1203
1204 /* test setting/getting both */
1205 hres = IHlink_SetStringReference(link, HLINKSETF_TARGET | HLINKSETF_LOCATION, one, two);
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, one), "Found target should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_tgt));
1211 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1212 CoTaskMemFree(fnd_tgt);
1213 CoTaskMemFree(fnd_loc);
1214
1215 hres = IHlink_SetStringReference(link, -(HLINKSETF_TARGET | HLINKSETF_LOCATION), three, one);
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 invalid flags/params */
1226 hres = IHlink_GetStringReference(link, 4, &fnd_tgt, &fnd_loc);
1227 ok(hres == E_INVALIDARG, "IHlink_GetStringReference should have failed "
1228 "with E_INVALIDARG (0x%08x), instead: 0x%08x\n", E_INVALIDARG, hres);
1229 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1230 ok(fnd_loc == NULL, "Found location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1231 CoTaskMemFree(fnd_tgt);
1232 CoTaskMemFree(fnd_loc);
1233
1234 hres = IHlink_GetStringReference(link, -1, &fnd_tgt, NULL);
1235 todo_wine ok(hres == E_FAIL, "IHlink_GetStringReference should have failed "
1236 "with E_FAIL (0x%08x), instead: 0x%08x\n", E_FAIL, hres);
1237 CoTaskMemFree(fnd_tgt);
1238
1239 hres = IHlink_GetStringReference(link, -1, NULL, NULL);
1240 ok(hres == S_OK, "failed, hres=%08x\n", hres);
1241
1242 hres = IHlink_GetStringReference(link, -1, NULL, &fnd_loc);
1243 ok(hres == S_OK, "failed, hres=%08x\n", hres);
1244 CoTaskMemFree(fnd_loc);
1245
1246 hres = IHlink_GetStringReference(link, -1, &fnd_tgt, &fnd_loc);
1247 todo_wine ok(hres == E_FAIL, "IHlink_GetStringReference should have failed "
1248 "with E_FAIL (0x%08x), instead: 0x%08x\n", E_FAIL, hres);
1249 CoTaskMemFree(fnd_tgt);
1250 CoTaskMemFree(fnd_loc);
1251
1252 hres = IHlink_GetStringReference(link, -2, &fnd_tgt, &fnd_loc);
1253 ok(hres == E_INVALIDARG, "IHlink_GetStringReference should have failed "
1254 "with E_INVALIDARG (0x%08x), instead: 0x%08x\n", E_INVALIDARG, hres);
1255 CoTaskMemFree(fnd_tgt);
1256 CoTaskMemFree(fnd_loc);
1257
1258 if (0)
1259 {
1260 /* Windows returns garbage; on 32-bit it returns the flags probably because the compiler happened to store them in %eax at some point */
1261 IHlink_SetStringReference(link, 4, NULL, NULL);
1262 IHlink_SetStringReference(link, -4, NULL, NULL);
1263 }
1264
1265 IHlink_Release(link);
1266 }
1267
1268 #define setStringRef(h,f,t,l) r_setStringRef(__LINE__,h,f,t,l)
1269 static void r_setStringRef(unsigned line, IHlink *hlink, DWORD flags, const WCHAR *tgt, const WCHAR *loc)
1270 {
1271 HRESULT hres;
1272 hres = IHlink_SetStringReference(hlink, flags, tgt, loc);
1273 ok_(__FILE__,line) (hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1274 }
1275
1276 #define getStringRef(h,t,l) r_getStringRef(__LINE__,h,t,l)
1277 static void r_getStringRef(unsigned line, IHlink *hlink, const WCHAR *exp_tgt, const WCHAR *exp_loc)
1278 {
1279 HRESULT hres;
1280 WCHAR *fnd_tgt, *fnd_loc;
1281
1282 hres = IHlink_GetStringReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1283 ok_(__FILE__,line) (hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1284
1285 if(exp_tgt)
1286 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));
1287 else
1288 ok_(__FILE__,line) (fnd_tgt == NULL, "Found string target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1289
1290 if(exp_loc)
1291 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));
1292 else
1293 ok_(__FILE__,line) (fnd_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1294
1295 CoTaskMemFree(fnd_tgt);
1296 CoTaskMemFree(fnd_loc);
1297 }
1298
1299 #define setMonikerRef(h,f,t,l) r_setMonikerRef(__LINE__,h,f,t,l)
1300 static void r_setMonikerRef(unsigned line, IHlink *hlink, DWORD flags, IMoniker *tgt, const WCHAR *loc)
1301 {
1302 HRESULT hres;
1303 hres = IHlink_SetMonikerReference(hlink, flags, tgt, loc);
1304 ok_(__FILE__,line) (hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1305 }
1306
1307 /* passing 0xFFFFFFFF as exp_tgt will return the retrieved target & not test it */
1308 #define getMonikerRef(h,t,l) r_getMonikerRef(__LINE__,h,t,l)
1309 static IMoniker *r_getMonikerRef(unsigned line, IHlink *hlink, IMoniker *exp_tgt, const WCHAR *exp_loc)
1310 {
1311 HRESULT hres;
1312 IMoniker *fnd_tgt;
1313 WCHAR *fnd_loc;
1314
1315 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1316 ok_(__FILE__,line) (hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1317
1318 if(exp_loc)
1319 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));
1320 else
1321 ok_(__FILE__,line) (fnd_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1322
1323 CoTaskMemFree(fnd_loc);
1324
1325 if(exp_tgt == (IMoniker*)0xFFFFFFFF)
1326 return fnd_tgt;
1327
1328 ok_(__FILE__,line) (fnd_tgt == exp_tgt, "Found moniker target should have been %p, was: %p\n", exp_tgt, fnd_tgt);
1329
1330 if(fnd_tgt)
1331 IMoniker_Release(fnd_tgt);
1332
1333 return NULL;
1334 }
1335
1336 static void test_HlinkMoniker(void)
1337 {
1338 IHlink *hlink;
1339 IMoniker *aMon, *file_mon;
1340 static const WCHAR emptyW[] = {0};
1341 static const WCHAR wordsW[] = {'w','o','r','d','s',0};
1342 static const WCHAR aW[] = {'a',0};
1343 static const WCHAR bW[] = {'b',0};
1344 HRESULT hres;
1345
1346 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1347 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1348 getStringRef(hlink, NULL, NULL);
1349 getMonikerRef(hlink, NULL, NULL);
1350
1351 /* setting a string target creates a moniker reference */
1352 setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, aW, wordsW);
1353 getStringRef(hlink, aW, wordsW);
1354 aMon = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, wordsW);
1355 ok(aMon != NULL, "Moniker from %s target should not be NULL\n", wine_dbgstr_w(aW));
1356 if(aMon)
1357 IMoniker_Release(aMon);
1358
1359 /* setting target & location to the empty string deletes the moniker
1360 * reference */
1361 setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, emptyW, emptyW);
1362 getStringRef(hlink, NULL, NULL);
1363 getMonikerRef(hlink, NULL, NULL);
1364
1365 /* setting a moniker target also sets the target string to that moniker's
1366 * display name */
1367 hres = CreateFileMoniker(bW, &file_mon);
1368 ok(hres == S_OK, "CreateFileMoniker failed: 0x%08x\n", hres);
1369
1370 setMonikerRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, file_mon, wordsW);
1371 getStringRef(hlink, bW, wordsW);
1372 getMonikerRef(hlink, file_mon, wordsW);
1373
1374 IMoniker_Release(file_mon);
1375
1376 IHlink_Release(hlink);
1377 }
1378
1379 static void test_HashLink(void)
1380 {
1381 IHlink *hlink;
1382 IMoniker *pmk;
1383 const WCHAR hash_targetW[] = {'a','f','i','l','e','#','a','n','a','n','c','h','o','r',0};
1384 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};
1385 const WCHAR hash_no_tgtW[] = {'#','a','n','a','n','c','h','o','r',0};
1386 const WCHAR tgt_partW[] = {'a','f','i','l','e',0};
1387 const WCHAR loc_partW[] = {'a','n','a','n','c','h','o','r',0};
1388 const WCHAR two_hash_loc_partW[] = {'a','n','a','n','c','h','o','r','#','a','n','o','t','h','e','r',0};
1389 const WCHAR test_locW[] = {'t','e','s','t','l','o','c',0};
1390 HRESULT hres;
1391
1392 /* simple single hash test */
1393 hres = HlinkCreateFromString(hash_targetW, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1394 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1395 ok(hlink != NULL, "Didn't get an hlink\n");
1396
1397 if(hlink){
1398 getStringRef(hlink, tgt_partW, loc_partW);
1399 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, loc_partW);
1400 ok(pmk != NULL, "Found moniker should not be NULL\n");
1401 if(pmk)
1402 IMoniker_Release(pmk);
1403
1404 setStringRef(hlink, HLINKSETF_TARGET, hash_targetW, NULL);
1405 getStringRef(hlink, hash_targetW, loc_partW);
1406
1407 IHlink_Release(hlink);
1408 }
1409
1410 /* two hashes in the target */
1411 hres = HlinkCreateFromString(two_hash_targetW, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1412 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1413 ok(hlink != NULL, "Didn't get an hlink\n");
1414
1415 if(hlink){
1416 getStringRef(hlink, tgt_partW, two_hash_loc_partW);
1417 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, two_hash_loc_partW);
1418 ok(pmk != NULL, "Found moniker should not be NULL\n");
1419 if(pmk)
1420 IMoniker_Release(pmk);
1421
1422 IHlink_Release(hlink);
1423 }
1424
1425 /* target with hash plus a location string */
1426 hres = HlinkCreateFromString(hash_targetW, test_locW, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1427 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1428 ok(hlink != NULL, "Didn't get an hlink\n");
1429
1430 if(hlink){
1431 getStringRef(hlink, tgt_partW, test_locW);
1432 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, test_locW);
1433 ok(pmk != NULL, "Found moniker should not be NULL\n");
1434 if(pmk)
1435 IMoniker_Release(pmk);
1436
1437 IHlink_Release(hlink);
1438 }
1439
1440 /* target with hash containing no "target part" */
1441 hres = HlinkCreateFromString(hash_no_tgtW, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void*)&hlink);
1442 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1443 ok(hlink != NULL, "Didn't get an hlink\n");
1444
1445 if(hlink){
1446 getStringRef(hlink, NULL, loc_partW);
1447 pmk = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, loc_partW);
1448 ok(pmk == NULL, "Found moniker should be NULL\n");
1449 if(pmk)
1450 IMoniker_Release(pmk);
1451
1452 IHlink_Release(hlink);
1453 }
1454 }
1455
1456 static WCHAR site_monikerW[] = {'S','I','T','E','_','M','O','N','I','K','E','R',0};
1457 static WCHAR ref_monikerW[] = {'R','E','F','_','M','O','N','I','K','E','R',0};
1458
1459 static HRESULT WINAPI hls_test_Moniker_BindToStorage(IMoniker *iface,
1460 IBindCtx *pbc, IMoniker *toLeft, REFIID riid, void **obj)
1461 {
1462 ok(0, "BTS: %p %p %p %p %p\n", iface, pbc, toLeft, riid, obj);
1463 return E_NOTIMPL;
1464 }
1465
1466 static HRESULT WINAPI hls_site_Moniker_ComposeWith(IMoniker *iface,
1467 IMoniker *right, BOOL onlyIfNotGeneric, IMoniker **composite)
1468 {
1469 LPOLESTR rightName;
1470 HRESULT hres;
1471
1472 ok(onlyIfNotGeneric == 0, "Expected onlyIfNotGeneric to be FALSE\n");
1473
1474 CHECK_EXPECT(ComposeWith);
1475
1476 hres = IMoniker_GetDisplayName(right, NULL, NULL, &rightName);
1477 ok(hres == S_OK, "GetDisplayName failed: %08x\n", hres);
1478 ok(!lstrcmpW(rightName, ref_monikerW),
1479 "Expected to get moniker set via SetMonikerReference, instead got: %s\n",
1480 wine_dbgstr_w(rightName));
1481 CoTaskMemFree(rightName);
1482
1483 *composite = NULL;
1484
1485 /* unlikely error code to verify this return result is used */
1486 return E_OUTOFMEMORY;
1487 }
1488
1489 static HRESULT WINAPI hls_site_Moniker_GetDisplayName(IMoniker *iface,
1490 IBindCtx *pbc, IMoniker *toLeft, LPOLESTR *displayName)
1491 {
1492 *displayName = CoTaskMemAlloc(sizeof(site_monikerW));
1493 memcpy(*displayName, site_monikerW, sizeof(site_monikerW));
1494 return S_OK;
1495 }
1496
1497 static HRESULT WINAPI hls_ref_Moniker_GetDisplayName(IMoniker *iface,
1498 IBindCtx *pbc, IMoniker *toLeft, LPOLESTR *displayName)
1499 {
1500 *displayName = CoTaskMemAlloc(sizeof(ref_monikerW));
1501 memcpy(*displayName, ref_monikerW, sizeof(ref_monikerW));
1502 return S_OK;
1503 }
1504
1505 static HRESULT WINAPI hls_test_Moniker_IsSystemMoniker(IMoniker *iface,
1506 DWORD *mksys)
1507 {
1508 return S_FALSE;
1509 }
1510
1511 static IMonikerVtbl hls_site_MonikerVtbl = {
1512 Moniker_QueryInterface,
1513 Moniker_AddRef,
1514 Moniker_Release,
1515 Moniker_GetClassID,
1516 Moniker_IsDirty,
1517 Moniker_Load,
1518 Moniker_Save,
1519 Moniker_GetSizeMax,
1520 Moniker_BindToObject,
1521 hls_test_Moniker_BindToStorage,
1522 Moniker_Reduce,
1523 hls_site_Moniker_ComposeWith,
1524 Moniker_Enum,
1525 Moniker_IsEqual,
1526 Moniker_Hash,
1527 Moniker_IsRunning,
1528 Moniker_GetTimeOfLastChange,
1529 Moniker_Inverse,
1530 Moniker_CommonPrefixWith,
1531 Moniker_RelativePathTo,
1532 hls_site_Moniker_GetDisplayName,
1533 Moniker_ParseDisplayName,
1534 hls_test_Moniker_IsSystemMoniker
1535 };
1536
1537 static IMonikerVtbl hls_ref_MonikerVtbl = {
1538 Moniker_QueryInterface,
1539 Moniker_AddRef,
1540 Moniker_Release,
1541 Moniker_GetClassID,
1542 Moniker_IsDirty,
1543 Moniker_Load,
1544 Moniker_Save,
1545 Moniker_GetSizeMax,
1546 Moniker_BindToObject,
1547 hls_test_Moniker_BindToStorage,
1548 Moniker_Reduce,
1549 Moniker_ComposeWith,
1550 Moniker_Enum,
1551 Moniker_IsEqual,
1552 Moniker_Hash,
1553 Moniker_IsRunning,
1554 Moniker_GetTimeOfLastChange,
1555 Moniker_Inverse,
1556 Moniker_CommonPrefixWith,
1557 Moniker_RelativePathTo,
1558 hls_ref_Moniker_GetDisplayName,
1559 Moniker_ParseDisplayName,
1560 hls_test_Moniker_IsSystemMoniker
1561 };
1562
1563 static IMoniker hls_site_Moniker = { &hls_site_MonikerVtbl };
1564 static IMoniker hls_ref_Moniker = { &hls_ref_MonikerVtbl };
1565
1566 static HRESULT WINAPI hls_QueryInterface(IHlinkSite *iface, REFGUID iid,
1567 void **obj)
1568 {
1569 ok(0, "QI: %p %s %p\n", iface, debugstr_guid(iid), obj);
1570 return E_NOTIMPL;
1571 }
1572
1573 static ULONG WINAPI hls_AddRef(IHlinkSite *iface)
1574 {
1575 return 2;
1576 }
1577
1578 static ULONG WINAPI hls_Release(IHlinkSite *iface)
1579 {
1580 return 1;
1581 }
1582
1583 static HRESULT WINAPI hls_QueryService(IHlinkSite *iface, DWORD siteData,
1584 REFGUID service, REFIID riid, IUnknown **punk)
1585 {
1586 ok(0, "QS: %p %x %s %s %p\n", iface, siteData, debugstr_guid(service),
1587 debugstr_guid(riid), punk);
1588 return E_NOTIMPL;
1589 }
1590
1591 static HRESULT WINAPI hls_GetMoniker(IHlinkSite *iface, DWORD siteData,
1592 DWORD assign, DWORD which, IMoniker **pmk)
1593 {
1594 ok(siteData == 17, "Expected siteData == 17, got: %d\n", siteData);
1595 *pmk = &hls_site_Moniker;
1596 return S_OK;
1597 }
1598
1599 static HRESULT WINAPI hls_ReadyToNavigate(IHlinkSite *iface, DWORD siteData,
1600 DWORD reserved)
1601 {
1602 ok(0, "RTN: %p %x %x\n", iface, siteData, reserved);
1603 return E_NOTIMPL;
1604 }
1605
1606 static HRESULT WINAPI hls_OnNavigationComplete(IHlinkSite *iface,
1607 DWORD siteData, DWORD reserved, HRESULT error, LPCWSTR errorStr)
1608 {
1609 CHECK_EXPECT(OnNavigationComplete);
1610 ok(siteData == 17, "Expected siteData == 17, got: %d\n", siteData);
1611 ok(error == E_OUTOFMEMORY, "Expected E_OUTOFMEMORY, got: %08x\n", error);
1612 return E_NOTIMPL;
1613 }
1614
1615 static IHlinkSiteVtbl HlinkSiteVtbl = {
1616 hls_QueryInterface,
1617 hls_AddRef,
1618 hls_Release,
1619 hls_QueryService,
1620 hls_GetMoniker,
1621 hls_ReadyToNavigate,
1622 hls_OnNavigationComplete
1623 };
1624
1625 static IHlinkSite HlinkSite = { &HlinkSiteVtbl };
1626
1627 static void test_HlinkSite(void)
1628 {
1629 IHlink *hl;
1630 IMoniker *mon_ref;
1631 IBindCtx *pbc;
1632 HRESULT hres;
1633
1634 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL,
1635 &IID_IHlink, (LPVOID*)&hl);
1636 ok(hres == S_OK, "HlinkCreateFromString failed: %08x\n", hres);
1637 getMonikerRef(hl, NULL, NULL);
1638
1639 hres = IHlink_SetHlinkSite(hl, &HlinkSite, 17);
1640 ok(hres == S_OK, "SetHlinkSite failed: %08x\n", hres);
1641 getMonikerRef(hl, NULL, NULL);
1642 getStringRef(hl, NULL, NULL);
1643
1644 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_RELATIVE, &mon_ref, NULL);
1645 ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres);
1646 ok(mon_ref == NULL, "Didn't get expected moniker, instead: %p\n", mon_ref);
1647
1648 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_ABSOLUTE, &mon_ref, NULL);
1649 ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres);
1650 ok(mon_ref == &hls_site_Moniker, "Didn't get expected moniker, instead: %p\n", mon_ref);
1651
1652 SET_EXPECT(Reduce);
1653 SET_EXPECT(Enum);
1654 hres = IHlink_SetMonikerReference(hl, HLINKSETF_TARGET, &hls_ref_Moniker, NULL);
1655 ok(hres == S_OK, "SetMonikerReference failed: %08x\n", hres);
1656 todo_wine CHECK_CALLED(Reduce);
1657 todo_wine CHECK_CALLED(Enum);
1658
1659 getMonikerRef(hl, &hls_ref_Moniker, NULL);
1660
1661 SET_EXPECT(Enum);
1662 getStringRef(hl, ref_monikerW, NULL);
1663 todo_wine CHECK_CALLED(Enum);
1664
1665 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_RELATIVE, &mon_ref, NULL);
1666 ok(hres == S_OK, "GetMonikerReference failed: %08x\n", hres);
1667 ok(mon_ref == &hls_ref_Moniker, "Didn't get expected moniker, instead: %p\n", mon_ref);
1668 IMoniker_Release(mon_ref);
1669
1670 SET_EXPECT(ComposeWith);
1671 hres = IHlink_GetMonikerReference(hl, HLINKGETREF_ABSOLUTE, &mon_ref, NULL);
1672 ok(hres == E_OUTOFMEMORY, "Expected E_OUTOFMEMORY, got: %08x\n", hres);
1673 ok(mon_ref == NULL, "Shouldn't have got a Moniker, got: %p\n", mon_ref);
1674 CHECK_CALLED(ComposeWith);
1675
1676 hres = CreateBindCtx(0, &pbc);
1677 ok(hres == S_OK, "CreateBindCtx failed: %08x\n", hres);
1678
1679 SET_EXPECT(ComposeWith);
1680 SET_EXPECT(OnNavigationComplete);
1681 hres = IHlink_Navigate(hl, 0, pbc, NULL, NULL);
1682 ok(hres == E_OUTOFMEMORY, "Navigate should've failed: %08x\n", hres);
1683 CHECK_CALLED(ComposeWith);
1684 CHECK_CALLED(OnNavigationComplete);
1685
1686 IBindCtx_Release(pbc);
1687 IHlink_Release(hl);
1688
1689 SET_EXPECT(Reduce);
1690 SET_EXPECT(Enum);
1691 hres = HlinkCreateFromMoniker(&hls_ref_Moniker, NULL, NULL, &HlinkSite, 17,
1692 NULL, &IID_IHlink, (LPVOID*)&hl);
1693 ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres);
1694 todo_wine CHECK_CALLED(Reduce);
1695 todo_wine CHECK_CALLED(Enum);
1696 getMonikerRef(hl, &hls_ref_Moniker, NULL);
1697 IHlink_Release(hl);
1698
1699 hres = HlinkCreateFromMoniker(NULL, NULL, NULL, &HlinkSite, 17,
1700 NULL, &IID_IHlink, (LPVOID*)&hl);
1701 ok(hres == S_OK, "HlinkCreateFromMoniker failed: %08x\n", hres);
1702 getMonikerRef(hl, NULL, NULL);
1703 IHlink_Release(hl);
1704 }
1705
1706 static void test_HlinkClone(void)
1707 {
1708 HRESULT hres;
1709 IHlink *hl, *cloned = NULL;
1710 IMoniker *dummy, *fnd_mk;
1711 IHlinkSite *fnd_site;
1712 WCHAR *fnd_name;
1713 DWORD fnd_data;
1714 const WCHAR one[] = {'1',0};
1715 const WCHAR two[] = {'2',0};
1716 const WCHAR name[] = {'a',0};
1717
1718 hres = HlinkClone(NULL, NULL, NULL, 0, NULL);
1719 ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
1720
1721 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL,
1722 &IID_IHlink, (void**)&hl);
1723 ok(hres == S_OK, "HlinkCreateFromString failed: %08x\n", hres);
1724
1725 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, NULL);
1726 ok(hres == E_INVALIDARG, "Got wrong failure code: %08x\n", hres);
1727
1728 if (0)
1729 {
1730 /* crash on Windows XP */
1731 HlinkClone(hl, NULL, NULL, 0, NULL);
1732
1733 HlinkClone(hl, NULL, NULL, 0, (void**)&cloned);
1734 }
1735
1736 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
1737 ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
1738 ok(cloned != NULL, "Didn't get a clone\n");
1739 getMonikerRef(cloned, NULL, NULL);
1740 IHlink_Release(cloned);
1741
1742 IHlink_Release(hl);
1743
1744 SET_EXPECT(Reduce);
1745 SET_EXPECT(Enum);
1746 hres = HlinkCreateFromMoniker(&hls_ref_Moniker, two, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hl);
1747 todo_wine CHECK_CALLED(Reduce);
1748 todo_wine CHECK_CALLED(Enum);
1749 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1750 getMonikerRef(hl, &hls_ref_Moniker, two);
1751
1752 SET_EXPECT(Save);
1753 SET_EXPECT(GetClassID);
1754 cloned = (IHlink*)0xdeadbeef;
1755 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
1756 /* fails because of invalid CLSID given by Moniker_GetClassID */
1757 ok(hres == REGDB_E_CLASSNOTREG, "Wrong error code: %08x\n", hres);
1758 ok(cloned == NULL, "Shouldn't have gotten a clone\n");
1759 CHECK_CALLED(Save);
1760 CHECK_CALLED(GetClassID);
1761
1762 IHlink_Release(hl);
1763
1764 hres = CreateItemMoniker(one, one, &dummy);
1765 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1766
1767 hres = HlinkCreateFromMoniker(dummy, two, name, &HlinkSite, 17, NULL, &IID_IHlink, (void**)&hl);
1768 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1769 getMonikerRef(hl, dummy, two);
1770
1771 cloned = NULL;
1772 hres = HlinkClone(hl, &IID_IHlink, NULL, 0, (void**)&cloned);
1773 ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
1774 ok(cloned != NULL, "Should have gotten a clone\n");
1775
1776 fnd_mk = getMonikerRef(cloned, (IMoniker*)0xFFFFFFFF, two);
1777 ok(fnd_mk != NULL, "Expected non-null Moniker\n");
1778 ok(fnd_mk != dummy, "Expected a new Moniker to be created\n");
1779
1780 fnd_name = NULL;
1781 hres = IHlink_GetFriendlyName(cloned, HLFNAMEF_DEFAULT, &fnd_name);
1782 ok(hres == S_OK, "GetFriendlyName failed: %08x\n", hres);
1783 ok(fnd_name != NULL, "Expected friendly name to be non-NULL\n");
1784 ok(lstrcmpW(fnd_name, name) == 0, "Expected friendly name to be %s, was %s\n",
1785 wine_dbgstr_w(name), wine_dbgstr_w(fnd_name));
1786 CoTaskMemFree(fnd_name);
1787
1788 fnd_site = (IHlinkSite*)0xdeadbeef;
1789 fnd_data = 4;
1790 hres = IHlink_GetHlinkSite(cloned, &fnd_site, &fnd_data);
1791 ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres);
1792 ok(fnd_site == NULL, "Expected NULL site\n");
1793 ok(fnd_data == 4, "Expected site data to be 4, was: %d\n", fnd_data);
1794
1795 IHlink_Release(cloned);
1796 IHlink_Release(hl);
1797
1798 hres = HlinkCreateFromMoniker(dummy, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hl);
1799 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1800 getMonikerRef(hl, dummy, NULL);
1801
1802 cloned = NULL;
1803 hres = HlinkClone(hl, &IID_IHlink, &HlinkSite, 17, (void**)&cloned);
1804 ok(hres == S_OK, "HlinkClone failed: %08x\n", hres);
1805 ok(cloned != NULL, "Should have gotten a clone\n");
1806
1807 fnd_mk = getMonikerRef(cloned, (IMoniker*)0xFFFFFFFF, NULL);
1808 ok(fnd_mk != NULL, "Expected non-null Moniker\n");
1809 ok(fnd_mk != dummy, "Expected a new Moniker to be created\n");
1810
1811 fnd_site = (IHlinkSite*)0xdeadbeef;
1812 fnd_data = 4;
1813 hres = IHlink_GetHlinkSite(cloned, &fnd_site, &fnd_data);
1814 ok(hres == S_OK, "GetHlinkSite failed: %08x\n", hres);
1815 ok(fnd_site == &HlinkSite, "Expected found site to be HlinkSite, was: %p\n", fnd_site);
1816 ok(fnd_data == 17, "Expected site data to be 17, was: %d\n", fnd_data);
1817
1818 IHlink_Release(cloned);
1819 IHlink_Release(hl);
1820
1821 IMoniker_Release(dummy);
1822 }
1823
1824 static void test_StdHlink(void)
1825 {
1826 IHlink *hlink;
1827 WCHAR *str;
1828 HRESULT hres;
1829
1830 static const WCHAR testW[] = {'t','e','s','t',0};
1831
1832 hres = CoCreateInstance(&CLSID_StdHlink, NULL, CLSCTX_INPROC_SERVER|CLSCTX_INPROC_HANDLER,
1833 &IID_IHlink, (void**)&hlink);
1834 ok(hres == S_OK, "CoCreateInstance failed: %08x\n", hres);
1835
1836 str = (void*)0xdeadbeef;
1837 hres = IHlink_GetTargetFrameName(hlink, &str);
1838 ok(hres == S_FALSE, "GetTargetFrameName failed: %08x\n", hres);
1839 ok(!str, "str = %s\n", wine_dbgstr_w(str));
1840
1841 hres = IHlink_SetTargetFrameName(hlink, testW);
1842 ok(hres == S_OK, "SetTargetFrameName failed: %08x\n", hres);
1843
1844 str = (void*)0xdeadbeef;
1845 hres = IHlink_GetTargetFrameName(hlink, &str);
1846 ok(hres == S_OK, "GetTargetFrameName failed: %08x\n", hres);
1847 ok(!lstrcmpW(str, testW), "str = %s\n", wine_dbgstr_w(str));
1848 CoTaskMemFree(str);
1849
1850 hres = IHlink_SetTargetFrameName(hlink, NULL);
1851 ok(hres == S_OK, "SetTargetFrameName failed: %08x\n", hres);
1852
1853 str = (void*)0xdeadbeef;
1854 hres = IHlink_GetTargetFrameName(hlink, &str);
1855 ok(hres == S_FALSE, "GetTargetFrameName failed: %08x\n", hres);
1856 ok(!str, "str = %s\n", wine_dbgstr_w(str));
1857
1858 IHlink_Release(hlink);
1859 }
1860
1861 START_TEST(hlink)
1862 {
1863 CoInitialize(NULL);
1864
1865 test_HlinkIsShortcut();
1866 test_reference();
1867 test_persist();
1868 test_special_reference();
1869 test_HlinkCreateExtensionServices();
1870 test_HlinkParseDisplayName();
1871 test_HlinkResolveMonikerForData();
1872 test_HlinkGetSetMonikerReference();
1873 test_HlinkGetSetStringReference();
1874 test_HlinkMoniker();
1875 test_HashLink();
1876 test_HlinkSite();
1877 test_HlinkClone();
1878 test_StdHlink();
1879
1880 CoUninitialize();
1881 }