iexplore: Added self-registration code.
[wine] / dlls / hlink / tests / hlink.c
1 /*
2  * Implementation of hyperlinking (hlink.dll)
3  *
4  * Copyright 2006 Mike McCormack
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20
21 #define COBJMACROS
22
23 #include <stdio.h>
24
25 #include <hlink.h>
26 #include <hlguids.h>
27
28 #include "wine/test.h"
29
30 static void test_HlinkIsShortcut(void)
31 {
32     int i;
33     HRESULT hres;
34
35     static const WCHAR file0[] = {'f','i','l','e',0};
36     static const WCHAR file1[] = {'f','i','l','e','.','u','r','l',0};
37     static const WCHAR file2[] = {'f','i','l','e','.','l','n','k',0};
38     static const WCHAR file3[] = {'f','i','l','e','.','u','R','l',0};
39     static const WCHAR file4[] = {'f','i','l','e','u','r','l',0};
40     static const WCHAR file5[] = {'c',':','\\','f','i','l','e','.','u','r','l',0};
41     static const WCHAR file6[] = {'c',':','\\','f','i','l','e','.','l','n','k',0};
42     static const WCHAR file7[] = {'.','u','r','l',0};
43
44     static struct {
45         LPCWSTR file;
46         HRESULT hres;
47     } shortcut_test[] = {
48         {file0, S_FALSE},
49         {file1, S_OK},
50         {file2, S_FALSE},
51         {file3, S_OK},
52         {file4, S_FALSE},
53         {file5, S_OK},
54         {file6, S_FALSE},
55         {file7, S_OK},
56         {NULL,  E_INVALIDARG}
57     };
58
59     for(i=0; i<sizeof(shortcut_test)/sizeof(shortcut_test[0]); i++) {
60         hres = HlinkIsShortcut(shortcut_test[i].file);
61         ok(hres == shortcut_test[i].hres, "[%d] HlinkIsShortcut returned %08x, expected %08x\n",
62            i, hres, shortcut_test[i].hres);
63     }
64 }
65
66 static void test_reference(void)
67 {
68     HRESULT r;
69     IHlink *lnk = NULL;
70     IMoniker *mk = NULL;
71     const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
72     const WCHAR url2[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g','/',0 };
73     LPWSTR str = NULL;
74
75     r = HlinkCreateFromString(url, NULL, NULL, NULL,
76                               0, NULL, &IID_IHlink, (LPVOID*) &lnk);
77     ok(r == S_OK, "failed to create link\n");
78     if (FAILED(r))
79         return;
80
81     r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
82     ok(r == S_OK, "failed\n");
83
84     r = IHlink_GetMonikerReference(lnk, HLINKGETREF_DEFAULT, &mk, &str);
85     ok(r == S_OK, "failed\n");
86     ok(mk != NULL, "no moniker\n");
87     ok(str == NULL, "string should be null\n");
88
89     r = IMoniker_Release(mk);
90     ok( r == 1, "moniker refcount wrong\n");
91
92     r = IHlink_GetStringReference(lnk, -1, &str, NULL);
93     ok(r == S_OK, "failed\n");
94
95     r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, &str, NULL);
96     ok(r == S_OK, "failed\n");
97     todo_wine {
98     ok(!lstrcmpW(str, url2), "url wrong\n");
99     }
100     CoTaskMemFree(str);
101
102     r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, NULL);
103     ok(r == S_OK, "failed\n");
104
105     r = IHlink_GetStringReference(lnk, HLINKGETREF_DEFAULT, NULL, &str);
106     ok(r == S_OK, "failed\n");
107     ok(str == NULL, "string should be null\n");
108 }
109
110 /* url only */
111 static const unsigned char expected_hlink_data[] =
112 {
113     0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
114     0xe0,0xc9,0xea,0x79,0xf9,0xba,0xce,0x11,
115     0x8c,0x82,0x00,0xaa,0x00,0x4b,0xa9,0x0b,
116     0x26,0x00,0x00,0x00,0x68,0x00,0x74,0x00,
117     0x74,0x00,0x70,0x00,0x3a,0x00,0x2f,0x00,
118     0x2f,0x00,0x77,0x00,0x69,0x00,0x6e,0x00,
119     0x65,0x00,0x68,0x00,0x71,0x00,0x2e,0x00,
120     0x6f,0x00,0x72,0x00,0x67,0x00,0x2f,0x00,
121     0x00,0x00,
122 };
123
124 /* url + friendly name */
125 static const unsigned char expected_hlink_data2[] =
126 {
127     0x02,0x00,0x00,0x00,0x17,0x00,0x00,0x00,
128     0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
129     0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
130     0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
131     0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
132     0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
133     0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
134     0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
135     0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
136     0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
137     0x67,0x00,0x2f,0x00,0x00,0x00,
138 };
139
140 /* url + friendly name + location */
141 static const unsigned char expected_hlink_data3[] =
142 {
143     0x02,0x00,0x00,0x00,0x1f,0x00,0x00,0x00,
144     0x08,0x00,0x00,0x00,0x57,0x00,0x69,0x00,
145     0x6e,0x00,0x65,0x00,0x20,0x00,0x48,0x00,
146     0x51,0x00,0x00,0x00,0xe0,0xc9,0xea,0x79,
147     0xf9,0xba,0xce,0x11,0x8c,0x82,0x00,0xaa,
148     0x00,0x4b,0xa9,0x0b,0x26,0x00,0x00,0x00,
149     0x68,0x00,0x74,0x00,0x74,0x00,0x70,0x00,
150     0x3a,0x00,0x2f,0x00,0x2f,0x00,0x77,0x00,
151     0x69,0x00,0x6e,0x00,0x65,0x00,0x68,0x00,
152     0x71,0x00,0x2e,0x00,0x6f,0x00,0x72,0x00,
153     0x67,0x00,0x2f,0x00,0x00,0x00,0x07,0x00,
154     0x00,0x00,0x5f,0x00,0x62,0x00,0x6c,0x00,
155     0x61,0x00,0x6e,0x00,0x6b,0x00,0x00,0x00,
156 };
157
158 /* relative url */
159 static const unsigned char expected_hlink_data4[] =
160 {
161     0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,
162     0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
163     0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
164     0x00,0x00,0x0b,0x00,0x00,0x00,0x69,0x6e,
165     0x64,0x65,0x78,0x2e,0x68,0x74,0x6d,0x6c,
166     0x00,0xff,0xff,0xad,0xde,0x00,0x00,0x00,
167     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
168     0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
169     0x00,0x00,0x00,0x00,0x00,
170 };
171
172 /* url + target frame name */
173 static const unsigned char expected_hlink_data5[] =
174 {
175     0x02,0x00,0x00,0x00,0x83,0x00,0x00,0x00,
176     0x07,0x00,0x00,0x00,0x74,0x00,0x67,0x00,
177     0x74,0x00,0x66,0x00,0x72,0x00,0x6d,0x00,
178     0x00,0x00,0xe0,0xc9,0xea,0x79,0xf9,0xba,
179     0xce,0x11,0x8c,0x82,0x00,0xaa,0x00,0x4b,
180     0xa9,0x0b,0x26,0x00,0x00,0x00,0x68,0x00,
181     0x74,0x00,0x74,0x00,0x70,0x00,0x3a,0x00,
182     0x2f,0x00,0x2f,0x00,0x77,0x00,0x69,0x00,
183     0x6e,0x00,0x65,0x00,0x68,0x00,0x71,0x00,
184     0x2e,0x00,0x6f,0x00,0x72,0x00,0x67,0x00,
185     0x2f,0x00,0x00,0x00,
186 };
187
188 /* filename */
189 static const unsigned char expected_hlink_data6[] =
190 {
191      0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
192      0x03,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
193      0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
194      0x00,0x00,0x04,0x00,0x00,0x00,0x63,0x3a,
195      0x5c,0x00,0xff,0xff,0xad,0xde,0x00,0x00,
196      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
197      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
198      0x00,0x00,0x0c,0x00,0x00,0x00,0x06,0x00,
199      0x00,0x00,0x03,0x00,0x63,0x00,0x3a,0x00,
200      0x5c,0x00,
201 };
202
203 static void test_persist_save_data(const char *testname, IHlink *lnk,
204                                    const unsigned char *expected_data,
205                                    unsigned int expected_data_size)
206 {
207     HRESULT hr;
208     IStream *stream;
209     IPersistStream *ps;
210     HGLOBAL hglobal;
211     DWORD data_size;
212     const unsigned char *data;
213     DWORD i;
214     BOOL same;
215
216     hr = IHlink_QueryInterface(lnk, &IID_IPersistStream, (void **)&ps);
217     ok(hr == S_OK, "IHlink_QueryInterface failed with error 0x%08x\n", hr);
218
219     hr = CreateStreamOnHGlobal(NULL, TRUE, &stream);
220     ok(hr == S_OK, "CreateStreamOnHGlobal failed with error 0x%08x\n", hr);
221
222     hr = IPersistStream_Save(ps, stream, TRUE);
223     ok(hr == S_OK, "IPersistStream_Save failed with error 0x%08x\n", hr);
224
225     hr = GetHGlobalFromStream(stream, &hglobal);
226     ok(hr == S_OK, "GetHGlobalFromStream failed with error 0x%08x\n", hr);
227
228     data_size = GlobalSize(hglobal);
229
230     data = GlobalLock(hglobal);
231
232     /* first check we have the right amount of data */
233     ok(data_size == expected_data_size,
234        "%s: Size of saved data differs (expected %d, actual %d)\n",
235        testname, expected_data_size, data_size);
236
237     same = TRUE;
238     /* then do a byte-by-byte comparison */
239     for (i = 0; i < min(data_size, expected_data_size); i++)
240     {
241         if ((expected_data[i] != data[i]) &&
242             (((expected_data != expected_hlink_data2) &&
243               (expected_data != expected_hlink_data3)) ||
244              ((i < 52 || i >= 56) && (i < 80 || i >= 84))))
245         {
246             same = FALSE;
247             break;
248         }
249     }
250
251     ok(same, "%s: Saved data differs\n", testname);
252     if (!same)
253     {
254         for (i = 0; i < data_size; i++)
255         {
256             if (i % 8 == 0) printf("    ");
257             printf("0x%02x,", data[i]);
258             if (i % 8 == 7) printf("\n");
259         }
260         printf("\n");
261     }
262
263     GlobalUnlock(hglobal);
264
265     IStream_Release(stream);
266     IPersistStream_Release(ps);
267 }
268
269 static void test_persist(void)
270 {
271     static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0 };
272     static const WCHAR rel_url[] = { 'i','n','d','e','x','.','h','t','m','l',0 };
273     static const WCHAR filename[] = { 'c',':','\\',0 };
274     static const WCHAR friendly_name[] = { 'W','i','n','e',' ','H','Q',0 };
275     static const WCHAR location[] = { '_','b','l','a','n','k',0 };
276     static const WCHAR target_frame_name[] = { 't','g','t','f','r','m',0 };
277     HRESULT hr;
278     IHlink *lnk;
279
280     hr = HlinkCreateFromString(url, NULL, NULL, NULL,
281                                0, NULL, &IID_IHlink, (LPVOID*) &lnk);
282     ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
283     test_persist_save_data("url only", lnk, expected_hlink_data, sizeof(expected_hlink_data));
284     IHlink_Release(lnk);
285
286     hr = HlinkCreateFromString(url, NULL, friendly_name, NULL,
287                                0, NULL, &IID_IHlink, (LPVOID*) &lnk);
288     ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
289     test_persist_save_data("url + friendly name", lnk, expected_hlink_data2, sizeof(expected_hlink_data2));
290     IHlink_Release(lnk);
291
292     hr = HlinkCreateFromString(url, location, friendly_name, NULL,
293                                0, NULL, &IID_IHlink, (LPVOID*) &lnk);
294     ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
295     test_persist_save_data("url + friendly_name + location", lnk, expected_hlink_data3, sizeof(expected_hlink_data3));
296     IHlink_Release(lnk);
297
298     hr = HlinkCreateFromString(rel_url, NULL, NULL, NULL,
299                                0, NULL, &IID_IHlink, (LPVOID*) &lnk);
300     ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
301     test_persist_save_data("relative url", lnk, expected_hlink_data4, sizeof(expected_hlink_data4));
302     IHlink_Release(lnk);
303
304     hr = HlinkCreateFromString(url, NULL, NULL, NULL,
305                                0, NULL, &IID_IHlink, (LPVOID*) &lnk);
306     ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
307     hr = IHlink_SetTargetFrameName(lnk, target_frame_name);
308     ok(hr == S_OK, "IHlink_SetTargetFrameName failed with error 0x%08x\n", hr);
309     test_persist_save_data("url + target frame name", lnk, expected_hlink_data5, sizeof(expected_hlink_data5));
310     IHlink_Release(lnk);
311
312     hr = HlinkCreateFromString(filename, NULL, NULL, NULL,
313                                0, NULL, &IID_IHlink, (LPVOID*) &lnk);
314     ok(hr == S_OK, "IHlinCreateFromString failed with error 0x%08x\n", hr);
315     test_persist_save_data("filename", lnk, expected_hlink_data6, sizeof(expected_hlink_data6));
316     IHlink_Release(lnk);
317 }
318
319 START_TEST(hlink)
320 {
321     CoInitialize(NULL);
322
323     test_HlinkIsShortcut();
324     test_reference();
325     test_persist();
326
327     CoUninitialize();
328 }