[HAL]
[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 static const char *debugstr_guid(REFIID riid)
61 {
62 static char buf[50];
63
64 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
65 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
66 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
67 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
68
69 return buf;
70 }
71
72 static void test_HlinkIsShortcut(void)
73 {
74 UINT i;
75 HRESULT hres;
76
77 static const WCHAR file0[] = {'f','i','l','e',0};
78 static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
79 static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
80 static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
81 static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
82 static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
83 static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
84 static const WCHAR file7[] = {'.','u','r','l',0};
85
86 static struct {
87 LPCWSTR file;
88 HRESULT hres;
89 } shortcut_test[] = {
90 {file0, S_FALSE},
91 {file1, S_OK},
92 {file2, S_FALSE},
93 {file3, S_OK},
94 {file4, S_FALSE},
95 {file5, S_OK},
96 {file6, S_FALSE},
97 {file7, S_OK},
98 {NULL, E_INVALIDARG}
99 };
100
101 for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
102 hres = HlinkIsShortcut(shortcut_test[i].file);
103 ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
104 i, hres, shortcut_test[i].hres);
105 }
106 }
107
108 static void test_reference(void)
109 {
110 HRESULT r;
111 IHlink *lnk = NULL;
112 IMoniker *mk = NULL;
113 const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
114 const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
115 LPWSTR str = NULL;
116
117 r = HlinkCreateFromString(url, NULL, NULL, NULL,
118 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
119 ok(r == S_OK, "failed to create link\n");
120 if (FAILED(r))
121 return;
122
123 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
124 ok(r == S_OK, "failed\n");
125
126 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
127 ok(r == S_OK, "failed\n");
128 ok(mk != NULL, "no moniker\n");
129 ok(str == NULL, "string should be null\n");
130
131 r = IMoniker_Release(mk);
132 ok( r == 1, "moniker refcount wrong\n");
133
134 r = IHlink_GetStringReference(lnk, -1, &str, NULL);
135 ok(r == S_OK, "failed\n");
136 CoTaskMemFree(str);
137
138 r = IHlink_GetStringReference(lnk, -1, NULL, NULL);
139 ok(r == S_OK, "failed, r=%08x\n", r);
140
141 r = IHlink_GetStringReference(lnk, -1, NULL, &str);
142 ok(r == S_OK, "failed, r=%08x\n", r);
143 ok(str == NULL, "string should be null\n");
144
145 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
146 ok(r == S_OK, "failed\n");
147 ok(!lstrcmpW(str, url2), "url wrong\n");
148 CoTaskMemFree(str);
149
150 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
151 ok(r == S_OK, "failed\n");
152
153 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
154 ok(r == S_OK, "failed\n");
155 ok(str == NULL, "string should be null\n");
156
157 /* Unimplented functions checks */
158 r = IHlink_GetAdditionalParams(lnk, NULL);
159 ok(r == E_NOTIMPL, "failed\n");
160
161 r = IHlink_SetAdditionalParams(lnk, NULL);
162 ok(r == E_NOTIMPL, "failed\n");
163
164 IHlink_Release(lnk);
165 }
166
167 /* url only */
168 static const unsigned char expected_hlink_data[] =
169 {
170 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
171 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
172 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
173 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
174 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
175 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
176 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
177 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
178 0x00,0x00,
179 };
180
181 /* url only (IE7) */
182 static const unsigned char expected_hlink_data_ie7[] =
183 {
184 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
185 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
186 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
187 0x3e,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
188 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
189 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
190 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
191 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
192 0x00,0x00,0x79,0x58,0x81,0xf4,0x3b,0x1d,
193 0x7f,0x48,0xaf,0x2c,0x82,0x5d,0xc4,0x85,
194 0x27,0x63,0x00,0x00,0x00,0x00,0xa5,0xab,
195 0x00,0x00,
196 };
197
198 /* url + friendly name */
199 static const unsigned char expected_hlink_data2[] =
200 {
201 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
202 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
203 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
204 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
205 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
206 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
207 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
208 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
209 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
210 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
211 0x67,0x00,0x2f,0x00,0x00,0x00,
212 };
213
214 /* url + friendly name (IE7) */
215 static const unsigned char expected_hlink_data2_ie7[] =
216 {
217 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
218 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
219 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
220 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
221 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
222 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
223 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
224 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
225 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
226 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
227 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
228 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
229 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
230 0x00,0x00,0xa5,0xab,0x00,0x00,
231 };
232
233 /* url + friendly name + location */
234 static const unsigned char expected_hlink_data3[] =
235 {
236 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
237 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
238 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
239 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
240 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
241 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
242 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
243 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
244 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
245 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
246 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
247 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
248 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
249 };
250
251 /* url + friendly name + location (IE7) */
252 static const unsigned char expected_hlink_data3_ie7[] =
253 {
254 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
255 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
256 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
257 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
258 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
259 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
260 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
261 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
262 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
263 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
264 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
265 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
266 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
267 0x00,0x00,0xa5,0xab,0x00,0x00,0x07,0x00,
268 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
269 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
270 };
271
272 /* relative url */
273 static const unsigned char expected_hlink_data4[] =
274 {
275 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
276 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
277 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
278 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
279 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
280 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
281 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
282 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
283 0x00,0x00,0x00,0x00,0x00,
284 };
285
286 /* url + target frame name */
287 static const unsigned char expected_hlink_data5[] =
288 {
289 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
290 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
291 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
292 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
293 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
294 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
295 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
296 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
297 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
298 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
299 0x2f,0x00,0x00,0x00,
300 };
301
302 /* url + target frame name (IE7) */
303 static const unsigned char expected_hlink_data5_ie7[] =
304 {
305 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
306 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
307 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
308 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
309 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
310 0xa9,0x0b,0x3e,0x00,0x00,0x00,0x68,0x00,
311 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
312 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
313 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
314 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
315 0x2f,0x00,0x00,0x00,0x79,0x58,0x81,0xf4,
316 0x3b,0x1d,0x7f,0x48,0xaf,0x2c,0x82,0x5d,
317 0xc4,0x85,0x27,0x63,0x00,0x00,0x00,0x00,
318 0xa5,0xab,0x00,0x00,
319 };
320
321 /* filename */
322 static const unsigned char expected_hlink_data6[] =
323 {
324 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
325 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
326 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
327 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
328 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
329 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
330 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
331 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
332 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
333 0x5c,0x00,
334 };
335
336 static void test_persist_save_data(const char *testname, IHlink *lnk,
337 const unsigned char *expected_data,
338 unsigned int expected_data_size,
339 const unsigned char *expected_data_alt,
340 unsigned int expected_data_alt_size)
341 {
342 HRESULT hr;
343 IStream *stream;
344 IPersistStream *ps;
345 HGLOBAL hglobal;
346 DWORD data_size;
347 const unsigned char *data;
348 DWORD i;
349 BOOL same;
350 unsigned int expected_data_win9x_size = 0;
351
352 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
353 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
354
355 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
356 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
357
358 hr = IPersistStream_Save(ps, stream, TRUE);
359 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
360
361 hr = GetHGlobalFromStream(stream, &hglobal);
362 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
363
364 data_size = GlobalSize(hglobal);
365
366 data = GlobalLock(hglobal);
367
368 if (expected_data_size % 4)
369 expected_data_win9x_size = 4 * ((expected_data_size / 4) + 1);
370
371 /* first check we have the right amount of data */
372 ok((data_size == expected_data_size) ||
373 (data_size == expected_data_alt_size) ||
374 broken(data_size == expected_data_win9x_size), /* Win9x and WinMe */
375 "%s: Size of saved data differs (expected %d or %d, actual %d)\n",
376 testname, expected_data_size, expected_data_alt_size, data_size);
377
378 same = TRUE;
379 /* then do a byte-by-byte comparison */
380 for (i = 0; i < min(data_size, expected_data_size); i++)
381 {
382 if ((expected_data[i] != data[i]) &&
383 (((expected_data != expected_hlink_data2) &&
384 (expected_data != expected_hlink_data3)) ||
385 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
386 {
387 same = FALSE;
388 break;
389 }
390 }
391
392 if (!same && (expected_data_alt != expected_data))
393 {
394 /* then try the alternate data */
395 same = TRUE;
396 for (i = 0; i < min(data_size, expected_data_alt_size); i++)
397 {
398 if ((expected_data_alt[i] != data[i]) &&
399 (((expected_data_alt != expected_hlink_data2) &&
400 (expected_data_alt != expected_hlink_data3)) ||
401 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
402 {
403 same = FALSE;
404 break;
405 }
406 }
407 }
408
409 ok(same, "%s: Saved data differs\n", testname);
410 if (!same)
411 {
412 for (i = 0; i < data_size; i++)
413 {
414 if (i % 8 == 0) printf(" ");
415 printf("0x%02x,", data[i]);
416 if (i % 8 == 7) printf("\n");
417 }
418 printf("\n");
419 }
420
421 GlobalUnlock(hglobal);
422
423 IStream_Release(stream);
424 IPersistStream_Release(ps);
425 }
426
427 static void test_persist(void)
428 {
429 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
430 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
431 static const WCHAR filename[] = { 'c',':','\\',0 };
432 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
433 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
434 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
435 HRESULT hr;
436 IHlink *lnk;
437
438 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
439 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
440 ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr);
441 if (!lnk) {
442 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
443 return;
444 }
445 test_persist_save_data("url only", lnk,
446 expected_hlink_data, sizeof(expected_hlink_data),
447 expected_hlink_data_ie7, sizeof(expected_hlink_data_ie7));
448 IHlink_Release(lnk);
449
450 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
451 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
452 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
453 test_persist_save_data("url + friendly name", lnk,
454 expected_hlink_data2, sizeof(expected_hlink_data2),
455 expected_hlink_data2_ie7, sizeof(expected_hlink_data2_ie7));
456 IHlink_Release(lnk);
457
458 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
459 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
460 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
461 test_persist_save_data("url + friendly_name + location", lnk,
462 expected_hlink_data3, sizeof(expected_hlink_data3),
463 expected_hlink_data3_ie7, sizeof(expected_hlink_data3_ie7));
464 IHlink_Release(lnk);
465
466 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
467 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
468 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
469 test_persist_save_data("relative url", lnk,
470 expected_hlink_data4, sizeof(expected_hlink_data4),
471 expected_hlink_data4, sizeof(expected_hlink_data4));
472 IHlink_Release(lnk);
473
474 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
475 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
476 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
477 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
478 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
479 test_persist_save_data("url + target frame name", lnk,
480 expected_hlink_data5, sizeof(expected_hlink_data5),
481 expected_hlink_data5_ie7, sizeof(expected_hlink_data5_ie7));
482 IHlink_Release(lnk);
483
484 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
485 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
486 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
487 test_persist_save_data("filename", lnk,
488 expected_hlink_data6, sizeof(expected_hlink_data6),
489 expected_hlink_data6, sizeof(expected_hlink_data6));
490 IHlink_Release(lnk);
491 }
492
493 static void test_special_reference(void)
494 {
495 LPWSTR ref;
496 HRESULT hres;
497
498 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
499 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
500 ok(ref != NULL, "ref == NULL\n");
501 CoTaskMemFree(ref);
502
503 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
504 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
505 ok(ref != NULL, "ref == NULL\n");
506 CoTaskMemFree(ref);
507
508 ref = (void*)0xdeadbeef;
509 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
510 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
511 ok(ref == NULL, "ref=%p\n", ref);
512
513 ref = (void*)0xdeadbeef;
514 hres = HlinkGetSpecialReference(4, &ref);
515 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
516 ok(ref == NULL, "ref=%p\n", ref);
517 }
518
519 static void test_HlinkCreateExtensionServices(void)
520 {
521 IAuthenticate *authenticate;
522 IHttpNegotiate *http_negotiate;
523 LPWSTR password, username, headers;
524 HWND hwnd;
525 HRESULT hres;
526
527 static const WCHAR usernameW[] = {'u','s','e','r',0};
528 static const WCHAR passwordW[] = {'p','a','s','s',0};
529 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
530 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
531
532 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
533 NULL, &IID_IAuthenticate, (void**)&authenticate);
534 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
535 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
536
537 password = username = (void*)0xdeadbeef;
538 hwnd = (void*)0xdeadbeef;
539 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
540 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
541 ok(!hwnd, "hwnd != NULL\n");
542 ok(!username, "username != NULL\n");
543 ok(!password, "password != NULL\n");
544
545 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
546 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
547
548 headers = (void*)0xdeadbeef;
549 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
550 0, &headers);
551 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
552 ok(headers == NULL, "headers != NULL\n");
553
554 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
555 0, NULL);
556 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
557
558 headers = (void*)0xdeadbeef;
559 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
560 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
561 ok(headers == NULL, "headers != NULL\n");
562
563 IHttpNegotiate_Release(http_negotiate);
564 IAuthenticate_Release(authenticate);
565
566
567 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
568 NULL, &IID_IAuthenticate, (void**)&authenticate);
569 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
570 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
571
572 password = username = NULL;
573 hwnd = NULL;
574 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
575 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
576 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
577 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
578 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
579 CoTaskMemFree(username);
580 CoTaskMemFree(password);
581
582 password = username = (void*)0xdeadbeef;
583 hwnd = (void*)0xdeadbeef;
584 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
585 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
586 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
587 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
588
589 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
590 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
591
592 headers = (void*)0xdeadbeef;
593 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
594 0, &headers);
595 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
596 ok(!lstrcmpW(headers, headersexW), "unexpected headers %s\n", wine_dbgstr_w(headers));
597 CoTaskMemFree(headers);
598
599 headers = (void*)0xdeadbeef;
600 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
601 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
602 ok(headers == NULL, "unexpected headers %s\n", wine_dbgstr_w(headers));
603
604 IHttpNegotiate_Release(http_negotiate);
605 IAuthenticate_Release(authenticate);
606 }
607
608 static void test_HlinkParseDisplayName(void)
609 {
610 IMoniker *mon = NULL;
611 LPWSTR name;
612 DWORD issys;
613 ULONG eaten = 0;
614 IBindCtx *bctx;
615 HRESULT hres;
616
617 static const WCHAR winehq_urlW[] =
618 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
619 '/','s','i','t','e','/','a','b','o','u','t',0};
620 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
621 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
622 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
623 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
624
625 CreateBindCtx(0, &bctx);
626
627 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
628 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
629 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
630 ok(mon != NULL, "mon == NULL\n");
631
632 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
633 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
634 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
635 CoTaskMemFree(name);
636
637 hres = IMoniker_IsSystemMoniker(mon, &issys);
638 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
639 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
640
641 IMoniker_Release(mon);
642
643 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
644 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
645 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
646 ok(mon != NULL, "mon == NULL\n");
647
648 hres = IMoniker_IsSystemMoniker(mon, &issys);
649 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
650 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
651
652 IMoniker_Release(mon);
653
654 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
655 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
656 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
657 ok(mon != NULL, "mon == NULL\n");
658
659 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
660 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
661 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
662 CoTaskMemFree(name);
663
664 hres = IMoniker_IsSystemMoniker(mon, &issys);
665 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
666 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
667
668 IMoniker_Release(mon);
669 IBindCtx_Release(bctx);
670 }
671
672 static IBindCtx *_bctx;
673
674 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
675 {
676 ok(0, "unexpected call\n");
677 return E_NOINTERFACE;
678 }
679
680 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
681 {
682 return 2;
683 }
684
685 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
686 {
687 return 1;
688 }
689
690 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
691 REFGUID guidService, REFIID riid, void **ppv)
692 {
693 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
694 return E_NOINTERFACE;
695 }
696
697 static IServiceProviderVtbl ServiceProviderVtbl = {
698 ServiceProvider_QueryInterface,
699 ServiceProvider_AddRef,
700 ServiceProvider_Release,
701 ServiceProvider_QueryService
702 };
703
704 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
705
706 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
707 {
708 *ppv = NULL;
709
710 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
711 *ppv = &ServiceProvider;
712 return S_OK;
713 }
714
715 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
716 return E_NOINTERFACE;
717 }
718
719 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
720 {
721 return 2;
722 }
723
724 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
725 {
726 return 1;
727 }
728
729 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
730 IBinding *pib)
731 {
732 ok(0, "unexpected call\n");
733 return E_NOTIMPL;
734 }
735
736 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
737 {
738 ok(0, "unexpected call\n");
739 return E_NOTIMPL;
740 }
741
742 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
743 {
744 ok(0, "unexpected call\n");
745 return E_NOTIMPL;
746 }
747
748 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
749 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
750 {
751 ok(0, "unexpected call\n");
752 return E_NOTIMPL;
753 }
754
755 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
756 {
757 ok(0, "unexpected call\n");
758 return E_NOTIMPL;
759 }
760
761 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
762 {
763 ok(0, "unexpected call\n");
764 return E_NOTIMPL;
765 }
766
767 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
768 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
769 {
770 ok(0, "unexpected call\n");
771 return E_NOTIMPL;
772 }
773
774 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
775 {
776 ok(0, "unexpected call\n");
777 return E_NOTIMPL;
778 }
779
780 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
781 BindStatusCallback_QueryInterface,
782 BindStatusCallback_AddRef,
783 BindStatusCallback_Release,
784 BindStatusCallback_OnStartBinding,
785 BindStatusCallback_GetPriority,
786 BindStatusCallback_OnLowResource,
787 BindStatusCallback_OnProgress,
788 BindStatusCallback_OnStopBinding,
789 BindStatusCallback_GetBindInfo,
790 BindStatusCallback_OnDataAvailable,
791 BindStatusCallback_OnObjectAvailable
792 };
793
794 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
795
796 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
797 {
798 *ppv = NULL;
799
800 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
801 return E_NOINTERFACE;
802 }
803
804 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
805 {
806 return 2;
807 }
808
809 static ULONG WINAPI Moniker_Release(IMoniker *iface)
810 {
811 return 1;
812 }
813
814 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
815 {
816 ok(0, "unexpected call\n");
817 return E_NOTIMPL;
818 }
819
820 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
821 {
822 ok(0, "unexpected call\n");
823 return E_NOTIMPL;
824 }
825
826 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
827 {
828 ok(0, "unexpected call\n");
829 return E_NOTIMPL;
830 }
831
832 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
833 {
834 ok(0, "unexpected call\n");
835 return E_NOTIMPL;
836 }
837
838 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
839 {
840 ok(0, "unexpected call\n");
841 return E_NOTIMPL;
842 }
843
844 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
845 REFIID riidResult, void **ppvResult)
846 {
847 ok(0, "unexpected call\n");
848 return E_NOTIMPL;
849 }
850
851 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
852 REFIID riid, void **ppv)
853 {
854 IUnknown *unk;
855 HRESULT hres;
856
857 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
858
859 CHECK_EXPECT(BindToStorage);
860
861 ok(pbc == _bctx, "pbc != _bctx\n");
862 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
863 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
864 ok(ppv != NULL, "ppv == NULL\n");
865 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
866
867 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
868 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
869 ok(unk != NULL, "unk == NULL\n");
870
871 IUnknown_Release(unk);
872
873 return S_OK;
874 }
875
876 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
877 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
878 {
879 ok(0, "unexpected call\n");
880 return E_NOTIMPL;
881 }
882
883 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
884 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
885 {
886 ok(0, "unexpected call\n");
887 return E_NOTIMPL;
888 }
889
890 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
891 {
892 ok(0, "unexpected call\n");
893 return E_NOTIMPL;
894 }
895
896 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
897 {
898 ok(0, "unexpected call\n");
899 return E_NOTIMPL;
900 }
901
902 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
903 {
904 ok(0, "unexpected call\n");
905 return E_NOTIMPL;
906 }
907
908 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
909 IMoniker *pmkNewlyRunning)
910 {
911 ok(0, "unexpected call\n");
912 return E_NOTIMPL;
913 }
914
915 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
916 IMoniker *pmkToLeft, FILETIME *pFileTime)
917 {
918 ok(0, "unexpected call\n");
919 return E_NOTIMPL;
920 }
921
922 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
923 {
924 ok(0, "unexpected call\n");
925 return E_NOTIMPL;
926 }
927
928 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
929 IMoniker **ppmkPrefix)
930 {
931 ok(0, "unexpected call\n");
932 return E_NOTIMPL;
933 }
934
935 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
936 IMoniker **pmkRelPath)
937 {
938 ok(0, "unexpected call\n");
939 return E_NOTIMPL;
940 }
941
942 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
943 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
944 {
945 static const WCHAR winehq_urlW[] =
946 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
947 '/','s','i','t','e','/','a','b','o','u','t',0};
948
949 CHECK_EXPECT(GetDisplayName);
950
951 ok(pbc != NULL, "pbc == NULL\n");
952 ok(pbc != _bctx, "pbc == _bctx\n");
953 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
954
955 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
956 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
957 return S_OK;
958 }
959
960 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
961 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
962 {
963 ok(0, "unexpected call\n");
964 return E_NOTIMPL;
965 }
966
967 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
968 {
969 CHECK_EXPECT2(IsSystemMoniker);
970
971 *pdwMksys = MKSYS_URLMONIKER;
972 return S_OK;
973 }
974
975 static IMonikerVtbl MonikerVtbl = {
976 Moniker_QueryInterface,
977 Moniker_AddRef,
978 Moniker_Release,
979 Moniker_GetClassID,
980 Moniker_IsDirty,
981 Moniker_Load,
982 Moniker_Save,
983 Moniker_GetSizeMax,
984 Moniker_BindToObject,
985 Moniker_BindToStorage,
986 Moniker_Reduce,
987 Moniker_ComposeWith,
988 Moniker_Enum,
989 Moniker_IsEqual,
990 Moniker_Hash,
991 Moniker_IsRunning,
992 Moniker_GetTimeOfLastChange,
993 Moniker_Inverse,
994 Moniker_CommonPrefixWith,
995 Moniker_RelativePathTo,
996 Moniker_GetDisplayName,
997 Moniker_ParseDisplayName,
998 Moniker_IsSystemMoniker
999 };
1000
1001 static IMoniker Moniker = { &MonikerVtbl };
1002
1003 static void test_HlinkResolveMonikerForData(void)
1004 {
1005 IBindCtx *bctx;
1006 HRESULT hres;
1007
1008 CreateBindCtx(0, &bctx);
1009 _bctx = bctx;
1010
1011 SET_EXPECT(IsSystemMoniker);
1012 SET_EXPECT(GetDisplayName);
1013 SET_EXPECT(BindToStorage);
1014
1015 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
1016 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
1017
1018 CHECK_CALLED(IsSystemMoniker);
1019 CHECK_CALLED(GetDisplayName);
1020 CHECK_CALLED(BindToStorage);
1021
1022 IBindCtx_Release(bctx);
1023 }
1024
1025 static void test_HlinkGetSetMonikerReference(void)
1026 {
1027 IMoniker *found_trgt, *dummy, *dummy2;
1028 IHlink *hlink;
1029 HRESULT hres;
1030 const WCHAR one[] = {'1',0};
1031 const WCHAR two[] = {'2',0};
1032 const WCHAR name[] = {'a',0};
1033 WCHAR *found_loc;
1034
1035 /* create two dummy monikers to use as targets */
1036 hres = CreateItemMoniker(one, one, &dummy);
1037 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1038
1039 hres = CreateItemMoniker(two, two, &dummy2);
1040 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1041
1042 /* create a new hlink: target => dummy, location => one */
1043 hres = HlinkCreateFromMoniker(dummy, one, name, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1044 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1045
1046 /* validate the target and location */
1047 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1048 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1049 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1050 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1051 IMoniker_Release(found_trgt);
1052 CoTaskMemFree(found_loc);
1053
1054 /* set location => two */
1055 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_LOCATION, dummy2, two);
1056 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1057
1058 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1059 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1060 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1061 IMoniker_Release(found_trgt);
1062 CoTaskMemFree(found_loc);
1063
1064 /* set target => dummy2 */
1065 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, dummy2, one);
1066 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1067
1068 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1069 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1070 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1071 IMoniker_Release(found_trgt);
1072 CoTaskMemFree(found_loc);
1073
1074 /* set target => dummy, location => one */
1075 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, dummy, one);
1076 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1077
1078 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1079 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1080 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1081 IMoniker_Release(found_trgt);
1082 CoTaskMemFree(found_loc);
1083
1084 /* no HLINKSETF flags */
1085 hres = IHlink_SetMonikerReference(hlink, 0, dummy2, two);
1086 ok(hres == E_INVALIDARG, "IHlink_SetMonikerReference should've failed with E_INVALIDARG (0x%08x), failed with 0x%08x\n", E_INVALIDARG, hres);
1087
1088 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1089 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1090 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1091 IMoniker_Release(found_trgt);
1092 CoTaskMemFree(found_loc);
1093
1094 /* invalid HLINKSETF flags */
1095 hres = IHlink_SetMonikerReference(hlink, 12, dummy2, two);
1096 ok(hres == 12, "IHlink_SetMonikerReference should've failed with 0x%08x, failed with 0x%08x\n", 12, hres);
1097
1098 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1099 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1100 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1101 IMoniker_Release(found_trgt);
1102 CoTaskMemFree(found_loc);
1103
1104 /* valid & invalid HLINKSETF flags */
1105 hres = IHlink_SetMonikerReference(hlink, 12 | HLINKSETF_TARGET, dummy2, two);
1106 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1107
1108 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1109 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, 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 /* NULL args */
1115 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, NULL, NULL);
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(found_trgt == NULL, "Found target should've been %p, was: %p\n", NULL, found_trgt);
1120 ok(found_loc == NULL, "Found location should've been %s, was: %s\n", wine_dbgstr_w(NULL), wine_dbgstr_w(found_loc));
1121 if(found_trgt)
1122 IMoniker_Release(found_trgt);
1123
1124 IHlink_Release(hlink);
1125 IMoniker_Release(dummy2);
1126 IMoniker_Release(dummy);
1127 }
1128
1129 static void test_HlinkGetSetStringReference(void)
1130 {
1131 IHlink *link;
1132 static const WCHAR one[] = {'1',0};
1133 static const WCHAR two[] = {'2',0};
1134 static const WCHAR three[] = {'3',0};
1135 static const WCHAR empty[] = {0};
1136 WCHAR *fnd_tgt, *fnd_loc;
1137 HRESULT hres;
1138
1139 /* create a new hlink: target => NULL, location => one */
1140 hres = HlinkCreateFromMoniker(NULL, one, empty, NULL, 0, NULL, &IID_IHlink, (void**)&link);
1141 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1142
1143 /* test setting/getting location */
1144 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1145 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1146 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1147 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1148 CoTaskMemFree(fnd_tgt);
1149 CoTaskMemFree(fnd_loc);
1150
1151 hres = IHlink_SetStringReference(link, HLINKSETF_LOCATION, one, two);
1152 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1153
1154 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1155 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1156 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1157 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1158 CoTaskMemFree(fnd_tgt);
1159 CoTaskMemFree(fnd_loc);
1160
1161 hres = IHlink_SetStringReference(link, -HLINKSETF_LOCATION, two, one);
1162 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1163
1164 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1165 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1166 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1167 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1168 CoTaskMemFree(fnd_tgt);
1169 CoTaskMemFree(fnd_loc);
1170
1171 /* test setting/getting target */
1172 hres = IHlink_SetStringReference(link, HLINKSETF_TARGET, two, three);
1173 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1174
1175 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1176 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1177 ok(!lstrcmpW(fnd_tgt, two), "Found target should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_tgt));
1178 ok(!lstrcmpW(fnd_loc, one), "Found location should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_loc));
1179 CoTaskMemFree(fnd_tgt);
1180 CoTaskMemFree(fnd_loc);
1181
1182 hres = IHlink_SetStringReference(link, -HLINKSETF_TARGET, three, two);
1183 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1184
1185 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1186 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1187 ok(!lstrcmpW(fnd_tgt, three), "Found target should have been %s, was: %s\n", wine_dbgstr_w(three), wine_dbgstr_w(fnd_tgt));
1188 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1189 CoTaskMemFree(fnd_tgt);
1190 CoTaskMemFree(fnd_loc);
1191
1192 /* test setting/getting both */
1193 hres = IHlink_SetStringReference(link, HLINKSETF_TARGET | HLINKSETF_LOCATION, one, two);
1194 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1195
1196 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1197 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1198 ok(!lstrcmpW(fnd_tgt, one), "Found target should have been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(fnd_tgt));
1199 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1200 CoTaskMemFree(fnd_tgt);
1201 CoTaskMemFree(fnd_loc);
1202
1203 hres = IHlink_SetStringReference(link, -(HLINKSETF_TARGET | HLINKSETF_LOCATION), three, one);
1204 ok(hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1205
1206 hres = IHlink_GetStringReference(link, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1207 ok(hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1208 ok(!lstrcmpW(fnd_tgt, three), "Found target should have been %s, was: %s\n", wine_dbgstr_w(three), wine_dbgstr_w(fnd_tgt));
1209 ok(!lstrcmpW(fnd_loc, two), "Found location should have been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(fnd_loc));
1210 CoTaskMemFree(fnd_tgt);
1211 CoTaskMemFree(fnd_loc);
1212
1213 /* test invalid flags/params */
1214 hres = IHlink_GetStringReference(link, 4, &fnd_tgt, &fnd_loc);
1215 ok(hres == E_INVALIDARG, "IHlink_GetStringReference should have failed "
1216 "with E_INVALIDARG (0x%08x), instead: 0x%08x\n", E_INVALIDARG, hres);
1217 ok(fnd_tgt == NULL, "Found target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1218 ok(fnd_loc == NULL, "Found location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1219 CoTaskMemFree(fnd_tgt);
1220 CoTaskMemFree(fnd_loc);
1221
1222 hres = IHlink_GetStringReference(link, -1, &fnd_tgt, NULL);
1223 todo_wine ok(hres == E_FAIL, "IHlink_GetStringReference should have failed "
1224 "with E_FAIL (0x%08x), instead: 0x%08x\n", E_FAIL, hres);
1225 CoTaskMemFree(fnd_tgt);
1226
1227 hres = IHlink_GetStringReference(link, -1, NULL, NULL);
1228 ok(hres == S_OK, "failed, hres=%08x\n", hres);
1229
1230 hres = IHlink_GetStringReference(link, -1, NULL, &fnd_loc);
1231 ok(hres == S_OK, "failed, hres=%08x\n", hres);
1232 CoTaskMemFree(fnd_loc);
1233
1234 hres = IHlink_GetStringReference(link, -1, &fnd_tgt, &fnd_loc);
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 CoTaskMemFree(fnd_loc);
1239
1240 hres = IHlink_GetStringReference(link, -2, &fnd_tgt, &fnd_loc);
1241 ok(hres == E_INVALIDARG, "IHlink_GetStringReference should have failed "
1242 "with E_INVALIDARG (0x%08x), instead: 0x%08x\n", E_INVALIDARG, hres);
1243 CoTaskMemFree(fnd_tgt);
1244 CoTaskMemFree(fnd_loc);
1245
1246 hres = IHlink_SetStringReference(link, 4, NULL, NULL);
1247 ok(hres == 4, "IHlink_SetStringReference should have failed with 0x4, instead: 0x%08x\n", hres);
1248
1249 hres = IHlink_SetStringReference(link, -4, NULL, NULL);
1250 ok(hres == -4, "IHlink_SetStringReference should have failed with 0xFFFFFFFC, instead: 0x%08x\n", hres);
1251
1252 IHlink_Release(link);
1253 }
1254
1255 #define setStringRef(h,f,t,l) r_setStringRef(__LINE__,h,f,t,l)
1256 static void r_setStringRef(unsigned line, IHlink *hlink, DWORD flags, const WCHAR *tgt, const WCHAR *loc)
1257 {
1258 HRESULT hres;
1259 hres = IHlink_SetStringReference(hlink, flags, tgt, loc);
1260 ok_(__FILE__,line) (hres == S_OK, "IHlink_SetStringReference failed: 0x%08x\n", hres);
1261 }
1262
1263 #define getStringRef(h,t,l) r_getStringRef(__LINE__,h,t,l)
1264 static void r_getStringRef(unsigned line, IHlink *hlink, const WCHAR *exp_tgt, const WCHAR *exp_loc)
1265 {
1266 HRESULT hres;
1267 WCHAR *fnd_tgt, *fnd_loc;
1268
1269 hres = IHlink_GetStringReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1270 ok_(__FILE__,line) (hres == S_OK, "IHlink_GetStringReference failed: 0x%08x\n", hres);
1271
1272 if(exp_tgt)
1273 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));
1274 else
1275 ok_(__FILE__,line) (exp_tgt == NULL, "Found string target should have been NULL, was: %s\n", wine_dbgstr_w(fnd_tgt));
1276
1277 if(exp_loc)
1278 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));
1279 else
1280 ok_(__FILE__,line) (exp_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1281
1282 CoTaskMemFree(fnd_tgt);
1283 CoTaskMemFree(fnd_loc);
1284 }
1285
1286 #define setMonikerRef(h,f,t,l) r_setMonikerRef(__LINE__,h,f,t,l)
1287 static void r_setMonikerRef(unsigned line, IHlink *hlink, DWORD flags, IMoniker *tgt, const WCHAR *loc)
1288 {
1289 HRESULT hres;
1290 hres = IHlink_SetMonikerReference(hlink, flags, tgt, loc);
1291 ok_(__FILE__,line) (hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1292 }
1293
1294 /* passing 0xFFFFFFFF as exp_tgt will return the retrieved target & not test it */
1295 #define getMonikerRef(h,t,l) r_getMonikerRef(__LINE__,h,t,l)
1296 static IMoniker *r_getMonikerRef(unsigned line, IHlink *hlink, IMoniker *exp_tgt, const WCHAR *exp_loc)
1297 {
1298 HRESULT hres;
1299 IMoniker *fnd_tgt;
1300 WCHAR *fnd_loc;
1301
1302 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &fnd_tgt, &fnd_loc);
1303 ok_(__FILE__,line) (hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1304
1305 if(exp_loc)
1306 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));
1307 else
1308 ok_(__FILE__,line) (exp_loc == NULL, "Found string location should have been NULL, was: %s\n", wine_dbgstr_w(fnd_loc));
1309
1310 CoTaskMemFree(fnd_loc);
1311
1312 if(exp_tgt == (IMoniker*)0xFFFFFFFF)
1313 return fnd_tgt;
1314
1315 ok_(__FILE__,line) (fnd_tgt == exp_tgt, "Found moniker target should have been %p, was: %p\n", exp_tgt, fnd_tgt);
1316
1317 if(fnd_tgt)
1318 IMoniker_Release(fnd_tgt);
1319
1320 return NULL;
1321 }
1322
1323 static void test_HlinkMoniker(void)
1324 {
1325 IHlink *hlink;
1326 IMoniker *aMon, *file_mon;
1327 static const WCHAR emptyW[] = {0};
1328 static const WCHAR wordsW[] = {'w','o','r','d','s',0};
1329 static const WCHAR aW[] = {'a',0};
1330 static const WCHAR bW[] = {'b',0};
1331 HRESULT hres;
1332
1333 hres = HlinkCreateFromString(NULL, NULL, NULL, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1334 ok(hres == S_OK, "HlinkCreateFromString failed: 0x%08x\n", hres);
1335 getStringRef(hlink, NULL, NULL);
1336 getMonikerRef(hlink, NULL, NULL);
1337
1338 /* setting a string target creates a moniker reference */
1339 setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, aW, wordsW);
1340 getStringRef(hlink, aW, wordsW);
1341 aMon = getMonikerRef(hlink, (IMoniker*)0xFFFFFFFF, wordsW);
1342 ok(aMon != NULL, "Moniker from %s target should not be NULL\n", wine_dbgstr_w(aW));
1343 if(aMon)
1344 IMoniker_Release(aMon);
1345
1346 /* setting target & location to the empty string deletes the moniker
1347 * reference */
1348 setStringRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, emptyW, emptyW);
1349 getStringRef(hlink, NULL, NULL);
1350 getMonikerRef(hlink, NULL, NULL);
1351
1352 /* setting a moniker target also sets the target string to that moniker's
1353 * display name */
1354 hres = CreateFileMoniker(bW, &file_mon);
1355 ok(hres == S_OK, "CreateFileMoniker failed: 0x%08x\n", hres);
1356
1357 setMonikerRef(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, file_mon, wordsW);
1358 getStringRef(hlink, bW, wordsW);
1359 getMonikerRef(hlink, file_mon, wordsW);
1360
1361 IMoniker_Release(file_mon);
1362
1363 IHlink_Release(hlink);
1364 }
1365
1366 START_TEST(hlink)
1367 {
1368 CoInitialize(NULL);
1369
1370 test_HlinkIsShortcut();
1371 test_reference();
1372 test_persist();
1373 test_special_reference();
1374 test_HlinkCreateExtensionServices();
1375 test_HlinkParseDisplayName();
1376 test_HlinkResolveMonikerForData();
1377 test_HlinkGetSetMonikerReference();
1378 test_HlinkGetSetStringReference();
1379 test_HlinkMoniker();
1380
1381 CoUninitialize();
1382 }