Remove redundant check.
[wine] / dlls / urlmon / urlmon_main.c
1 /*
2  * UrlMon
3  *
4  * Copyright (c) 2000 Patrik Stridvall
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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <stdarg.h>
22
23 #define COBJMACROS
24
25 #include "windef.h"
26 #include "winbase.h"
27 #include "winerror.h"
28 #include "wtypes.h"
29 #define NO_SHLWAPI_REG
30 #include "shlwapi.h"
31
32 #include "wine/debug.h"
33
34 #include "winuser.h"
35 #include "urlmon.h"
36 #include "urlmon_main.h"
37
38 WINE_DEFAULT_DEBUG_CHANNEL(urlmon);
39
40 LONG URLMON_refCount = 0;
41
42 HINSTANCE URLMON_hInstance = 0;
43
44 /***********************************************************************
45  *              DllMain (URLMON.init)
46  */
47 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID fImpLoad)
48 {
49     TRACE("%p 0x%lx %p\n", hinstDLL, fdwReason, fImpLoad);
50
51     switch(fdwReason) {
52     case DLL_PROCESS_ATTACH:
53         DisableThreadLibraryCalls(hinstDLL);
54         URLMON_hInstance = hinstDLL;
55         break;
56
57     case DLL_PROCESS_DETACH:
58         URLMON_hInstance = 0;
59         break;
60     }
61     return TRUE;
62 }
63
64
65 /***********************************************************************
66  *              DllInstall (URLMON.@)
67  */
68 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
69 {
70   FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
71         debugstr_w(cmdline));
72
73   return S_OK;
74 }
75
76 /***********************************************************************
77  *              DllCanUnloadNow (URLMON.@)
78  */
79 HRESULT WINAPI DllCanUnloadNow(void)
80 {
81     return URLMON_refCount != 0 ? S_FALSE : S_OK;
82 }
83
84
85
86 /******************************************************************************
87  * Urlmon ClassFactory
88  */
89 typedef struct {
90     IClassFactory ITF_IClassFactory;
91
92     LONG ref;
93     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
94 } IClassFactoryImpl;
95
96 struct object_creation_info
97 {
98     const CLSID *clsid;
99     HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, LPVOID *ppObj);
100 };
101  
102 static const struct object_creation_info object_creation[] =
103 {
104     { &CLSID_FileProtocol, FileProtocol_Construct },
105     { &CLSID_InternetSecurityManager, &SecManagerImpl_Construct },
106     { &CLSID_InternetZoneManager, ZoneMgrImpl_Construct }
107 };
108
109 static HRESULT WINAPI
110 CF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj)
111 {
112     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
113
114     if (IsEqualGUID(riid, &IID_IUnknown)
115         || IsEqualGUID(riid, &IID_IClassFactory))
116     {
117         IClassFactory_AddRef(iface);
118         *ppobj = This;
119         return S_OK;
120     }
121
122     WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
123     return E_NOINTERFACE;
124 }
125
126 static ULONG WINAPI CF_AddRef(LPCLASSFACTORY iface)
127 {
128     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
129     return InterlockedIncrement(&This->ref);
130 }
131
132 static ULONG WINAPI CF_Release(LPCLASSFACTORY iface)
133 {
134     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
135
136     ULONG ref = InterlockedDecrement(&This->ref);
137
138     if (ref == 0) {
139         HeapFree(GetProcessHeap(), 0, This);
140         URLMON_UnlockModule();
141     }
142
143     return ref;
144 }
145
146
147 static HRESULT WINAPI CF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter,
148                                         REFIID riid, LPVOID *ppobj)
149 {
150     IClassFactoryImpl *This = (IClassFactoryImpl *)iface;
151     HRESULT hres;
152     LPUNKNOWN punk;
153     
154     TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
155
156     *ppobj = NULL;
157     if(SUCCEEDED(hres = This->pfnCreateInstance(pOuter, (LPVOID *) &punk))) {
158         hres = IUnknown_QueryInterface(punk, riid, ppobj);
159         IUnknown_Release(punk);
160     }
161     return hres;
162 }
163
164 static HRESULT WINAPI CF_LockServer(LPCLASSFACTORY iface,BOOL dolock)
165 {
166     TRACE("(%d)\n", dolock);
167
168     if (dolock)
169            URLMON_LockModule();
170     else
171            URLMON_UnlockModule();
172
173     return S_OK;
174 }
175
176 static const IClassFactoryVtbl CF_Vtbl =
177 {
178     CF_QueryInterface,
179     CF_AddRef,
180     CF_Release,
181     CF_CreateInstance,
182     CF_LockServer
183 };
184
185 /*******************************************************************************
186  * DllGetClassObject [URLMON.@]
187  * Retrieves class object from a DLL object
188  *
189  * NOTES
190  *    Docs say returns STDAPI
191  *
192  * PARAMS
193  *    rclsid [I] CLSID for the class object
194  *    riid   [I] Reference to identifier of interface for class object
195  *    ppv    [O] Address of variable to receive interface pointer for riid
196  *
197  * RETURNS
198  *    Success: S_OK
199  *    Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
200  *             E_UNEXPECTED
201  */
202
203 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv)
204 {
205     int i;
206     IClassFactoryImpl *factory;
207     
208     TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
209     
210     if ( !IsEqualGUID( &IID_IClassFactory, riid )
211          && ! IsEqualGUID( &IID_IUnknown, riid) )
212         return E_NOINTERFACE;
213
214     for (i=0; i < sizeof(object_creation)/sizeof(object_creation[0]); i++)
215     {
216         if (IsEqualGUID(object_creation[i].clsid, rclsid))
217             break;
218     }
219
220     if (i == sizeof(object_creation)/sizeof(object_creation[0]))
221     {
222         FIXME("%s: no class found.\n", debugstr_guid(rclsid));
223         return CLASS_E_CLASSNOTAVAILABLE;
224     }
225
226     factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
227     if (factory == NULL) return E_OUTOFMEMORY;
228
229     factory->ITF_IClassFactory.lpVtbl = &CF_Vtbl;
230     factory->ref = 1;
231     factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
232
233     *ppv = &(factory->ITF_IClassFactory);
234
235     URLMON_LockModule();
236
237     return S_OK;
238 }
239
240
241 /***********************************************************************
242  *              DllRegisterServerEx (URLMON.@)
243  */
244 HRESULT WINAPI DllRegisterServerEx(void)
245 {
246     FIXME("(void): stub\n");
247
248     return E_FAIL;
249 }
250
251 /**************************************************************************
252  *                 UrlMkSetSessionOption (URLMON.@)
253  */
254 HRESULT WINAPI UrlMkSetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
255                                         DWORD Reserved)
256 {
257     FIXME("(%#lx, %p, %#lx): stub\n", dwOption, pBuffer, dwBufferLength);
258
259     return S_OK;
260 }
261
262 /**************************************************************************
263  *                 UrlMkGetSessionOption (URLMON.@)
264  */
265 HRESULT WINAPI UrlMkGetSessionOption(DWORD dwOption, LPVOID pBuffer, DWORD dwBufferLength,
266                                         DWORD* pdwBufferLength, DWORD dwReserved)
267 {
268     FIXME("(%#lx, %p, %#lx, %p): stub\n", dwOption, pBuffer, dwBufferLength, pdwBufferLength);
269
270     return S_OK;
271 }
272
273 static const CHAR Agent[] = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)";
274
275 /**************************************************************************
276  *                 ObtainUserAgentString (URLMON.@)
277  */
278 HRESULT WINAPI ObtainUserAgentString(DWORD dwOption, LPSTR pcszUAOut, DWORD *cbSize)
279 {
280     FIXME("(%ld, %p, %p): stub\n", dwOption, pcszUAOut, cbSize);
281
282     if(dwOption) {
283       ERR("dwOption: %ld, must be zero\n", dwOption);
284     }
285
286     if (sizeof(Agent) < *cbSize)
287         *cbSize = sizeof(Agent);
288     lstrcpynA(pcszUAOut, Agent, *cbSize); 
289
290     return S_OK;
291 }
292
293 HRESULT WINAPI CoInternetCombineUrl(LPCWSTR pwzBaseUrl, LPCWSTR pwzRelativeUrl, DWORD dwCombineFlags,
294                                     LPWSTR pwzResult, DWORD cchResult, DWORD *pcchResult, DWORD dwReserved)
295 {
296     HRESULT hres;
297     DWORD size = cchResult;
298     
299     TRACE("(%s,%s,0x%08lx,%p,%ld,%p,%ld)\n", debugstr_w(pwzBaseUrl), debugstr_w(pwzRelativeUrl), dwCombineFlags,
300           pwzResult, cchResult, pcchResult, dwReserved);
301     hres = UrlCombineW(pwzBaseUrl, pwzRelativeUrl, pwzResult, &size, dwCombineFlags);
302     if(pcchResult) *pcchResult = size;
303     return hres;
304 }
305
306 HRESULT WINAPI CoInternetCompareUrl(LPCWSTR pwzUrl1, LPCWSTR pwzUrl2, DWORD dwCompareFlags)
307 {
308     TRACE("(%s,%s,%08lx)\n", debugstr_w(pwzUrl1), debugstr_w(pwzUrl2), dwCompareFlags);
309     return UrlCompareW(pwzUrl1, pwzUrl2, dwCompareFlags)==0?S_OK:S_FALSE;
310 }
311
312 /**************************************************************************
313  *                 IsValidURL (URLMON.@)
314  * 
315  * Determines if a specified string is a valid URL.
316  *
317  * PARAMS
318  *  pBC        [I] ignored, must be NULL.
319  *  szURL      [I] string that represents the URL in question.
320  *  dwReserved [I] reserved and must be zero.
321  *
322  * RETURNS
323  *  Success: S_OK.
324  *  Failure: S_FALSE.
325  *  returns E_INVALIDARG if one or more of the args is invalid.
326  *
327  * TODO:
328  *  test functionality against windows to see what a valid URL is.
329  */
330 HRESULT WINAPI IsValidURL(LPBC pBC, LPCWSTR szURL, DWORD dwReserved)
331 {
332     FIXME("(%p, %s, %ld): stub\n", pBC, debugstr_w(szURL), dwReserved);
333     
334     if (pBC != NULL || dwReserved != 0)
335         return E_INVALIDARG;
336     
337     return S_OK;
338 }
339
340 /**************************************************************************
341  *                 FaultInIEFeature (URLMON.@)
342  *
343  *  Undocumented.  Appears to be used by native shdocvw.dll.
344  */
345 HRESULT WINAPI FaultInIEFeature( HWND hwnd, uCLSSPEC * pClassSpec,
346                                  QUERYCONTEXT *pQuery, DWORD flags )
347 {
348     FIXME("%p %p %p %08lx\n", hwnd, pClassSpec, pQuery, flags);
349     return E_NOTIMPL;
350 }
351
352 /**************************************************************************
353  *                 CoGetClassObjectFromURL (URLMON.@)
354  */
355 HRESULT WINAPI CoGetClassObjectFromURL( REFCLSID rclsid, LPCWSTR szCodeURL, DWORD dwFileVersionMS,
356                                         DWORD dwFileVersionLS, LPCWSTR szContentType,
357                                         LPBINDCTX pBindCtx, DWORD dwClsContext, LPVOID pvReserved,
358                                         REFIID riid, LPVOID *ppv )
359 {
360     FIXME("(%s %s %ld %ld %s %p %ld %p %s %p) Stub!\n", debugstr_guid(rclsid), debugstr_w(szCodeURL),
361         dwFileVersionMS, dwFileVersionLS, debugstr_w(szContentType), pBindCtx, dwClsContext, pvReserved,
362         debugstr_guid(riid), ppv);
363     return E_NOINTERFACE;
364 }
365
366 /***********************************************************************
367  *           ReleaseBindInfo (URLMON.@)
368  *
369  * Release the resources used by the specified BINDINFO structure.
370  *
371  * PARAMS
372  *  pbindinfo [I] BINDINFO to release.
373  *
374  * RETURNS
375  *  Nothing.
376  */
377 void WINAPI ReleaseBindInfo(BINDINFO* pbindinfo)
378 {
379     TRACE("(%p)\n", pbindinfo);
380
381     if(!pbindinfo)
382         return;
383
384     CoTaskMemFree(pbindinfo->szExtraInfo);
385
386     if(pbindinfo->pUnk)
387         IUnknown_Release(pbindinfo->pUnk);
388 }