2 * Implementation of hyperlinking (hlink.dll)
4 * Copyright 2006 Mike McCormack
5 * Copyright 2007 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
29 #include "wine/test.h"
31 static void test_HlinkIsShortcut(void)
36 static const WCHAR file0
[] = {'f','i','l','e',0};
37 static const WCHAR file1
[] = {'f','i','l','e','.','u','r','l',0};
38 static const WCHAR file2
[] = {'f','i','l','e','.','l','n','k',0};
39 static const WCHAR file3
[] = {'f','i','l','e','.','u','R','l',0};
40 static const WCHAR file4
[] = {'f','i','l','e','u','r','l',0};
41 static const WCHAR file5
[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
42 static const WCHAR file6
[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
43 static const WCHAR file7
[] = {'.','u','r','l',0};
60 for(i
=0; i
<sizeof(shortcut_test
)/sizeof(shortcut_test
[0]); i
++) {
61 hres
= HlinkIsShortcut(shortcut_test
[i
].file
);
62 ok(hres
== shortcut_test
[i
].hres
, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
63 i
, hres
, shortcut_test
[i
].hres
);
67 static void test_reference(void)
72 const WCHAR url
[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
73 const WCHAR url2
[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
76 r
= HlinkCreateFromString(url
, NULL
, NULL
, NULL
,
77 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
78 ok(r
== S_OK
, "failed to create link\n");
82 r
= IHlink_GetMonikerReference(lnk
, HLINKGETREF_DEFAULT
, NULL
, NULL
);
83 ok(r
== S_OK
, "failed\n");
85 r
= IHlink_GetMonikerReference(lnk
, HLINKGETREF_DEFAULT
, &mk
, &str
);
86 ok(r
== S_OK
, "failed\n");
87 ok(mk
!= NULL
, "no moniker\n");
88 ok(str
== NULL
, "string should be null\n");
90 r
= IMoniker_Release(mk
);
91 ok( r
== 1, "moniker refcount wrong\n");
93 r
= IHlink_GetStringReference(lnk
, -1, &str
, NULL
);
94 ok(r
== S_OK
, "failed\n");
96 r
= IHlink_GetStringReference(lnk
, HLINKGETREF_DEFAULT
, &str
, NULL
);
97 ok(r
== S_OK
, "failed\n");
99 ok(!lstrcmpW(str
, url2
), "url wrong\n");
103 r
= IHlink_GetStringReference(lnk
, HLINKGETREF_DEFAULT
, NULL
, NULL
);
104 ok(r
== S_OK
, "failed\n");
106 r
= IHlink_GetStringReference(lnk
, HLINKGETREF_DEFAULT
, NULL
, &str
);
107 ok(r
== S_OK
, "failed\n");
108 ok(str
== NULL
, "string should be null\n");
112 static const unsigned char expected_hlink_data
[] =
114 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
115 0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
116 0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
117 0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
118 0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
119 0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
120 0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
121 0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
125 /* url + friendly name */
126 static const unsigned char expected_hlink_data2
[] =
128 0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
129 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
130 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
131 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
132 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
133 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
134 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
135 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
136 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
137 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
138 0x67,0x00,0x2f,0x00,0x00,0x00,
141 /* url + friendly name + location */
142 static const unsigned char expected_hlink_data3
[] =
144 0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
145 0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
146 0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
147 0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
148 0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
149 0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
150 0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
151 0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
152 0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
153 0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
154 0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
155 0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
156 0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
160 static const unsigned char expected_hlink_data4
[] =
162 0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
163 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
164 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
165 0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
166 0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
167 0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
168 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
169 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
170 0x00,0x00,0x00,0x00,0x00,
173 /* url + target frame name */
174 static const unsigned char expected_hlink_data5
[] =
176 0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
177 0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
178 0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
179 0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
180 0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
181 0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
182 0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
183 0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
184 0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
185 0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
190 static const unsigned char expected_hlink_data6
[] =
192 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
193 0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
194 0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
195 0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
196 0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
197 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
198 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
199 0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
200 0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
204 static void test_persist_save_data(const char *testname
, IHlink
*lnk
,
205 const unsigned char *expected_data
,
206 unsigned int expected_data_size
)
213 const unsigned char *data
;
217 hr
= IHlink_QueryInterface(lnk
, &IID_IPersistStream
, (void **)&ps
);
218 ok(hr
== S_OK
, "IHlink_QueryInterface failed with error 0x%08x\n", hr
);
220 hr
= CreateStreamOnHGlobal(NULL
, TRUE
, &stream
);
221 ok(hr
== S_OK
, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr
);
223 hr
= IPersistStream_Save(ps
, stream
, TRUE
);
224 ok(hr
== S_OK
, "IPersistStream_Save failed with error 0x%08x\n", hr
);
226 hr
= GetHGlobalFromStream(stream
, &hglobal
);
227 ok(hr
== S_OK
, "GetHGlobalFromStream failed with error 0x%08x\n", hr
);
229 data_size
= GlobalSize(hglobal
);
231 data
= GlobalLock(hglobal
);
233 /* first check we have the right amount of data */
234 ok(data_size
== expected_data_size
,
235 "%s: Size of saved data differs (expected %d, actual %d)\n",
236 testname
, expected_data_size
, data_size
);
239 /* then do a byte-by-byte comparison */
240 for (i
= 0; i
< min(data_size
, expected_data_size
); i
++)
242 if ((expected_data
[i
] != data
[i
]) &&
243 (((expected_data
!= expected_hlink_data2
) &&
244 (expected_data
!= expected_hlink_data3
)) ||
245 ((i
< 52 || i
>= 56) && (i
< 80 || i
>= 84))))
252 ok(same
, "%s: Saved data differs\n", testname
);
255 for (i
= 0; i
< data_size
; i
++)
257 if (i
% 8 == 0) printf(" ");
258 printf("0x%02x,", data
[i
]);
259 if (i
% 8 == 7) printf("\n");
264 GlobalUnlock(hglobal
);
266 IStream_Release(stream
);
267 IPersistStream_Release(ps
);
270 static void test_persist(void)
272 static const WCHAR url
[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
273 static const WCHAR rel_url
[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
274 static const WCHAR filename
[] = { 'c',':','\\',0 };
275 static const WCHAR friendly_name
[] = { 'W','i','n','e',' ','H','Q',0 };
276 static const WCHAR location
[] = { '_','b','l','a','n','k',0 };
277 static const WCHAR target_frame_name
[] = { 't','g','t','f','r','m',0 };
281 hr
= HlinkCreateFromString(url
, NULL
, NULL
, NULL
,
282 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
283 ok(hr
== S_OK
, "IHlinCreateFromString failed with error 0x%08x\n", hr
);
284 test_persist_save_data("url only", lnk
, expected_hlink_data
, sizeof(expected_hlink_data
));
287 hr
= HlinkCreateFromString(url
, NULL
, friendly_name
, NULL
,
288 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
289 ok(hr
== S_OK
, "IHlinCreateFromString failed with error 0x%08x\n", hr
);
290 test_persist_save_data("url + friendly name", lnk
, expected_hlink_data2
, sizeof(expected_hlink_data2
));
293 hr
= HlinkCreateFromString(url
, location
, friendly_name
, NULL
,
294 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
295 ok(hr
== S_OK
, "IHlinCreateFromString failed with error 0x%08x\n", hr
);
296 test_persist_save_data("url + friendly_name + location", lnk
, expected_hlink_data3
, sizeof(expected_hlink_data3
));
299 hr
= HlinkCreateFromString(rel_url
, NULL
, NULL
, NULL
,
300 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
301 ok(hr
== S_OK
, "IHlinCreateFromString failed with error 0x%08x\n", hr
);
302 test_persist_save_data("relative url", lnk
, expected_hlink_data4
, sizeof(expected_hlink_data4
));
305 hr
= HlinkCreateFromString(url
, NULL
, NULL
, NULL
,
306 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
307 ok(hr
== S_OK
, "IHlinCreateFromString failed with error 0x%08x\n", hr
);
308 hr
= IHlink_SetTargetFrameName(lnk
, target_frame_name
);
309 ok(hr
== S_OK
, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr
);
310 test_persist_save_data("url + target frame name", lnk
, expected_hlink_data5
, sizeof(expected_hlink_data5
));
313 hr
= HlinkCreateFromString(filename
, NULL
, NULL
, NULL
,
314 0, NULL
, &IID_IHlink
, (LPVOID
*) &lnk
);
315 ok(hr
== S_OK
, "IHlinCreateFromString failed with error 0x%08x\n", hr
);
316 test_persist_save_data("filename", lnk
, expected_hlink_data6
, sizeof(expected_hlink_data6
));
320 static void test_special_reference(void)
325 hres
= HlinkGetSpecialReference(HLSR_HOME
, &ref
);
326 ok(hres
== S_OK
, "HlinkGetSpecialReference(HLSR_HOME) failed: %08x\n", hres
);
327 ok(ref
!= NULL
, "ref == NULL\n");
330 hres
= HlinkGetSpecialReference(HLSR_SEARCHPAGE
, &ref
);
331 ok(hres
== S_OK
, "HlinkGetSpecialReference(HLSR_SEARCHPAGE) failed: %08x\n", hres
);
332 ok(ref
!= NULL
, "ref == NULL\n");
335 ref
= (void*)0xdeadbeef;
336 hres
= HlinkGetSpecialReference(HLSR_HISTORYFOLDER
, &ref
);
337 ok(hres
== E_NOTIMPL
, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres
);
338 ok(ref
== NULL
, "ref=%p\n", ref
);
340 ref
= (void*)0xdeadbeef;
341 hres
= HlinkGetSpecialReference(4, &ref
);
342 ok(hres
== E_INVALIDARG
, "HlinkGetSpecialReference(HLSR_HISTORYFOLDER) failed: %08x\n", hres
);
343 ok(ref
== NULL
, "ref=%p\n", ref
);
346 static void test_HlinkCreateExtensionServices(void)
348 IAuthenticate
*authenticate
;
349 LPWSTR password
, username
;
353 static const WCHAR usernameW
[] = {'u','s','e','r',0};
354 static const WCHAR passwordW
[] = {'p','a','s','s',0};
356 hres
= HlinkCreateExtensionServices(NULL
, NULL
, NULL
, NULL
,
357 NULL
, &IID_IAuthenticate
, (void**)&authenticate
);
358 ok(hres
== S_OK
, "HlinkCreateExtensionServices failed: %08x\n", hres
);
359 ok(authenticate
!= NULL
, "HlinkCreateExtensionServices returned NULL\n");
361 password
= username
= (void*)0xdeadbeef;
362 hwnd
= (void*)0xdeadbeef;
363 hres
= IAuthenticate_Authenticate(authenticate
, &hwnd
, &username
, &password
);
364 ok(hres
== S_OK
, "Authenticate failed: %08x\n", hres
);
365 ok(!hwnd
, "hwnd != NULL\n");
366 ok(!username
, "username != NULL\n");
367 ok(!password
, "password != NULL\n");
369 IAuthenticate_Release(authenticate
);
372 hres
= HlinkCreateExtensionServices(NULL
, (HWND
)0xfefefefe, usernameW
, passwordW
,
373 NULL
, &IID_IAuthenticate
, (void**)&authenticate
);
374 ok(hres
== S_OK
, "HlinkCreateExtensionServices failed: %08x\n", hres
);
375 ok(authenticate
!= NULL
, "HlinkCreateExtensionServices returned NULL\n");
377 password
= username
= NULL
;
379 hres
= IAuthenticate_Authenticate(authenticate
, &hwnd
, &username
, &password
);
380 ok(hres
== S_OK
, "Authenticate failed: %08x\n", hres
);
381 ok(hwnd
== (HWND
)0xfefefefe, "hwnd=%p\n", hwnd
);
382 ok(!lstrcmpW(username
, usernameW
), "unexpected username\n");
383 ok(!lstrcmpW(password
, passwordW
), "unexpected password\n");
384 CoTaskMemFree(username
);
385 CoTaskMemFree(password
);
387 password
= username
= (void*)0xdeadbeef;
388 hwnd
= (void*)0xdeadbeef;
389 hres
= IAuthenticate_Authenticate(authenticate
, &hwnd
, NULL
, &password
);
390 ok(hres
== E_INVALIDARG
, "Authenticate failed: %08x\n", hres
);
391 ok(password
== (void*)0xdeadbeef, "password = %p\n", password
);
392 ok(hwnd
== (void*)0xdeadbeef, "hwnd = %p\n", hwnd
);
394 IAuthenticate_Release(authenticate
);
401 test_HlinkIsShortcut();
404 test_special_reference();
405 test_HlinkCreateExtensionServices();