1a7536fee93116fb27d6e6b46ff216668fd26a49
[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 todo_wine {
141 ok(!lstrcmpW(str, url2), "url wrong\n");
142 }
143 CoTaskMemFree(str);
144
145 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
146 ok(r == S_OK, "failed\n");
147
148 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
149 ok(r == S_OK, "failed\n");
150 ok(str == NULL, "string should be null\n");
151
152 /* Unimplented functions checks */
153 r = IHlink_GetAdditionalParams(lnk, NULL);
154 ok(r == E_NOTIMPL, "failed\n");
155
156 r = IHlink_SetAdditionalParams(lnk, NULL);
157 ok(r == E_NOTIMPL, "failed\n");
158
159 IHlink_Release(lnk);
160 }
161
162 /* url only */
163 static const unsigned char expected_hlink_data[] =
164 {
165 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
166 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
167 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
168 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
169 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
170 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
171 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
172 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
173 0x00,0x00,
174 };
175
176 /* url only (IE7) */
177 static const unsigned char expected_hlink_data_ie7[] =
178 {
179 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
180 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
181 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
182 0x3e,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
183 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
184 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
185 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
186 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
187 0x00,0x00,0x79,0x58,0x81,0xf4,0x3b,0x1d,
188 0x7f,0x48,0xaf,0x2c,0x82,0x5d,0xc4,0x85,
189 0x27,0x63,0x00,0x00,0x00,0x00,0xa5,0xab,
190 0x00,0x00,
191 };
192
193 /* url + friendly name */
194 static const unsigned char expected_hlink_data2[] =
195 {
196 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
197 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
198 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
199 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
200 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
201 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
202 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
203 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
204 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
205 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
206 0x67,0x00,0x2f,0x00,0x00,0x00,
207 };
208
209 /* url + friendly name (IE7) */
210 static const unsigned char expected_hlink_data2_ie7[] =
211 {
212 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
213 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
214 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
215 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
216 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
217 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
218 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
219 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
220 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
221 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
222 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
223 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
224 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
225 0x00,0x00,0xa5,0xab,0x00,0x00,
226 };
227
228 /* url + friendly name + location */
229 static const unsigned char expected_hlink_data3[] =
230 {
231 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
232 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
233 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
234 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
235 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
236 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
237 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
238 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
239 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
240 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
241 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
242 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
243 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
244 };
245
246 /* url + friendly name + location (IE7) */
247 static const unsigned char expected_hlink_data3_ie7[] =
248 {
249 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
250 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
251 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
252 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
253 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
254 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
255 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
256 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
257 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
258 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
259 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
260 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
261 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
262 0x00,0x00,0xa5,0xab,0x00,0x00,0x07,0x00,
263 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
264 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
265 };
266
267 /* relative url */
268 static const unsigned char expected_hlink_data4[] =
269 {
270 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
271 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
272 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
273 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
274 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
275 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
276 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
277 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
278 0x00,0x00,0x00,0x00,0x00,
279 };
280
281 /* url + target frame name */
282 static const unsigned char expected_hlink_data5[] =
283 {
284 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
285 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
286 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
287 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
288 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
289 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
290 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
291 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
292 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
293 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
294 0x2f,0x00,0x00,0x00,
295 };
296
297 /* url + target frame name (IE7) */
298 static const unsigned char expected_hlink_data5_ie7[] =
299 {
300 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
301 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
302 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
303 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
304 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
305 0xa9,0x0b,0x3e,0x00,0x00,0x00,0x68,0x00,
306 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
307 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
308 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
309 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
310 0x2f,0x00,0x00,0x00,0x79,0x58,0x81,0xf4,
311 0x3b,0x1d,0x7f,0x48,0xaf,0x2c,0x82,0x5d,
312 0xc4,0x85,0x27,0x63,0x00,0x00,0x00,0x00,
313 0xa5,0xab,0x00,0x00,
314 };
315
316 /* filename */
317 static const unsigned char expected_hlink_data6[] =
318 {
319 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
320 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
321 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
322 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
323 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
324 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
325 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
326 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
327 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
328 0x5c,0x00,
329 };
330
331 static void test_persist_save_data(const char *testname, IHlink *lnk,
332 const unsigned char *expected_data,
333 unsigned int expected_data_size,
334 const unsigned char *expected_data_alt,
335 unsigned int expected_data_alt_size)
336 {
337 HRESULT hr;
338 IStream *stream;
339 IPersistStream *ps;
340 HGLOBAL hglobal;
341 DWORD data_size;
342 const unsigned char *data;
343 DWORD i;
344 BOOL same;
345 unsigned int expected_data_win9x_size = 0;
346
347 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
348 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
349
350 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
351 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
352
353 hr = IPersistStream_Save(ps, stream, TRUE);
354 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
355
356 hr = GetHGlobalFromStream(stream, &hglobal);
357 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
358
359 data_size = GlobalSize(hglobal);
360
361 data = GlobalLock(hglobal);
362
363 if (expected_data_size % 4)
364 expected_data_win9x_size = 4 * ((expected_data_size / 4) + 1);
365
366 /* first check we have the right amount of data */
367 ok((data_size == expected_data_size) ||
368 (data_size == expected_data_alt_size) ||
369 broken(data_size == expected_data_win9x_size), /* Win9x and WinMe */
370 "%s: Size of saved data differs (expected %d or %d, actual %d)\n",
371 testname, expected_data_size, expected_data_alt_size, data_size);
372
373 same = TRUE;
374 /* then do a byte-by-byte comparison */
375 for (i = 0; i < min(data_size, expected_data_size); i++)
376 {
377 if ((expected_data[i] != data[i]) &&
378 (((expected_data != expected_hlink_data2) &&
379 (expected_data != expected_hlink_data3)) ||
380 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
381 {
382 same = FALSE;
383 break;
384 }
385 }
386
387 if (!same && (expected_data_alt != expected_data))
388 {
389 /* then try the alternate data */
390 same = TRUE;
391 for (i = 0; i < min(data_size, expected_data_alt_size); i++)
392 {
393 if ((expected_data_alt[i] != data[i]) &&
394 (((expected_data_alt != expected_hlink_data2) &&
395 (expected_data_alt != expected_hlink_data3)) ||
396 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
397 {
398 same = FALSE;
399 break;
400 }
401 }
402 }
403
404 ok(same, "%s: Saved data differs\n", testname);
405 if (!same)
406 {
407 for (i = 0; i < data_size; i++)
408 {
409 if (i % 8 == 0) printf(" ");
410 printf("0x%02x,", data[i]);
411 if (i % 8 == 7) printf("\n");
412 }
413 printf("\n");
414 }
415
416 GlobalUnlock(hglobal);
417
418 IStream_Release(stream);
419 IPersistStream_Release(ps);
420 }
421
422 static void test_persist(void)
423 {
424 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
425 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
426 static const WCHAR filename[] = { 'c',':','\\',0 };
427 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
428 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
429 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
430 HRESULT hr;
431 IHlink *lnk;
432
433 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
434 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
435 ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr);
436 if (!lnk) {
437 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
438 return;
439 }
440 test_persist_save_data("url only", lnk,
441 expected_hlink_data, sizeof(expected_hlink_data),
442 expected_hlink_data_ie7, sizeof(expected_hlink_data_ie7));
443 IHlink_Release(lnk);
444
445 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
446 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
447 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
448 test_persist_save_data("url + friendly name", lnk,
449 expected_hlink_data2, sizeof(expected_hlink_data2),
450 expected_hlink_data2_ie7, sizeof(expected_hlink_data2_ie7));
451 IHlink_Release(lnk);
452
453 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
454 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
455 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
456 test_persist_save_data("url + friendly_name + location", lnk,
457 expected_hlink_data3, sizeof(expected_hlink_data3),
458 expected_hlink_data3_ie7, sizeof(expected_hlink_data3_ie7));
459 IHlink_Release(lnk);
460
461 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
462 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
463 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
464 test_persist_save_data("relative url", lnk,
465 expected_hlink_data4, sizeof(expected_hlink_data4),
466 expected_hlink_data4, sizeof(expected_hlink_data4));
467 IHlink_Release(lnk);
468
469 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
470 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
471 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
472 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
473 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
474 test_persist_save_data("url + target frame name", lnk,
475 expected_hlink_data5, sizeof(expected_hlink_data5),
476 expected_hlink_data5_ie7, sizeof(expected_hlink_data5_ie7));
477 IHlink_Release(lnk);
478
479 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
480 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
481 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
482 test_persist_save_data("filename", lnk,
483 expected_hlink_data6, sizeof(expected_hlink_data6),
484 expected_hlink_data6, sizeof(expected_hlink_data6));
485 IHlink_Release(lnk);
486 }
487
488 static void test_special_reference(void)
489 {
490 LPWSTR ref;
491 HRESULT hres;
492
493 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
494 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
495 ok(ref != NULL, "ref == NULL\n");
496 CoTaskMemFree(ref);
497
498 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
499 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
500 ok(ref != NULL, "ref == NULL\n");
501 CoTaskMemFree(ref);
502
503 ref = (void*)0xdeadbeef;
504 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
505 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
506 ok(ref == NULL, "ref=%p\n", ref);
507
508 ref = (void*)0xdeadbeef;
509 hres = HlinkGetSpecialReference(4, &ref);
510 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
511 ok(ref == NULL, "ref=%p\n", ref);
512 }
513
514 static void test_HlinkCreateExtensionServices(void)
515 {
516 IAuthenticate *authenticate;
517 IHttpNegotiate *http_negotiate;
518 LPWSTR password, username, headers;
519 HWND hwnd;
520 HRESULT hres;
521
522 static const WCHAR usernameW[] = {'u','s','e','r',0};
523 static const WCHAR passwordW[] = {'p','a','s','s',0};
524 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
525 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
526
527 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
528 NULL, &IID_IAuthenticate, (void**)&authenticate);
529 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
530 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
531
532 password = username = (void*)0xdeadbeef;
533 hwnd = (void*)0xdeadbeef;
534 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
535 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
536 ok(!hwnd, "hwnd != NULL\n");
537 ok(!username, "username != NULL\n");
538 ok(!password, "password != NULL\n");
539
540 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
541 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
542
543 headers = (void*)0xdeadbeef;
544 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
545 0, &headers);
546 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
547 ok(headers == NULL, "headers != NULL\n");
548
549 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
550 0, NULL);
551 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
552
553 headers = (void*)0xdeadbeef;
554 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
555 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
556 ok(headers == NULL, "headers != NULL\n");
557
558 IHttpNegotiate_Release(http_negotiate);
559 IAuthenticate_Release(authenticate);
560
561
562 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
563 NULL, &IID_IAuthenticate, (void**)&authenticate);
564 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
565 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
566
567 password = username = NULL;
568 hwnd = NULL;
569 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
570 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
571 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
572 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
573 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
574 CoTaskMemFree(username);
575 CoTaskMemFree(password);
576
577 password = username = (void*)0xdeadbeef;
578 hwnd = (void*)0xdeadbeef;
579 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
580 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
581 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
582 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
583
584 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
585 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
586
587 headers = (void*)0xdeadbeef;
588 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
589 0, &headers);
590 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
591 ok(!lstrcmpW(headers, headersexW), "unexpected headers %s\n", wine_dbgstr_w(headers));
592 CoTaskMemFree(headers);
593
594 headers = (void*)0xdeadbeef;
595 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
596 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
597 ok(headers == NULL, "unexpected headers %s\n", wine_dbgstr_w(headers));
598
599 IHttpNegotiate_Release(http_negotiate);
600 IAuthenticate_Release(authenticate);
601 }
602
603 static void test_HlinkParseDisplayName(void)
604 {
605 IMoniker *mon = NULL;
606 LPWSTR name;
607 DWORD issys;
608 ULONG eaten = 0;
609 IBindCtx *bctx;
610 HRESULT hres;
611
612 static const WCHAR winehq_urlW[] =
613 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
614 '/','s','i','t','e','/','a','b','o','u','t',0};
615 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
616 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
617 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
618 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
619
620 CreateBindCtx(0, &bctx);
621
622 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
623 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
624 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
625 ok(mon != NULL, "mon == NULL\n");
626
627 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
628 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
629 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
630 CoTaskMemFree(name);
631
632 hres = IMoniker_IsSystemMoniker(mon, &issys);
633 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
634 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
635
636 IMoniker_Release(mon);
637
638 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
639 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
640 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
641 ok(mon != NULL, "mon == NULL\n");
642
643 hres = IMoniker_IsSystemMoniker(mon, &issys);
644 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
645 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
646
647 IMoniker_Release(mon);
648
649 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
650 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
651 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
652 ok(mon != NULL, "mon == NULL\n");
653
654 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
655 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
656 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", wine_dbgstr_w(name));
657 CoTaskMemFree(name);
658
659 hres = IMoniker_IsSystemMoniker(mon, &issys);
660 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
661 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
662
663 IMoniker_Release(mon);
664 IBindCtx_Release(bctx);
665 }
666
667 static IBindCtx *_bctx;
668
669 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
670 {
671 ok(0, "unexpected call\n");
672 return E_NOINTERFACE;
673 }
674
675 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
676 {
677 return 2;
678 }
679
680 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
681 {
682 return 1;
683 }
684
685 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
686 REFGUID guidService, REFIID riid, void **ppv)
687 {
688 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
689 return E_NOINTERFACE;
690 }
691
692 static IServiceProviderVtbl ServiceProviderVtbl = {
693 ServiceProvider_QueryInterface,
694 ServiceProvider_AddRef,
695 ServiceProvider_Release,
696 ServiceProvider_QueryService
697 };
698
699 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
700
701 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
702 {
703 *ppv = NULL;
704
705 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
706 *ppv = &ServiceProvider;
707 return S_OK;
708 }
709
710 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
711 return E_NOINTERFACE;
712 }
713
714 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
715 {
716 return 2;
717 }
718
719 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
720 {
721 return 1;
722 }
723
724 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
725 IBinding *pib)
726 {
727 ok(0, "unexpected call\n");
728 return E_NOTIMPL;
729 }
730
731 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
732 {
733 ok(0, "unexpected call\n");
734 return E_NOTIMPL;
735 }
736
737 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
738 {
739 ok(0, "unexpected call\n");
740 return E_NOTIMPL;
741 }
742
743 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
744 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
745 {
746 ok(0, "unexpected call\n");
747 return E_NOTIMPL;
748 }
749
750 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
751 {
752 ok(0, "unexpected call\n");
753 return E_NOTIMPL;
754 }
755
756 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
757 {
758 ok(0, "unexpected call\n");
759 return E_NOTIMPL;
760 }
761
762 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
763 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
764 {
765 ok(0, "unexpected call\n");
766 return E_NOTIMPL;
767 }
768
769 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
770 {
771 ok(0, "unexpected call\n");
772 return E_NOTIMPL;
773 }
774
775 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
776 BindStatusCallback_QueryInterface,
777 BindStatusCallback_AddRef,
778 BindStatusCallback_Release,
779 BindStatusCallback_OnStartBinding,
780 BindStatusCallback_GetPriority,
781 BindStatusCallback_OnLowResource,
782 BindStatusCallback_OnProgress,
783 BindStatusCallback_OnStopBinding,
784 BindStatusCallback_GetBindInfo,
785 BindStatusCallback_OnDataAvailable,
786 BindStatusCallback_OnObjectAvailable
787 };
788
789 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
790
791 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
792 {
793 *ppv = NULL;
794
795 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
796 return E_NOINTERFACE;
797 }
798
799 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
800 {
801 return 2;
802 }
803
804 static ULONG WINAPI Moniker_Release(IMoniker *iface)
805 {
806 return 1;
807 }
808
809 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
810 {
811 ok(0, "unexpected call\n");
812 return E_NOTIMPL;
813 }
814
815 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
816 {
817 ok(0, "unexpected call\n");
818 return E_NOTIMPL;
819 }
820
821 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
822 {
823 ok(0, "unexpected call\n");
824 return E_NOTIMPL;
825 }
826
827 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
828 {
829 ok(0, "unexpected call\n");
830 return E_NOTIMPL;
831 }
832
833 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
834 {
835 ok(0, "unexpected call\n");
836 return E_NOTIMPL;
837 }
838
839 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
840 REFIID riidResult, void **ppvResult)
841 {
842 ok(0, "unexpected call\n");
843 return E_NOTIMPL;
844 }
845
846 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
847 REFIID riid, void **ppv)
848 {
849 IUnknown *unk;
850 HRESULT hres;
851
852 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
853
854 CHECK_EXPECT(BindToStorage);
855
856 ok(pbc == _bctx, "pbc != _bctx\n");
857 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
858 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
859 ok(ppv != NULL, "ppv == NULL\n");
860 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
861
862 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
863 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
864 ok(unk != NULL, "unk == NULL\n");
865
866 IUnknown_Release(unk);
867
868 return S_OK;
869 }
870
871 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
872 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
873 {
874 ok(0, "unexpected call\n");
875 return E_NOTIMPL;
876 }
877
878 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
879 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
880 {
881 ok(0, "unexpected call\n");
882 return E_NOTIMPL;
883 }
884
885 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
886 {
887 ok(0, "unexpected call\n");
888 return E_NOTIMPL;
889 }
890
891 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
892 {
893 ok(0, "unexpected call\n");
894 return E_NOTIMPL;
895 }
896
897 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
898 {
899 ok(0, "unexpected call\n");
900 return E_NOTIMPL;
901 }
902
903 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
904 IMoniker *pmkNewlyRunning)
905 {
906 ok(0, "unexpected call\n");
907 return E_NOTIMPL;
908 }
909
910 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
911 IMoniker *pmkToLeft, FILETIME *pFileTime)
912 {
913 ok(0, "unexpected call\n");
914 return E_NOTIMPL;
915 }
916
917 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
918 {
919 ok(0, "unexpected call\n");
920 return E_NOTIMPL;
921 }
922
923 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
924 IMoniker **ppmkPrefix)
925 {
926 ok(0, "unexpected call\n");
927 return E_NOTIMPL;
928 }
929
930 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
931 IMoniker **pmkRelPath)
932 {
933 ok(0, "unexpected call\n");
934 return E_NOTIMPL;
935 }
936
937 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
938 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
939 {
940 static const WCHAR winehq_urlW[] =
941 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
942 '/','s','i','t','e','/','a','b','o','u','t',0};
943
944 CHECK_EXPECT(GetDisplayName);
945
946 ok(pbc != NULL, "pbc == NULL\n");
947 ok(pbc != _bctx, "pbc == _bctx\n");
948 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
949
950 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
951 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
952 return S_OK;
953 }
954
955 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
956 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
957 {
958 ok(0, "unexpected call\n");
959 return E_NOTIMPL;
960 }
961
962 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
963 {
964 CHECK_EXPECT2(IsSystemMoniker);
965
966 *pdwMksys = MKSYS_URLMONIKER;
967 return S_OK;
968 }
969
970 static IMonikerVtbl MonikerVtbl = {
971 Moniker_QueryInterface,
972 Moniker_AddRef,
973 Moniker_Release,
974 Moniker_GetClassID,
975 Moniker_IsDirty,
976 Moniker_Load,
977 Moniker_Save,
978 Moniker_GetSizeMax,
979 Moniker_BindToObject,
980 Moniker_BindToStorage,
981 Moniker_Reduce,
982 Moniker_ComposeWith,
983 Moniker_Enum,
984 Moniker_IsEqual,
985 Moniker_Hash,
986 Moniker_IsRunning,
987 Moniker_GetTimeOfLastChange,
988 Moniker_Inverse,
989 Moniker_CommonPrefixWith,
990 Moniker_RelativePathTo,
991 Moniker_GetDisplayName,
992 Moniker_ParseDisplayName,
993 Moniker_IsSystemMoniker
994 };
995
996 static IMoniker Moniker = { &MonikerVtbl };
997
998 static void test_HlinkResolveMonikerForData(void)
999 {
1000 IBindCtx *bctx;
1001 HRESULT hres;
1002
1003 CreateBindCtx(0, &bctx);
1004 _bctx = bctx;
1005
1006 SET_EXPECT(IsSystemMoniker);
1007 SET_EXPECT(GetDisplayName);
1008 SET_EXPECT(BindToStorage);
1009
1010 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
1011 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
1012
1013 CHECK_CALLED(IsSystemMoniker);
1014 CHECK_CALLED(GetDisplayName);
1015 CHECK_CALLED(BindToStorage);
1016
1017 IBindCtx_Release(bctx);
1018 }
1019
1020 static void test_HlinkGetSetMonikerReference(void)
1021 {
1022 IMoniker *found_trgt, *dummy, *dummy2;
1023 IHlink *hlink;
1024 HRESULT hres;
1025 const WCHAR one[] = {'1',0};
1026 const WCHAR two[] = {'2',0};
1027 const WCHAR name[] = {'a',0};
1028 WCHAR *found_loc;
1029
1030 /* create two dummy monikers to use as targets */
1031 hres = CreateItemMoniker(one, one, &dummy);
1032 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1033
1034 hres = CreateItemMoniker(two, two, &dummy2);
1035 ok(hres == S_OK, "CreateItemMoniker failed: 0x%08x\n", hres);
1036
1037 /* create a new hlink: target => dummy, location => one */
1038 hres = HlinkCreateFromMoniker(dummy, one, name, NULL, 0, NULL, &IID_IHlink, (void**)&hlink);
1039 ok(hres == S_OK, "HlinkCreateFromMoniker failed: 0x%08x\n", hres);
1040
1041 /* validate the target and location */
1042 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1043 ok(hres == S_OK, "IHlink_GetMonikerReference failed: 0x%08x\n", hres);
1044 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1045 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1046 IMoniker_Release(found_trgt);
1047 CoTaskMemFree(found_loc);
1048
1049 /* set location => two */
1050 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_LOCATION, dummy2, two);
1051 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1052
1053 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1054 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1055 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1056 IMoniker_Release(found_trgt);
1057 CoTaskMemFree(found_loc);
1058
1059 /* set target => dummy2 */
1060 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET, dummy2, one);
1061 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1062
1063 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1064 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1065 ok(lstrcmpW(found_loc, two) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(two), wine_dbgstr_w(found_loc));
1066 IMoniker_Release(found_trgt);
1067 CoTaskMemFree(found_loc);
1068
1069 /* set target => dummy, location => one */
1070 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, dummy, one);
1071 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1072
1073 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1074 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1075 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1076 IMoniker_Release(found_trgt);
1077 CoTaskMemFree(found_loc);
1078
1079 /* no HLINKSETF flags */
1080 hres = IHlink_SetMonikerReference(hlink, 0, dummy2, two);
1081 ok(hres == E_INVALIDARG, "IHlink_SetMonikerReference should've failed with E_INVALIDARG (0x%08x), failed with 0x%08x\n", E_INVALIDARG, hres);
1082
1083 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1084 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1085 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1086 IMoniker_Release(found_trgt);
1087 CoTaskMemFree(found_loc);
1088
1089 /* invalid HLINKSETF flags */
1090 hres = IHlink_SetMonikerReference(hlink, 12, dummy2, two);
1091 ok(hres == 12, "IHlink_SetMonikerReference should've failed with 0x%08x, failed with 0x%08x\n", 12, hres);
1092
1093 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1094 ok(found_trgt == dummy, "Found target should've been %p, was: %p\n", dummy, found_trgt);
1095 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1096 IMoniker_Release(found_trgt);
1097 CoTaskMemFree(found_loc);
1098
1099 /* valid & invalid HLINKSETF flags */
1100 hres = IHlink_SetMonikerReference(hlink, 12 | HLINKSETF_TARGET, dummy2, two);
1101 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1102
1103 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1104 ok(found_trgt == dummy2, "Found target should've been %p, was: %p\n", dummy2, found_trgt);
1105 ok(lstrcmpW(found_loc, one) == 0, "Found location should've been %s, was: %s\n", wine_dbgstr_w(one), wine_dbgstr_w(found_loc));
1106 IMoniker_Release(found_trgt);
1107 CoTaskMemFree(found_loc);
1108
1109 /* NULL args */
1110 hres = IHlink_SetMonikerReference(hlink, HLINKSETF_TARGET | HLINKSETF_LOCATION, NULL, NULL);
1111 ok(hres == S_OK, "IHlink_SetMonikerReference failed: 0x%08x\n", hres);
1112
1113 hres = IHlink_GetMonikerReference(hlink, HLINKGETREF_DEFAULT, &found_trgt, &found_loc);
1114 ok(found_trgt == NULL, "Found target should've been %p, was: %p\n", NULL, found_trgt);
1115 ok(found_loc == NULL, "Found location should've been %s, was: %s\n", wine_dbgstr_w(NULL), wine_dbgstr_w(found_loc));
1116 if(found_trgt)
1117 IMoniker_Release(found_trgt);
1118
1119 IHlink_Release(hlink);
1120 IMoniker_Release(dummy2);
1121 IMoniker_Release(dummy);
1122 }
1123
1124 START_TEST(hlink)
1125 {
1126 CoInitialize(NULL);
1127
1128 test_HlinkIsShortcut();
1129 test_reference();
1130 test_persist();
1131 test_special_reference();
1132 test_HlinkCreateExtensionServices();
1133 test_HlinkParseDisplayName();
1134 test_HlinkResolveMonikerForData();
1135 test_HlinkGetSetMonikerReference();
1136
1137 CoUninitialize();
1138 }