push e8d2f3f1a5d20911a70f6477421a6c3dacf00760
[wine/hacks.git] / dlls / hlink / tests / hlink.c
blob89b7c7a954b2717e2a182af47dc299c497325a11
1 /*
2 * Implementation of hyperlinking (hlink.dll)
4 * Copyright 2006 Mike McCormack
5 * Copyright 2007-2008 Jacek Caban for CodeWeavers
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.
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.
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
22 #define COBJMACROS
24 #include <stdio.h>
26 #include <initguid.h>
27 #include <hlink.h>
28 #include <hlguids.h>
30 #include "wine/test.h"
32 #define DEFINE_EXPECT(func) \
33 static BOOL expect_ ## func = FALSE, called_ ## func = FALSE
35 #define SET_EXPECT(func) \
36 expect_ ## func = TRUE
38 #define CHECK_EXPECT2(func) \
39 do { \
40 ok(expect_ ##func, "unexpected call " #func "\n"); \
41 called_ ## func = TRUE; \
42 }while(0)
44 #define CHECK_EXPECT(func) \
45 do { \
46 CHECK_EXPECT2(func); \
47 expect_ ## func = FALSE; \
48 }while(0)
50 #define CHECK_CALLED(func) \
51 do { \
52 ok(called_ ## func, "expected " #func "\n"); \
53 expect_ ## func = called_ ## func = FALSE; \
54 }while(0)
56 DEFINE_EXPECT(IsSystemMoniker);
57 DEFINE_EXPECT(BindToStorage);
58 DEFINE_EXPECT(GetDisplayName);
60 static const char *debugstr_w(LPCWSTR str)
62 static char buf[1024];
63 if(!str)
64 return "(null)";
65 WideCharToMultiByte(CP_ACP, 0, str, -1, buf, sizeof(buf), NULL, NULL);
66 return buf;
69 static const char *debugstr_guid(REFIID riid)
71 static char buf[50];
73 sprintf(buf, "{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
74 riid->Data1, riid->Data2, riid->Data3, riid->Data4[0],
75 riid->Data4[1], riid->Data4[2], riid->Data4[3], riid->Data4[4],
76 riid->Data4[5], riid->Data4[6], riid->Data4[7]);
78 return buf;
81 static void test_HlinkIsShortcut(void)
83 int i;
84 HRESULT hres;
86 static const WCHAR file0[] = {'f','i','l','e',0};
87 static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
88 static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
89 static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
90 static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
91 static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
92 static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
93 static const WCHAR file7[] = {'.','u','r','l',0};
95 static struct {
96 LPCWSTR file;
97 HRESULT hres;
98 } shortcut_test[] = {
99 {file0, S_FALSE},
100 {file1, S_OK},
101 {file2, S_FALSE},
102 {file3, S_OK},
103 {file4, S_FALSE},
104 {file5, S_OK},
105 {file6, S_FALSE},
106 {file7, S_OK},
107 {NULL, E_INVALIDARG}
110 for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
111 hres = HlinkIsShortcut(shortcut_test[i].file);
112 ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
113 i, hres, shortcut_test[i].hres);
117 static void test_reference(void)
119 HRESULT r;
120 IHlink *lnk = NULL;
121 IMoniker *mk = NULL;
122 const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
123 const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
124 LPWSTR str = NULL;
126 r = HlinkCreateFromString(url, NULL, NULL, NULL,
127 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
128 ok(r == S_OK, "failed to create link\n");
129 if (FAILED(r))
130 return;
132 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
133 ok(r == S_OK, "failed\n");
135 r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
136 ok(r == S_OK, "failed\n");
137 ok(mk != NULL, "no moniker\n");
138 ok(str == NULL, "string should be null\n");
140 r = IMoniker_Release(mk);
141 ok( r == 1, "moniker refcount wrong\n");
143 r = IHlink_GetStringReference(lnk, -1, &str, NULL);
144 ok(r == S_OK, "failed\n");
145 CoTaskMemFree(str);
147 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
148 ok(r == S_OK, "failed\n");
149 todo_wine {
150 ok(!lstrcmpW(str, url2), "url wrong\n");
152 CoTaskMemFree(str);
154 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
155 ok(r == S_OK, "failed\n");
157 r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
158 ok(r == S_OK, "failed\n");
159 ok(str == NULL, "string should be null\n");
161 /* Unimplented functions checks */
162 r = IHlink_GetAdditionalParams(lnk, NULL);
163 ok(r == E_NOTIMPL, "failed\n");
165 r = IHlink_SetAdditionalParams(lnk, NULL);
166 ok(r == E_NOTIMPL, "failed\n");
168 IHlink_Release(lnk);
171 /* url only */
172 static const unsigned char expected_hlink_data[] =
174 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
175 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
176 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
177 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
178 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
179 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
180 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
181 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
182 0x00,0x00,
185 /* url only (IE7) */
186 static const unsigned char expected_hlink_data_ie7[] =
188 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
189 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
190 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
191 0x3e,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
192 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
193 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
194 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
195 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
196 0x00,0x00,0x79,0x58,0x81,0xf4,0x3b,0x1d,
197 0x7f,0x48,0xaf,0x2c,0x82,0x5d,0xc4,0x85,
198 0x27,0x63,0x00,0x00,0x00,0x00,0xa5,0xab,
199 0x00,0x00,
202 /* url + friendly name */
203 static const unsigned char expected_hlink_data2[] =
205 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
206 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
207 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
208 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
209 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
210 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
211 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
212 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
213 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
214 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
215 0x67,0x00,0x2f,0x00,0x00,0x00,
218 /* url + friendly name (IE7) */
219 static const unsigned char expected_hlink_data2_ie7[] =
221 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
222 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
223 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
224 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
225 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
226 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
227 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
228 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
229 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
230 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
231 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
232 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
233 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
234 0x00,0x00,0xa5,0xab,0x00,0x00,
237 /* url + friendly name + location */
238 static const unsigned char expected_hlink_data3[] =
240 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
241 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
242 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
243 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
244 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
245 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
246 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
247 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
248 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
249 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
250 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
251 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
252 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
255 /* url + friendly name + location (IE7) */
256 static const unsigned char expected_hlink_data3_ie7[] =
258 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
259 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
260 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
261 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
262 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
263 0x00,0x4b,0xa9,0x0b,0x3e,0x00,0x00,0x00,
264 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
265 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
266 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
267 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
268 0x67,0x00,0x2f,0x00,0x00,0x00,0x79,0x58,
269 0x81,0xf4,0x3b,0x1d,0x7f,0x48,0xaf,0x2c,
270 0x82,0x5d,0xc4,0x85,0x27,0x63,0x00,0x00,
271 0x00,0x00,0xa5,0xab,0x00,0x00,0x07,0x00,
272 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
273 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
276 /* relative url */
277 static const unsigned char expected_hlink_data4[] =
279 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
280 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
281 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
282 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
283 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
284 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
285 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
286 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
287 0x00,0x00,0x00,0x00,0x00,
290 /* url + target frame name */
291 static const unsigned char expected_hlink_data5[] =
293 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
294 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
295 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
296 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
297 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
298 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
299 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
300 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
301 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
302 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
303 0x2f,0x00,0x00,0x00,
306 /* url + target frame name (IE7) */
307 static const unsigned char expected_hlink_data5_ie7[] =
309 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
310 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
311 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
312 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
313 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
314 0xa9,0x0b,0x3e,0x00,0x00,0x00,0x68,0x00,
315 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
316 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
317 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
318 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
319 0x2f,0x00,0x00,0x00,0x79,0x58,0x81,0xf4,
320 0x3b,0x1d,0x7f,0x48,0xaf,0x2c,0x82,0x5d,
321 0xc4,0x85,0x27,0x63,0x00,0x00,0x00,0x00,
322 0xa5,0xab,0x00,0x00,
325 /* filename */
326 static const unsigned char expected_hlink_data6[] =
328 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
329 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
330 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
331 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
332 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
333 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
334 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
335 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
336 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
337 0x5c,0x00,
340 static void test_persist_save_data(const char *testname, IHlink *lnk,
341 const unsigned char *expected_data,
342 unsigned int expected_data_size,
343 const unsigned char *expected_data_alt,
344 unsigned int expected_data_alt_size)
346 HRESULT hr;
347 IStream *stream;
348 IPersistStream *ps;
349 HGLOBAL hglobal;
350 DWORD data_size;
351 const unsigned char *data;
352 DWORD i;
353 BOOL same;
355 hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
356 ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
358 hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
359 ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
361 hr = IPersistStream_Save(ps, stream, TRUE);
362 ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
364 hr = GetHGlobalFromStream(stream, &hglobal);
365 ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
367 data_size = GlobalSize(hglobal);
369 data = GlobalLock(hglobal);
371 /* first check we have the right amount of data */
372 ok((data_size == expected_data_size) || (data_size == expected_data_alt_size),
373 "%s: Size of saved data differs (expected %d or %d, actual %d)\n",
374 testname, expected_data_size, expected_data_alt_size, data_size);
376 same = TRUE;
377 /* then do a byte-by-byte comparison */
378 for (i = 0; i < min(data_size, expected_data_size); i++)
380 if ((expected_data[i] != data[i]) &&
381 (((expected_data != expected_hlink_data2) &&
382 (expected_data != expected_hlink_data3)) ||
383 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
385 same = FALSE;
386 break;
390 if (!same && (expected_data_alt != expected_data))
392 /* then try the alternate data */
393 same = TRUE;
394 for (i = 0; i < min(data_size, expected_data_alt_size); i++)
396 if ((expected_data_alt[i] != data[i]) &&
397 (((expected_data_alt != expected_hlink_data2) &&
398 (expected_data_alt != expected_hlink_data3)) ||
399 ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
401 same = FALSE;
402 break;
407 ok(same, "%s: Saved data differs\n", testname);
408 if (!same)
410 for (i = 0; i < data_size; i++)
412 if (i % 8 == 0) printf(" ");
413 printf("0x%02x,", data[i]);
414 if (i % 8 == 7) printf("\n");
416 printf("\n");
419 GlobalUnlock(hglobal);
421 IStream_Release(stream);
422 IPersistStream_Release(ps);
425 static void test_persist(void)
427 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
428 static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
429 static const WCHAR filename[] = { 'c',':','\\',0 };
430 static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
431 static const WCHAR location[] = { '_','b','l','a','n','k',0 };
432 static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
433 HRESULT hr;
434 IHlink *lnk;
436 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
437 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
438 ok(hr == S_OK, "IHlinkCreateFromString failed with error 0x%08x\n", hr);
439 if (!lnk) {
440 skip("Can't create lnk, skipping test_persist. Was wineprefixcreate run properly?\n");
441 return;
443 test_persist_save_data("url only", lnk,
444 expected_hlink_data, sizeof(expected_hlink_data),
445 expected_hlink_data_ie7, sizeof(expected_hlink_data_ie7));
446 IHlink_Release(lnk);
448 hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
449 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
450 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
451 test_persist_save_data("url + friendly name", lnk,
452 expected_hlink_data2, sizeof(expected_hlink_data2),
453 expected_hlink_data2_ie7, sizeof(expected_hlink_data2_ie7));
454 IHlink_Release(lnk);
456 hr = HlinkCreateFromString(url, location, friendly_name, NULL,
457 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
458 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
459 test_persist_save_data("url + friendly_name + location", lnk,
460 expected_hlink_data3, sizeof(expected_hlink_data3),
461 expected_hlink_data3_ie7, sizeof(expected_hlink_data3_ie7));
462 IHlink_Release(lnk);
464 hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
465 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
466 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
467 test_persist_save_data("relative url", lnk,
468 expected_hlink_data4, sizeof(expected_hlink_data4),
469 expected_hlink_data4, sizeof(expected_hlink_data4));
470 IHlink_Release(lnk);
472 hr = HlinkCreateFromString(url, NULL, NULL, NULL,
473 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
474 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
475 hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
476 ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
477 test_persist_save_data("url + target frame name", lnk,
478 expected_hlink_data5, sizeof(expected_hlink_data5),
479 expected_hlink_data5_ie7, sizeof(expected_hlink_data5_ie7));
480 IHlink_Release(lnk);
482 hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
483 0, NULL, &IID_IHlink, (LPVOID*) &lnk);
484 ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
485 test_persist_save_data("filename", lnk,
486 expected_hlink_data6, sizeof(expected_hlink_data6),
487 expected_hlink_data6, sizeof(expected_hlink_data6));
488 IHlink_Release(lnk);
491 static void test_special_reference(void)
493 LPWSTR ref;
494 HRESULT hres;
496 hres = HlinkGetSpecialReference(HLSR_HOME, &ref);
497 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres);
498 ok(ref != NULL, "ref == NULL\n");
499 CoTaskMemFree(ref);
501 hres = HlinkGetSpecialReference(HLSR_SEARCHPAGE, &ref);
502 ok(hres == S_OK, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres);
503 ok(ref != NULL, "ref == NULL\n");
504 CoTaskMemFree(ref);
506 ref = (void*)0xdeadbeef;
507 hres = HlinkGetSpecialReference(HLSR_HISTORYFOLDER, &ref);
508 ok(hres == E_NOTIMPL, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
509 ok(ref == NULL, "ref=%p\n", ref);
511 ref = (void*)0xdeadbeef;
512 hres = HlinkGetSpecialReference(4, &ref);
513 ok(hres == E_INVALIDARG, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres);
514 ok(ref == NULL, "ref=%p\n", ref);
517 static void test_HlinkCreateExtensionServices(void)
519 IAuthenticate *authenticate;
520 IHttpNegotiate *http_negotiate;
521 LPWSTR password, username, headers;
522 HWND hwnd;
523 HRESULT hres;
525 static const WCHAR usernameW[] = {'u','s','e','r',0};
526 static const WCHAR passwordW[] = {'p','a','s','s',0};
527 static const WCHAR headersW[] = {'h','e','a','d','e','r','s',0};
528 static const WCHAR headersexW[] = {'h','e','a','d','e','r','s','\r','\n',0};
530 hres = HlinkCreateExtensionServices(NULL, NULL, NULL, NULL,
531 NULL, &IID_IAuthenticate, (void**)&authenticate);
532 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
533 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
535 password = username = (void*)0xdeadbeef;
536 hwnd = (void*)0xdeadbeef;
537 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
538 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
539 ok(!hwnd, "hwnd != NULL\n");
540 ok(!username, "username != NULL\n");
541 ok(!password, "password != NULL\n");
543 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
544 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
546 headers = (void*)0xdeadbeef;
547 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
548 0, &headers);
549 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
550 ok(headers == NULL, "headers != NULL\n");
552 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
553 0, NULL);
554 ok(hres == E_INVALIDARG, "BeginningTransaction failed: %08x, expected E_INVALIDARG\n", hres);
556 headers = (void*)0xdeadbeef;
557 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
558 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
559 ok(headers == NULL, "headers != NULL\n");
561 IHttpNegotiate_Release(http_negotiate);
562 IAuthenticate_Release(authenticate);
565 hres = HlinkCreateExtensionServices(headersW, (HWND)0xfefefefe, usernameW, passwordW,
566 NULL, &IID_IAuthenticate, (void**)&authenticate);
567 ok(hres == S_OK, "HlinkCreateExtensionServices failed: %08x\n", hres);
568 ok(authenticate != NULL, "HlinkCreateExtensionServices returned NULL\n");
570 password = username = NULL;
571 hwnd = NULL;
572 hres = IAuthenticate_Authenticate(authenticate, &hwnd, &username, &password);
573 ok(hres == S_OK, "Authenticate failed: %08x\n", hres);
574 ok(hwnd == (HWND)0xfefefefe, "hwnd=%p\n", hwnd);
575 ok(!lstrcmpW(username, usernameW), "unexpected username\n");
576 ok(!lstrcmpW(password, passwordW), "unexpected password\n");
577 CoTaskMemFree(username);
578 CoTaskMemFree(password);
580 password = username = (void*)0xdeadbeef;
581 hwnd = (void*)0xdeadbeef;
582 hres = IAuthenticate_Authenticate(authenticate, &hwnd, NULL, &password);
583 ok(hres == E_INVALIDARG, "Authenticate failed: %08x\n", hres);
584 ok(password == (void*)0xdeadbeef, "password = %p\n", password);
585 ok(hwnd == (void*)0xdeadbeef, "hwnd = %p\n", hwnd);
587 hres = IAuthenticate_QueryInterface(authenticate, &IID_IHttpNegotiate, (void**)&http_negotiate);
588 ok(hres == S_OK, "Could not get IHttpNegotiate interface: %08x\n", hres);
590 headers = (void*)0xdeadbeef;
591 hres = IHttpNegotiate_BeginningTransaction(http_negotiate, (void*)0xdeadbeef, (void*)0xdeadbeef,
592 0, &headers);
593 ok(hres == S_OK, "BeginningTransaction failed: %08x\n", hres);
594 ok(!lstrcmpW(headers, headersexW), "unexpected headers \"%s\"\n", debugstr_w(headers));
595 CoTaskMemFree(headers);
597 headers = (void*)0xdeadbeef;
598 hres = IHttpNegotiate_OnResponse(http_negotiate, 200, (void*)0xdeadbeef, (void*)0xdeadbeef, &headers);
599 ok(hres == S_OK, "OnResponse failed: %08x\n", hres);
600 ok(headers == NULL, "unexpected headers \"%s\"\n", debugstr_w(headers));
602 IHttpNegotiate_Release(http_negotiate);
603 IAuthenticate_Release(authenticate);
606 static void test_HlinkParseDisplayName(void)
608 IMoniker *mon = NULL;
609 LPWSTR name;
610 DWORD issys;
611 ULONG eaten = 0;
612 IBindCtx *bctx;
613 HRESULT hres;
615 static const WCHAR winehq_urlW[] =
616 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
617 '/','s','i','t','e','/','a','b','o','u','t',0};
618 static const WCHAR invalid_urlW[] = {'t','e','s','t',':','1','2','3','a','b','c',0};
619 static const WCHAR clsid_nameW[] = {'c','l','s','i','d',':',
620 '2','0','D','0','4','F','E','0','-','3','A','E','A','-','1','0','6','9','-','A','2','D','8',
621 '-','0','8','0','0','2','B','3','0','3','0','9','D',':',0};
623 CreateBindCtx(0, &bctx);
625 hres = HlinkParseDisplayName(bctx, winehq_urlW, FALSE, &eaten, &mon);
626 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
627 ok(eaten == sizeof(winehq_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
628 ok(mon != NULL, "mon == NULL\n");
630 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
631 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
632 ok(!lstrcmpW(name, winehq_urlW), "wrong display name %s\n", debugstr_w(name));
633 CoTaskMemFree(name);
635 hres = IMoniker_IsSystemMoniker(mon, &issys);
636 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
637 ok(issys == MKSYS_URLMONIKER, "issys=%x\n", issys);
639 IMoniker_Release(mon);
641 hres = HlinkParseDisplayName(bctx, clsid_nameW, FALSE, &eaten, &mon);
642 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
643 ok(eaten == sizeof(clsid_nameW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
644 ok(mon != NULL, "mon == NULL\n");
646 hres = IMoniker_IsSystemMoniker(mon, &issys);
647 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
648 ok(issys == MKSYS_CLASSMONIKER, "issys=%x\n", issys);
650 IMoniker_Release(mon);
652 hres = HlinkParseDisplayName(bctx, invalid_urlW, FALSE, &eaten, &mon);
653 ok(hres == S_OK, "HlinkParseDisplayName failed: %08x\n", hres);
654 ok(eaten == sizeof(invalid_urlW)/sizeof(WCHAR)-1, "eaten=%d\n", eaten);
655 ok(mon != NULL, "mon == NULL\n");
657 hres = IMoniker_GetDisplayName(mon, bctx, 0, &name);
658 ok(hres == S_OK, "GetDiasplayName failed: %08x\n", hres);
659 ok(!lstrcmpW(name, invalid_urlW), "wrong display name %s\n", debugstr_w(name));
660 CoTaskMemFree(name);
662 hres = IMoniker_IsSystemMoniker(mon, &issys);
663 ok(hres == S_OK, "IsSystemMoniker failed: %08x\n", hres);
664 ok(issys == MKSYS_FILEMONIKER, "issys=%x\n", issys);
666 IBindCtx_Release(bctx);
669 static IBindCtx *_bctx;
671 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **ppv)
673 ok(0, "unexpected call\n");
674 return E_NOINTERFACE;
677 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
679 return 2;
682 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
684 return 1;
687 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface,
688 REFGUID guidService, REFIID riid, void **ppv)
690 ok(0, "unexpected service %s\n", debugstr_guid(guidService));
691 return E_NOINTERFACE;
694 static IServiceProviderVtbl ServiceProviderVtbl = {
695 ServiceProvider_QueryInterface,
696 ServiceProvider_AddRef,
697 ServiceProvider_Release,
698 ServiceProvider_QueryService
701 static IServiceProvider ServiceProvider = { &ServiceProviderVtbl };
703 static HRESULT WINAPI BindStatusCallback_QueryInterface(IBindStatusCallback *iface, REFIID riid, void **ppv)
705 *ppv = NULL;
707 if(IsEqualGUID(riid, &IID_IServiceProvider)) {
708 *ppv = &ServiceProvider;
709 return S_OK;
712 ok(0, "unexpected interface %s\n", debugstr_guid(riid));
713 return E_NOINTERFACE;
716 static ULONG WINAPI BindStatusCallback_AddRef(IBindStatusCallback *iface)
718 return 2;
721 static ULONG WINAPI BindStatusCallback_Release(IBindStatusCallback *iface)
723 return 1;
726 static HRESULT WINAPI BindStatusCallback_OnStartBinding(IBindStatusCallback *iface, DWORD dwReserved,
727 IBinding *pib)
729 ok(0, "unexpected call\n");
730 return E_NOTIMPL;
733 static HRESULT WINAPI BindStatusCallback_GetPriority(IBindStatusCallback *iface, LONG *pnPriority)
735 ok(0, "unexpected call\n");
736 return E_NOTIMPL;
739 static HRESULT WINAPI BindStatusCallback_OnLowResource(IBindStatusCallback *iface, DWORD reserved)
741 ok(0, "unexpected call\n");
742 return E_NOTIMPL;
745 static HRESULT WINAPI BindStatusCallback_OnProgress(IBindStatusCallback *iface, ULONG ulProgress,
746 ULONG ulProgressMax, ULONG ulStatusCode, LPCWSTR szStatusText)
748 ok(0, "unexpected call\n");
749 return E_NOTIMPL;
752 static HRESULT WINAPI BindStatusCallback_OnStopBinding(IBindStatusCallback *iface, HRESULT hresult, LPCWSTR szError)
754 ok(0, "unexpected call\n");
755 return E_NOTIMPL;
758 static HRESULT WINAPI BindStatusCallback_GetBindInfo(IBindStatusCallback *iface, DWORD *grfBINDF, BINDINFO *pbindinfo)
760 ok(0, "unexpected call\n");
761 return E_NOTIMPL;
764 static HRESULT WINAPI BindStatusCallback_OnDataAvailable(IBindStatusCallback *iface, DWORD grfBSCF,
765 DWORD dwSize, FORMATETC* pformatetc, STGMEDIUM* pstgmed)
767 ok(0, "unexpected call\n");
768 return E_NOTIMPL;
771 static HRESULT WINAPI BindStatusCallback_OnObjectAvailable(IBindStatusCallback *iface, REFIID riid, IUnknown *punk)
773 ok(0, "unexpected call\n");
774 return E_NOTIMPL;
777 static IBindStatusCallbackVtbl BindStatusCallbackVtbl = {
778 BindStatusCallback_QueryInterface,
779 BindStatusCallback_AddRef,
780 BindStatusCallback_Release,
781 BindStatusCallback_OnStartBinding,
782 BindStatusCallback_GetPriority,
783 BindStatusCallback_OnLowResource,
784 BindStatusCallback_OnProgress,
785 BindStatusCallback_OnStopBinding,
786 BindStatusCallback_GetBindInfo,
787 BindStatusCallback_OnDataAvailable,
788 BindStatusCallback_OnObjectAvailable
791 static IBindStatusCallback BindStatusCallback = { &BindStatusCallbackVtbl };
793 static HRESULT WINAPI Moniker_QueryInterface(IMoniker *iface, REFIID riid, void **ppv)
795 *ppv = NULL;
797 ok(0, "unexpected riid: %s\n", debugstr_guid(riid));
798 return E_NOINTERFACE;
801 static ULONG WINAPI Moniker_AddRef(IMoniker *iface)
803 return 2;
806 static ULONG WINAPI Moniker_Release(IMoniker *iface)
808 return 1;
811 static HRESULT WINAPI Moniker_GetClassID(IMoniker *iface, CLSID *pClassID)
813 ok(0, "unexpected call\n");
814 return E_NOTIMPL;
817 static HRESULT WINAPI Moniker_IsDirty(IMoniker *iface)
819 ok(0, "unexpected call\n");
820 return E_NOTIMPL;
823 static HRESULT WINAPI Moniker_Load(IMoniker *iface, IStream *pStm)
825 ok(0, "unexpected call\n");
826 return E_NOTIMPL;
829 static HRESULT WINAPI Moniker_Save(IMoniker *iface, IStream *pStm, BOOL fClearDirty)
831 ok(0, "unexpected call\n");
832 return E_NOTIMPL;
835 static HRESULT WINAPI Moniker_GetSizeMax(IMoniker *iface, ULARGE_INTEGER *pcbSize)
837 ok(0, "unexpected call\n");
838 return E_NOTIMPL;
841 static HRESULT WINAPI Moniker_BindToObject(IMoniker *iface, IBindCtx *pcb, IMoniker *pmkToLeft,
842 REFIID riidResult, void **ppvResult)
844 ok(0, "unexpected call\n");
845 return E_NOTIMPL;
848 static HRESULT WINAPI Moniker_BindToStorage(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
849 REFIID riid, void **ppv)
851 IUnknown *unk;
852 HRESULT hres;
854 static OLECHAR BSCBHolder[] = { '_','B','S','C','B','_','H','o','l','d','e','r','_',0 };
856 CHECK_EXPECT(BindToStorage);
858 ok(pbc == _bctx, "pbc != _bctx\n");
859 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
860 ok(IsEqualGUID(&IID_IUnknown, riid), "unexpected riid %s\n", debugstr_guid(riid));
861 ok(ppv != NULL, "ppv == NULL\n");
862 ok(*ppv == NULL, "*ppv=%p\n", *ppv);
864 hres = IBindCtx_GetObjectParam(pbc, BSCBHolder, &unk);
865 ok(hres == S_OK, "GetObjectParam failed: %08x\n", hres);
866 ok(unk != NULL, "unk == NULL\n");
868 IUnknown_Release(unk);
870 return S_OK;
873 static HRESULT WINAPI Moniker_Reduce(IMoniker *iface, IBindCtx *pbc, DWORD dwReduceHowFar,
874 IMoniker **ppmkToLeft, IMoniker **ppmkReduced)
876 ok(0, "unexpected call\n");
877 return E_NOTIMPL;
880 static HRESULT WINAPI Moniker_ComposeWith(IMoniker *iface, IMoniker *pmkRight,
881 BOOL fOnlyIfNotGeneric, IMoniker **ppnkComposite)
883 ok(0, "unexpected call\n");
884 return E_NOTIMPL;
887 static HRESULT WINAPI Moniker_Enum(IMoniker *iface, BOOL fForwrd, IEnumMoniker **ppenumMoniker)
889 ok(0, "unexpected call\n");
890 return E_NOTIMPL;
893 static HRESULT WINAPI Moniker_IsEqual(IMoniker *iface, IMoniker *pmkOtherMoniker)
895 ok(0, "unexpected call\n");
896 return E_NOTIMPL;
899 static HRESULT WINAPI Moniker_Hash(IMoniker *iface, DWORD *pdwHash)
901 ok(0, "unexpected call\n");
902 return E_NOTIMPL;
905 static HRESULT WINAPI Moniker_IsRunning(IMoniker *iface, IBindCtx *pbc, IMoniker *pmkToLeft,
906 IMoniker *pmkNewlyRunning)
908 ok(0, "unexpected call\n");
909 return E_NOTIMPL;
912 static HRESULT WINAPI Moniker_GetTimeOfLastChange(IMoniker *iface, IBindCtx *pbc,
913 IMoniker *pmkToLeft, FILETIME *pFileTime)
915 ok(0, "unexpected call\n");
916 return E_NOTIMPL;
919 static HRESULT WINAPI Moniker_Inverse(IMoniker *iface, IMoniker **ppmk)
921 ok(0, "unexpected call\n");
922 return E_NOTIMPL;
925 static HRESULT WINAPI Moniker_CommonPrefixWith(IMoniker *iface, IMoniker *pmkOther,
926 IMoniker **ppmkPrefix)
928 ok(0, "unexpected call\n");
929 return E_NOTIMPL;
932 static HRESULT WINAPI Moniker_RelativePathTo(IMoniker *iface, IMoniker *pmkOther,
933 IMoniker **pmkRelPath)
935 ok(0, "unexpected call\n");
936 return E_NOTIMPL;
939 static HRESULT WINAPI Moniker_GetDisplayName(IMoniker *iface, IBindCtx *pbc,
940 IMoniker *pmkToLeft, LPOLESTR *ppszDisplayName)
942 static const WCHAR winehq_urlW[] =
943 {'h','t','t','p',':','/','/','w','w','w','.','w','i','n','e','h','q','.','o','r','g',
944 '/','s','i','t','e','/','a','b','o','u','t',0};
946 CHECK_EXPECT(GetDisplayName);
948 ok(pbc != NULL, "pbc == NULL\n");
949 ok(pbc != _bctx, "pbc == _bctx\n");
950 ok(pmkToLeft == NULL, "pmkToLeft=%p\n", pmkToLeft);
952 *ppszDisplayName = CoTaskMemAlloc(sizeof(winehq_urlW));
953 memcpy(*ppszDisplayName, winehq_urlW, sizeof(winehq_urlW));
954 return S_OK;
957 static HRESULT WINAPI Moniker_ParseDisplayName(IMoniker *iface, IBindCtx *pbc,
958 IMoniker *pmkToLeft, LPOLESTR pszDisplayName, ULONG *pchEaten, IMoniker **ppmkOut)
960 ok(0, "unexpected call\n");
961 return E_NOTIMPL;
964 static HRESULT WINAPI Moniker_IsSystemMoniker(IMoniker *iface, DWORD *pdwMksys)
966 CHECK_EXPECT2(IsSystemMoniker);
968 *pdwMksys = MKSYS_URLMONIKER;
969 return S_OK;
972 static IMonikerVtbl MonikerVtbl = {
973 Moniker_QueryInterface,
974 Moniker_AddRef,
975 Moniker_Release,
976 Moniker_GetClassID,
977 Moniker_IsDirty,
978 Moniker_Load,
979 Moniker_Save,
980 Moniker_GetSizeMax,
981 Moniker_BindToObject,
982 Moniker_BindToStorage,
983 Moniker_Reduce,
984 Moniker_ComposeWith,
985 Moniker_Enum,
986 Moniker_IsEqual,
987 Moniker_Hash,
988 Moniker_IsRunning,
989 Moniker_GetTimeOfLastChange,
990 Moniker_Inverse,
991 Moniker_CommonPrefixWith,
992 Moniker_RelativePathTo,
993 Moniker_GetDisplayName,
994 Moniker_ParseDisplayName,
995 Moniker_IsSystemMoniker
998 static IMoniker Moniker = { &MonikerVtbl };
1000 static void test_HlinkResolveMonikerForData(void)
1002 IBindCtx *bctx;
1003 HRESULT hres;
1005 CreateBindCtx(0, &bctx);
1006 _bctx = bctx;
1008 SET_EXPECT(IsSystemMoniker);
1009 SET_EXPECT(GetDisplayName);
1010 SET_EXPECT(BindToStorage);
1012 hres = HlinkResolveMonikerForData(&Moniker, 0, bctx, 0, NULL, &BindStatusCallback, NULL);
1013 ok(hres == S_OK, "HlinkResolveMonikerForData failed: %08x\n", hres);
1015 CHECK_CALLED(IsSystemMoniker);
1016 CHECK_CALLED(GetDisplayName);
1017 CHECK_CALLED(BindToStorage);
1019 IBindCtx_Release(bctx);
1022 START_TEST(hlink)
1024 CoInitialize(NULL);
1026 test_HlinkIsShortcut();
1027 test_reference();
1028 test_persist();
1029 test_special_reference();
1030 test_HlinkCreateExtensionServices();
1031 test_HlinkParseDisplayName();
1032 test_HlinkResolveMonikerForData();
1034 CoUninitialize();