wined3d: Fix WINED3DRS_DEPTHBIAS handling.
[wine] / dlls / hlink / hlink_main.c
1 /*
2  * Implementation of hyperlinking (hlink.dll)
3  *
4  * Copyright 2005 Aric Stewart for CodeWeavers
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 #include "hlink_private.h"
22
23 #include "winreg.h"
24 #include "hlguids.h"
25
26 #include "wine/debug.h"
27
28 WINE_DEFAULT_DEBUG_CHANNEL(hlink);
29
30 typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown*, REFIID, LPVOID*);
31
32 typedef struct
33 {
34     const IClassFactoryVtbl *lpVtbl;
35     LPFNCREATEINSTANCE      lpfnCI;
36 } CFImpl;
37
38 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
39 {
40     TRACE("%p %d %p\n", hinstDLL, fdwReason, lpvReserved);
41
42     switch (fdwReason)
43     {
44     case DLL_PROCESS_ATTACH:
45         DisableThreadLibraryCalls(hinstDLL);
46         break;
47     case DLL_PROCESS_DETACH:
48         break;
49     }
50     return TRUE;
51 }
52
53 /***********************************************************************
54  *             DllCanUnloadNow (HLINK.@)
55  */
56 HRESULT WINAPI DllCanUnloadNow( void )
57 {
58     FIXME("\n");
59     return S_OK;
60 }
61
62 /***********************************************************************
63  *             HlinkCreateFromMoniker (HLINK.@)
64  */
65 HRESULT WINAPI HlinkCreateFromMoniker( IMoniker *pimkTrgt, LPCWSTR pwzLocation,
66         LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData,
67         IUnknown* piunkOuter, REFIID riid, void** ppvObj)
68 {
69     IHlink *hl = NULL;
70     HRESULT r = S_OK;
71
72     TRACE("%p %s %s %p %i %p %s %p\n", pimkTrgt, debugstr_w(pwzLocation),
73             debugstr_w(pwzFriendlyName), pihlsite, dwSiteData, piunkOuter,
74             debugstr_guid(riid), ppvObj);
75
76     r = CoCreateInstance(&CLSID_StdHlink, piunkOuter, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&hl);
77     if (FAILED(r))
78         return r;
79
80     IHlink_SetMonikerReference(hl, HLINKSETF_LOCATION | HLINKSETF_TARGET, pimkTrgt, pwzLocation);
81
82     if (pwzFriendlyName)
83         IHlink_SetFriendlyName(hl, pwzFriendlyName);
84     if (pihlsite)
85         IHlink_SetHlinkSite(hl, pihlsite, dwSiteData);
86
87     *ppvObj = hl;
88
89     TRACE("Returning %i\n",r);
90
91     return r;
92 }
93
94 /***********************************************************************
95  *             HlinkCreateFromString (HLINK.@)
96  */
97 HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation,
98         LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData,
99         IUnknown* piunkOuter, REFIID riid, void** ppvObj)
100 {
101     IHlink *hl = NULL;
102     HRESULT r = S_OK;
103
104     TRACE("%s %s %s %p %i %p %s %p\n", debugstr_w(pwzTarget),
105             debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), pihlsite,
106             dwSiteData, piunkOuter, debugstr_guid(riid), ppvObj);
107
108     r = CoCreateInstance(&CLSID_StdHlink, piunkOuter, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&hl);
109     if (FAILED(r))
110         return r;
111
112     IHlink_SetStringReference(hl, HLINKSETF_TARGET | HLINKSETF_LOCATION,
113             pwzTarget, pwzLocation);
114
115     if (pwzFriendlyName)
116         IHlink_SetFriendlyName(hl, pwzFriendlyName);
117
118     if (pihlsite)
119         IHlink_SetHlinkSite(hl, pihlsite, dwSiteData);
120
121     TRACE("Returning %i\n",r);
122     *ppvObj = hl;
123
124     return r;
125 }
126
127
128 /***********************************************************************
129  *             HlinkNavigate (HLINK.@)
130  */
131 HRESULT WINAPI HlinkCreateBrowseContext( IUnknown* piunkOuter, REFIID riid, void** ppvObj)
132 {
133     HRESULT r = S_OK;
134
135     TRACE("%p %s %p\n", piunkOuter, debugstr_guid(riid), ppvObj);
136
137     r = CoCreateInstance(&CLSID_StdHlinkBrowseContext, piunkOuter, CLSCTX_INPROC_SERVER, riid, ppvObj);
138
139     TRACE("returning %i\n",r);
140
141     return r;
142 }
143
144 /***********************************************************************
145  *             HlinkNavigate (HLINK.@)
146  */
147 HRESULT WINAPI HlinkNavigate(IHlink *phl, IHlinkFrame *phlFrame,
148         DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pbsc,
149         IHlinkBrowseContext *phlbc)
150 {
151     HRESULT r = S_OK;
152
153     TRACE("%p %p %i %p %p %p\n", phl, phlFrame, grfHLNF, pbc, pbsc, phlbc);
154
155     if (phlFrame)
156         r = IHlinkFrame_Navigate(phlFrame, grfHLNF, pbc, pbsc, phl);
157     else if (phl)
158         r = IHlink_Navigate(phl, grfHLNF, pbc, pbsc, phlbc);
159
160     return r;
161 }
162
163 /***********************************************************************
164  *             HlinkOnNavigate (HLINK.@)
165  */
166 HRESULT WINAPI HlinkOnNavigate( IHlinkFrame *phlFrame,
167         IHlinkBrowseContext* phlbc, DWORD grfHLNF, IMoniker *pmkTarget,
168         LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, ULONG* puHLID)
169 {
170     HRESULT r = S_OK;
171
172     TRACE("%p %p %i %p %s %s %p\n",phlFrame, phlbc, grfHLNF, pmkTarget,
173             debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), puHLID);
174
175     r = IHlinkBrowseContext_OnNavigateHlink(phlbc, grfHLNF, pmkTarget,
176             pwzLocation, pwzFriendlyName, puHLID);
177
178     if (phlFrame)
179         r = IHlinkFrame_OnNavigate(phlFrame,grfHLNF,pmkTarget, pwzLocation,
180                 pwzFriendlyName, 0);
181
182     return r;
183 }
184
185 /***********************************************************************
186  *             HlinkCreateFromData (HLINK.@)
187  */
188 HRESULT WINAPI HlinkCreateFromData(IDataObject *piDataObj,
189         IHlinkSite *pihlsite, DWORD dwSiteData, IUnknown *piunkOuter,
190         REFIID riid, void **ppvObj)
191 {
192     FIXME("%p %p %d %p %p %p\n",
193           piDataObj, pihlsite, dwSiteData, piunkOuter, riid, ppvObj);
194     *ppvObj = NULL;
195     return E_NOTIMPL;
196 }
197
198 /***********************************************************************
199  *             HlinkQueryCreateFromData (HLINK.@)
200  */
201 HRESULT WINAPI HlinkQueryCreateFromData(IDataObject* piDataObj)
202 {
203     FIXME("%p\n", piDataObj);
204     return E_NOTIMPL;
205 }
206
207 /***********************************************************************
208  *             HlinkNavigateToStringReference (HLINK.@)
209  */
210 HRESULT WINAPI HlinkNavigateToStringReference( LPCWSTR pwzTarget,
211         LPCWSTR pwzLocation, IHlinkSite *pihlsite, DWORD dwSiteData,
212         IHlinkFrame *pihlframe, DWORD grfHLNF, LPBC pibc,
213         IBindStatusCallback *pibsc, IHlinkBrowseContext *pihlbc)
214 {
215     HRESULT r;
216     IHlink *hlink = NULL;
217
218     FIXME("%s %s %p %08x %p %08x %p %p %p\n",
219           debugstr_w(pwzTarget), debugstr_w(pwzLocation), pihlsite,
220           dwSiteData, pihlframe, grfHLNF, pibc, pibsc, pihlbc);
221
222     r = HlinkCreateFromString( pwzTarget, pwzLocation, NULL, pihlsite,
223                                dwSiteData, NULL, &IID_IHlink, (LPVOID*) &hlink );
224     if (SUCCEEDED(r))
225         r = HlinkNavigate(hlink, pihlframe, grfHLNF, pibc, pibsc, pihlbc);
226
227     return r;
228 }
229
230 /***********************************************************************
231  *             HlinkIsShortcut (HLINK.@)
232  */
233 HRESULT WINAPI HlinkIsShortcut(LPCWSTR pwzFileName)
234 {
235     int len;
236
237     static const WCHAR url_ext[] = {'.','u','r','l',0};
238
239     TRACE("(%s)\n", debugstr_w(pwzFileName));
240
241     if(!pwzFileName)
242         return E_INVALIDARG;
243
244     len = strlenW(pwzFileName)-4;
245     if(len < 0)
246         return S_FALSE;
247
248     return strcmpiW(pwzFileName+len, url_ext) ? S_FALSE : S_OK;
249 }
250
251 /***********************************************************************
252  *             HlinkGetSpecialReference (HLINK.@)
253  */
254 HRESULT WINAPI HlinkGetSpecialReference(ULONG uReference, LPWSTR *ppwzReference)
255 {
256     DWORD res, type, size = 100;
257     LPCWSTR value_name;
258     WCHAR *buf;
259     HKEY hkey;
260
261     static const WCHAR start_pageW[] = {'S','t','a','r','t',' ','P','a','g','e',0};
262     static const WCHAR search_pageW[] = {'S','e','a','r','c','h',' ','P','a','g','e',0};
263
264     static const WCHAR ie_main_keyW[] =
265         {'S','o','f','t','w','a','r','e',
266          '\\','M','i','c','r','o','s','o','f','t','\\',
267          'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',
268          '\\','M','a','i','n',0};
269
270     TRACE("(%u %p)\n", uReference, ppwzReference);
271
272     *ppwzReference = NULL;
273
274     switch(uReference) {
275     case HLSR_HOME:
276         value_name = start_pageW;
277         break;
278     case HLSR_SEARCHPAGE:
279         value_name = search_pageW;
280         break;
281     case HLSR_HISTORYFOLDER:
282         return E_NOTIMPL;
283     default:
284         return E_INVALIDARG;
285     }
286
287     res = RegOpenKeyW(HKEY_CURRENT_USER, ie_main_keyW, &hkey);
288     if(res != ERROR_SUCCESS) {
289         WARN("Could not open key: %u\n", res);
290         return HRESULT_FROM_WIN32(res);
291     }
292
293     buf = CoTaskMemAlloc(size);
294     res = RegQueryValueExW(hkey, value_name, NULL, &type, (PBYTE)buf, &size);
295     buf = CoTaskMemRealloc(buf, size);
296     if(res == ERROR_MORE_DATA)
297         res = RegQueryValueExW(hkey, value_name, NULL, &type, (PBYTE)buf, &size);
298     RegCloseKey(hkey);
299     if(res != ERROR_SUCCESS) {
300         WARN("Could not query value %s: %u\n", debugstr_w(value_name), res);
301         CoTaskMemFree(buf);
302         return HRESULT_FROM_WIN32(res);
303     }
304
305     *ppwzReference = buf;
306     return S_OK;
307 }
308
309 /***********************************************************************
310  *             HlinkTranslateURL (HLINK.@)
311  */
312 HRESULT WINAPI HlinkTranslateURL(LPCWSTR pwzURL, DWORD grfFlags, LPWSTR *ppwzTranslatedURL)
313 {
314     FIXME("(%s %08x %p)\n", debugstr_w(pwzURL), grfFlags, ppwzTranslatedURL);
315     return E_NOTIMPL;
316 }
317
318 /***********************************************************************
319  *             HlinkUpdateStackItem (HLINK.@)
320  */
321 HRESULT WINAPI HlinkUpdateStackItem(IHlinkFrame *pihlframe, IHlinkBrowseContext *pihlbc,
322         ULONG uHLID, IMoniker *pimkTrgt, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
323 {
324     FIXME("(%p %p %u %p %s %s)\n", pihlframe, pihlbc, uHLID, pimkTrgt, debugstr_w(pwzLocation),
325           debugstr_w(pwzFriendlyName));
326     return E_NOTIMPL;
327 }
328
329 /***********************************************************************
330  *             HlinkParseDisplayName (HLINK.@)
331  */
332 HRESULT WINAPI HlinkParseDisplayName(LPBC pibc, LPCWSTR pwzDisplayName, BOOL fNoForceAbs,
333         ULONG *pcchEaten, IMoniker **ppimk)
334 {
335     HRESULT hres;
336
337     TRACE("(%p %s %x %p %p)\n", pibc, debugstr_w(pwzDisplayName), fNoForceAbs, pcchEaten, ppimk);
338
339     if(fNoForceAbs)
340         FIXME("Unsupported fNoForceAbs\n");
341
342     hres = MkParseDisplayNameEx(pibc, pwzDisplayName, pcchEaten, ppimk);
343     if(SUCCEEDED(hres))
344         return hres;
345
346     hres = MkParseDisplayName(pibc, pwzDisplayName, pcchEaten, ppimk);
347     if(SUCCEEDED(hres))
348         return hres;
349
350     hres = CreateFileMoniker(pwzDisplayName, ppimk);
351     if(SUCCEEDED(hres))
352         *pcchEaten = strlenW(pwzDisplayName);
353
354     return hres;
355 }
356
357 /***********************************************************************
358  *             HlinkResolveMonikerForData (HLINK.@)
359  */
360 HRESULT WINAPI HlinkResolveMonikerForData(LPMONIKER pimkReference, DWORD reserved, LPBC pibc,
361         ULONG cFmtetc, FORMATETC *rgFmtetc, IBindStatusCallback *pibsc, LPMONIKER pimkBase)
362 {
363     LPOLESTR name = NULL;
364     IBindCtx *bctx;
365     DWORD mksys = 0;
366     void *obj = NULL;
367     HRESULT hres;
368
369     TRACE("(%p %x %p %d %p %p %p)\n", pimkReference, reserved, pibc, cFmtetc, rgFmtetc, pibsc, pimkBase);
370
371     if(cFmtetc || rgFmtetc || pimkBase)
372         FIXME("Unsupported args\n");
373
374     hres = RegisterBindStatusCallback(pibc, pibsc, NULL /* FIXME */, 0);
375     if(FAILED(hres))
376         return hres;
377
378     hres = IMoniker_IsSystemMoniker(pimkReference, &mksys);
379     if(SUCCEEDED(hres) && mksys != MKSYS_URLMONIKER)
380         WARN("sysmk = %x\n", mksys);
381
382     /* FIXME: What is it for? */
383     CreateBindCtx(0, &bctx);
384     hres = IMoniker_GetDisplayName(pimkReference, bctx, NULL, &name);
385     IBindCtx_Release(bctx);
386     if(SUCCEEDED(hres)) {
387         TRACE("got display name %s\n", debugstr_w(name));
388         CoTaskMemFree(name);
389     }
390
391     return IMoniker_BindToStorage(pimkReference, pibc, NULL, &IID_IUnknown, &obj);
392 }
393
394 static HRESULT WINAPI HLinkCF_fnQueryInterface ( LPCLASSFACTORY iface,
395         REFIID riid, LPVOID *ppvObj)
396 {
397     CFImpl *This = (CFImpl *)iface;
398
399     TRACE("(%p)->(%s)\n",This,debugstr_guid(riid));
400
401     *ppvObj = NULL;
402
403     if (IsEqualIID(riid, &IID_IUnknown) ||
404         IsEqualIID(riid, &IID_IClassFactory))
405     {
406         *ppvObj = This;
407         return S_OK;
408     }
409
410     TRACE("-- E_NOINTERFACE\n");
411     return E_NOINTERFACE;
412 }
413
414 static ULONG WINAPI HLinkCF_fnAddRef (LPCLASSFACTORY iface)
415 {
416     return 2;
417 }
418
419 static ULONG WINAPI HLinkCF_fnRelease(LPCLASSFACTORY iface)
420 {
421     return 1;
422 }
423
424 static HRESULT WINAPI HLinkCF_fnCreateInstance( LPCLASSFACTORY iface,
425         LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
426 {
427     CFImpl *This = (CFImpl *)iface;
428
429     TRACE("%p->(%p,%s,%p)\n", This, pUnkOuter, debugstr_guid(riid), ppvObject);
430
431     *ppvObject = NULL;
432
433     return This->lpfnCI(pUnkOuter, riid, ppvObject);
434 }
435
436 static HRESULT WINAPI HLinkCF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
437 {
438     FIXME("%p %d\n", iface, fLock);
439     return E_NOTIMPL;
440 }
441
442 static const IClassFactoryVtbl hlcfvt =
443 {
444     HLinkCF_fnQueryInterface,
445     HLinkCF_fnAddRef,
446     HLinkCF_fnRelease,
447     HLinkCF_fnCreateInstance,
448     HLinkCF_fnLockServer
449 };
450
451 static CFImpl HLink_cf = { &hlcfvt, HLink_Constructor };
452 static CFImpl HLinkBrowseContext_cf = { &hlcfvt, HLinkBrowseContext_Constructor };
453
454 /***********************************************************************
455  *             DllGetClassObject (HLINK.@)
456  */
457 HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
458 {
459     IClassFactory   *pcf = NULL;
460
461     TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
462
463     if (!ppv)
464         return E_INVALIDARG;
465     *ppv = NULL;
466
467     if (IsEqualIID(rclsid, &CLSID_StdHlink))
468         pcf = (IClassFactory*) &HLink_cf;
469     else if (IsEqualIID(rclsid, &CLSID_StdHlinkBrowseContext))
470         pcf = (IClassFactory*) &HLinkBrowseContext_cf;
471     else
472         return CLASS_E_CLASSNOTAVAILABLE;
473
474     return IClassFactory_QueryInterface(pcf, iid, ppv);
475 }
476
477 static HRESULT register_clsid(LPCGUID guid)
478 {
479     static const WCHAR clsid[] =
480         {'C','L','S','I','D','\\',0};
481     static const WCHAR ips[] =
482         {'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
483     static const WCHAR hlink[] =
484         {'h','l','i','n','k','.','d','l','l',0};
485     static const WCHAR threading_model[] =
486         {'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
487     static const WCHAR apartment[] =
488         {'A','p','a','r','t','m','e','n','t',0};
489     WCHAR path[80];
490     HKEY key = NULL;
491     LONG r;
492
493     lstrcpyW(path, clsid);
494     StringFromGUID2(guid, &path[6], 80);
495     lstrcatW(path, ips);
496     r = RegCreateKeyW(HKEY_CLASSES_ROOT, path, &key);
497     if (r != ERROR_SUCCESS)
498         return E_FAIL;
499
500     RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)hlink, sizeof hlink);
501     RegSetValueExW(key, threading_model, 0, REG_SZ, (const BYTE *)apartment, sizeof apartment);
502     RegCloseKey(key);
503
504     return S_OK;
505 }
506
507 /***********************************************************************
508  *             DllRegisterServer (HLINK.@)
509  */
510 HRESULT WINAPI DllRegisterServer(void)
511 {
512     HRESULT r;
513
514     r = register_clsid(&CLSID_StdHlink);
515     if (SUCCEEDED(r))
516         r = register_clsid(&CLSID_StdHlinkBrowseContext);
517
518     return S_OK;
519 }