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