Add tests for functionality implemented or corrected: multiplication,
[wine] / dlls / urlmon / internet.c
1 /*
2  * Copyright 2005 Jacek Caban
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19 #include <stdarg.h>
20
21 #define COBJMACROS
22
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winuser.h"
26 #include "winreg.h"
27 #include "shlwapi.h"
28 #include "ole2.h"
29 #include "urlmon.h"
30 #include "urlmon_main.h"
31
32 #include "wine/debug.h"
33 #include "wine/unicode.h"
34
35 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
36
37 static HRESULT parse_schema(LPCWSTR url, DWORD flags, LPWSTR result, DWORD size, DWORD *rsize)
38 {
39     WCHAR *ptr;
40     DWORD len = 0;
41
42     TRACE("(%s %08lx %p %ld %p)\n", debugstr_w(url), flags, result, size, rsize);
43
44     if(flags)
45         ERR("wrong flags\n");
46     
47     ptr = strchrW(url, ':');
48     if(ptr)
49         len = ptr-url;
50
51     if(len >= size)
52         return E_POINTER;
53
54     if(len)
55         memcpy(result, url, len*sizeof(WCHAR));
56     result[len] = 0;
57
58     if(rsize)
59         *rsize = len;
60
61     return S_OK;
62 }
63
64 static IInternetProtocolInfo *get_protocol_info(LPCWSTR url)
65 {
66     IInternetProtocolInfo *ret = NULL;
67     WCHAR schema[64], str_clsid[64];
68     HKEY hkey = NULL;
69     DWORD res, type, size, schema_len;
70     CLSID clsid;
71     LPWSTR wszKey;
72     HRESULT hres;
73
74     static const WCHAR wszProtocolsKey[] =
75         {'P','R','O','T','O','C','O','L','S','\\','H','a','n','d','l','e','r','\\'};
76     static const WCHAR wszCLSID[] = {'C','L','S','I','D',0};
77
78     hres = parse_schema(url, 0, schema, sizeof(schema)/sizeof(schema[0]), &schema_len);
79     if(FAILED(hres) || !schema_len)
80         return NULL;
81
82     wszKey = HeapAlloc(GetProcessHeap(), 0, sizeof(wszProtocolsKey)+(schema_len+1)*sizeof(WCHAR));
83     memcpy(wszKey, wszProtocolsKey, sizeof(wszProtocolsKey));
84     memcpy(wszKey + sizeof(wszProtocolsKey)/sizeof(WCHAR), schema, (schema_len+1)*sizeof(WCHAR));
85
86     res = RegOpenKeyW(HKEY_CLASSES_ROOT, wszKey, &hkey);
87     HeapFree(GetProcessHeap(), 0, wszKey);
88     if(res != ERROR_SUCCESS) {
89         TRACE("Could not open key %s\n", debugstr_w(wszKey));
90         return NULL;
91     }
92     
93     size = sizeof(str_clsid);
94     res = RegQueryValueExW(hkey, wszCLSID, NULL, &type, (LPBYTE)str_clsid, &size);
95     RegCloseKey(hkey);
96     if(res != ERROR_SUCCESS || type != REG_SZ) {
97         WARN("Could not get protocol CLSID res=%ld\n", res);
98         return NULL;
99     }
100
101     hres = CLSIDFromString(str_clsid, &clsid);
102     if(FAILED(hres)) {
103         WARN("CLSIDFromString failed: %08lx\n", hres);
104         return NULL;
105     }
106
107     CoGetClassObject(&clsid, CLSCTX_INPROC_SERVER, NULL, &IID_IInternetProtocolInfo, (void**)&ret);
108     return ret;
109 }
110
111 static HRESULT parse_security_url(LPCWSTR url, DWORD flags, LPWSTR result, DWORD size, DWORD *rsize)
112 {
113     IInternetProtocolInfo *protocol_info;
114     HRESULT hres;
115
116     TRACE("(%s %08lx %p %ld %p)\n", debugstr_w(url), flags, result, size, rsize);
117
118     protocol_info = get_protocol_info(url);
119
120     if(protocol_info) {
121         hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_URL,
122                 flags, result, size, rsize, 0);
123         return hres;
124     }
125
126     return E_FAIL;
127 }
128
129 static HRESULT parse_encode(LPCWSTR url, DWORD flags, LPWSTR result, DWORD size, DWORD *rsize)
130 {
131     IInternetProtocolInfo *protocol_info;
132     DWORD prsize;
133     HRESULT hres;
134
135     TRACE("(%s %08lx %p %ld %p)\n", debugstr_w(url), flags, result, size, rsize);
136
137     protocol_info = get_protocol_info(url);
138
139     if(protocol_info) {
140         hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_ENCODE,
141                 flags, result, size, rsize, 0);
142         if(SUCCEEDED(hres))
143             return hres;
144     }
145
146     prsize = size;
147     hres = UrlUnescapeW((LPWSTR)url, result, &prsize, flags);
148
149     if(rsize)
150         *rsize = prsize;
151
152     return hres;
153 }
154
155 static HRESULT parse_path_from_url(LPCWSTR url, DWORD flags, LPWSTR result, DWORD size, DWORD *rsize)
156 {
157     IInternetProtocolInfo *protocol_info;
158     DWORD prsize;
159     HRESULT hres;
160
161     TRACE("(%s %08lx %p %ld %p)\n", debugstr_w(url), flags, result, size, rsize);
162
163     protocol_info = get_protocol_info(url);
164
165     if(protocol_info) {
166         hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_PATH_FROM_URL,
167                 flags, result, size, rsize, 0);
168         if(SUCCEEDED(hres))
169             return hres;
170     }
171
172     prsize = size;
173     hres = PathCreateFromUrlW(url, result, &prsize, 0);
174
175     if(rsize)
176         *rsize = prsize;
177     return hres;
178 }
179
180 static HRESULT parse_security_domain(LPCWSTR url, DWORD flags, LPWSTR result,
181         DWORD size, DWORD *rsize)
182 {
183     IInternetProtocolInfo *protocol_info;
184     HRESULT hres;
185
186     TRACE("(%s %08lx %p %ld %p)\n", debugstr_w(url), flags, result, size, rsize);
187
188     protocol_info = get_protocol_info(url);
189
190     if(protocol_info) {
191         hres = IInternetProtocolInfo_ParseUrl(protocol_info, url, PARSE_SECURITY_DOMAIN,
192                 flags, result, size, rsize, 0);
193         if(SUCCEEDED(hres))
194             return hres;
195     }
196
197     return E_FAIL;
198 }
199
200
201 HRESULT WINAPI CoInternetParseUrl(LPCWSTR pwzUrl, PARSEACTION ParseAction, DWORD dwFlags,
202         LPWSTR pszResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
203 {
204     if(dwReserved)
205         WARN("dwReserved = %ld\n", dwReserved);
206
207     switch(ParseAction) {
208     case PARSE_SECURITY_URL:
209         return parse_security_url(pwzUrl, dwFlags, pszResult, cchResult, pcchResult);
210     case PARSE_ENCODE:
211         return parse_encode(pwzUrl, dwFlags, pszResult, cchResult, pcchResult);
212     case PARSE_PATH_FROM_URL:
213         return parse_path_from_url(pwzUrl, dwFlags, pszResult, cchResult, pcchResult);
214     case PARSE_SCHEMA:
215         return parse_schema(pwzUrl, dwFlags, pszResult, cchResult, pcchResult);
216     case PARSE_SECURITY_DOMAIN:
217         return parse_security_domain(pwzUrl, dwFlags, pszResult, cchResult, pcchResult);
218     default:
219         FIXME("not supported action %d\n", ParseAction);
220     }
221
222     return E_NOTIMPL;
223 }