~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/shdocvw/intshcut.c

Version: ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright 2008 Damjan Jovanovic
  3  *
  4  * ShellLink's barely documented cousin that handles URLs.
  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 /*
 22  * TODO:
 23  * Implement the IShellLinkA/W interfaces
 24  * Handle the SetURL flags
 25  * Implement any other interfaces? Does any software actually use them?
 26  *
 27  * The installer for the Zuma Deluxe Popcap game is good for testing.
 28  */
 29 
 30 #include "wine/debug.h"
 31 #include "shdocvw.h"
 32 #include "objidl.h"
 33 #include "shobjidl.h"
 34 #include "intshcut.h"
 35 
 36 WINE_DEFAULT_DEBUG_CHANNEL(shdocvw);
 37 
 38 typedef struct
 39 {
 40     IUniformResourceLocatorA uniformResourceLocatorA;
 41     IUniformResourceLocatorW uniformResourceLocatorW;
 42     IPersistFile persistFile;
 43 
 44     LONG refCount;
 45 
 46     WCHAR *url;
 47     BOOLEAN isDirty;
 48     LPOLESTR currentFile;
 49 } InternetShortcut;
 50 
 51 /* utility functions */
 52 
 53 static inline InternetShortcut* impl_from_IUniformResourceLocatorA(IUniformResourceLocatorA *iface)
 54 {
 55     return (InternetShortcut*)((char*)iface - FIELD_OFFSET(InternetShortcut, uniformResourceLocatorA));
 56 }
 57 
 58 static inline InternetShortcut* impl_from_IUniformResourceLocatorW(IUniformResourceLocatorW *iface)
 59 {
 60     return (InternetShortcut*)((char*)iface - FIELD_OFFSET(InternetShortcut, uniformResourceLocatorW));
 61 }
 62 
 63 static inline InternetShortcut* impl_from_IPersistFile(IPersistFile *iface)
 64 {
 65     return (InternetShortcut*)((char*)iface - FIELD_OFFSET(InternetShortcut, persistFile));
 66 }
 67 
 68 static BOOL StartLinkProcessor(LPCOLESTR szLink)
 69 {
 70     static const WCHAR szFormat[] = {
 71         'w','i','n','e','m','e','n','u','b','u','i','l','d','e','r','.','e','x','e',
 72         ' ','-','w',' ','-','u',' ','"','%','s','"',0 };
 73     LONG len;
 74     LPWSTR buffer;
 75     STARTUPINFOW si;
 76     PROCESS_INFORMATION pi;
 77     BOOL ret;
 78 
 79     len = sizeof(szFormat) + lstrlenW( szLink ) * sizeof(WCHAR);
 80     buffer = heap_alloc( len );
 81     if( !buffer )
 82         return FALSE;
 83 
 84     wsprintfW( buffer, szFormat, szLink );
 85 
 86     TRACE("starting %s\n",debugstr_w(buffer));
 87 
 88     memset(&si, 0, sizeof(si));
 89     si.cb = sizeof(si);
 90 
 91     ret = CreateProcessW( NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi );
 92 
 93     HeapFree( GetProcessHeap(), 0, buffer );
 94 
 95     if (ret)
 96     {
 97         CloseHandle( pi.hProcess );
 98         CloseHandle( pi.hThread );
 99     }
100 
101     return ret;
102 }
103 
104 /* interface functions */
105 
106 static HRESULT Unknown_QueryInterface(InternetShortcut *This, REFIID riid, PVOID *ppvObject)
107 {
108     TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject);
109     *ppvObject = NULL;
110     if (IsEqualGUID(&IID_IUnknown, riid))
111         *ppvObject = &This->uniformResourceLocatorA;
112     else if (IsEqualGUID(&IID_IUniformResourceLocatorA, riid))
113         *ppvObject = &This->uniformResourceLocatorA;
114     else if (IsEqualGUID(&IID_IUniformResourceLocatorW, riid))
115         *ppvObject = &This->uniformResourceLocatorW;
116     else if (IsEqualGUID(&IID_IPersistFile, riid))
117         *ppvObject = &This->persistFile;
118     else if (IsEqualGUID(&IID_IShellLinkA, riid))
119     {
120         FIXME("The IShellLinkA interface is not yet supported by InternetShortcut\n");
121         return E_NOINTERFACE;
122     }
123     else if (IsEqualGUID(&IID_IShellLinkW, riid))
124     {
125         FIXME("The IShellLinkW interface is not yet supported by InternetShortcut\n");
126         return E_NOINTERFACE;
127     }
128     else
129     {
130         FIXME("Interface with GUID %s not yet implemented by InternetShortcut\n", debugstr_guid(riid));
131         return E_NOINTERFACE;
132     }
133     IUnknown_AddRef((IUnknown*)*ppvObject);
134     return S_OK;
135 }
136 
137 static ULONG Unknown_AddRef(InternetShortcut *This)
138 {
139     TRACE("(%p)\n", This);
140     return InterlockedIncrement(&This->refCount);
141 }
142 
143 static ULONG Unknown_Release(InternetShortcut *This)
144 {
145     ULONG count;
146     TRACE("(%p)\n", This);
147     count = InterlockedDecrement(&This->refCount);
148     if (count == 0)
149     {
150         CoTaskMemFree(This->url);
151         CoTaskMemFree(This->currentFile);
152         heap_free(This);
153         SHDOCVW_UnlockModule();
154     }
155     return count;
156 }
157 
158 static HRESULT WINAPI UniformResourceLocatorW_QueryInterface(IUniformResourceLocatorW *url, REFIID riid, PVOID *ppvObject)
159 {
160     InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
161     TRACE("(%p, %s, %p)\n", url, debugstr_guid(riid), ppvObject);
162     return Unknown_QueryInterface(This, riid, ppvObject);
163 }
164 
165 static ULONG WINAPI UniformResourceLocatorW_AddRef(IUniformResourceLocatorW *url)
166 {
167     InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
168     TRACE("(%p)\n", url);
169     return Unknown_AddRef(This);
170 }
171 
172 static ULONG WINAPI UniformResourceLocatorW_Release(IUniformResourceLocatorW *url)
173 {
174     InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
175     TRACE("(%p)\n", url);
176     return Unknown_Release(This);
177 }
178 
179 static HRESULT WINAPI UniformResourceLocatorW_SetUrl(IUniformResourceLocatorW *url, LPCWSTR pcszURL, DWORD dwInFlags)
180 {
181     WCHAR *newURL = NULL;
182     InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
183     TRACE("(%p, %s, 0x%x)\n", url, debugstr_w(pcszURL), dwInFlags);
184     if (dwInFlags != 0)
185         FIXME("ignoring unsupported flags 0x%x\n", dwInFlags);
186     if (pcszURL != NULL)
187     {
188         newURL = co_strdupW(pcszURL);
189         if (newURL == NULL)
190             return E_OUTOFMEMORY;
191     }
192     CoTaskMemFree(This->url);
193     This->url = newURL;
194     This->isDirty = TRUE;
195     return S_OK;
196 }
197 
198 static HRESULT WINAPI UniformResourceLocatorW_GetUrl(IUniformResourceLocatorW *url, LPWSTR *ppszURL)
199 {
200     HRESULT hr = S_OK;
201     InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
202     TRACE("(%p, %p)\n", url, ppszURL);
203     if (This->url == NULL)
204         *ppszURL = NULL;
205     else
206     {
207         *ppszURL = co_strdupW(This->url);
208         if (*ppszURL == NULL)
209             hr = E_OUTOFMEMORY;
210     }
211     return hr;
212 }
213 
214 static HRESULT WINAPI UniformResourceLocatorW_InvokeCommand(IUniformResourceLocatorW *url, PURLINVOKECOMMANDINFOW pCommandInfo)
215 {
216     FIXME("(%p, %p): stub\n", url, pCommandInfo);
217     return E_NOTIMPL;
218 }
219 
220 static HRESULT WINAPI UniformResourceLocatorA_QueryInterface(IUniformResourceLocatorA *url, REFIID riid, PVOID *ppvObject)
221 {
222     InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
223     TRACE("(%p, %s, %p)\n", url, debugstr_guid(riid), ppvObject);
224     return Unknown_QueryInterface(This, riid, ppvObject);
225 }
226 
227 static ULONG WINAPI UniformResourceLocatorA_AddRef(IUniformResourceLocatorA *url)
228 {
229     InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
230     TRACE("(%p)\n", url);
231     return Unknown_AddRef(This);
232 }
233 
234 static ULONG WINAPI UniformResourceLocatorA_Release(IUniformResourceLocatorA *url)
235 {
236     InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
237     TRACE("(%p)\n", url);
238     return Unknown_Release(This);
239 }
240 
241 static HRESULT WINAPI UniformResourceLocatorA_SetUrl(IUniformResourceLocatorA *url, LPCSTR pcszURL, DWORD dwInFlags)
242 {
243     WCHAR *newURL = NULL;
244     InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
245     TRACE("(%p, %s, 0x%x)\n", url, debugstr_a(pcszURL), dwInFlags);
246     if (dwInFlags != 0)
247         FIXME("ignoring unsupported flags 0x%x\n", dwInFlags);
248     if (pcszURL != NULL)
249     {
250         newURL = co_strdupAtoW(pcszURL);
251         if (newURL == NULL)
252             return E_OUTOFMEMORY;
253     }
254     CoTaskMemFree(This->url);
255     This->url = newURL;
256     This->isDirty = TRUE;
257     return S_OK;
258 }
259 
260 static HRESULT WINAPI UniformResourceLocatorA_GetUrl(IUniformResourceLocatorA *url, LPSTR *ppszURL)
261 {
262     HRESULT hr = S_OK;
263     InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
264     TRACE("(%p, %p)\n", url, ppszURL);
265     if (This->url == NULL)
266         *ppszURL = NULL;
267     else
268     {
269         *ppszURL = co_strdupWtoA(This->url);
270         if (*ppszURL == NULL)
271             hr = E_OUTOFMEMORY;
272     }
273     return hr;
274 }
275 
276 static HRESULT WINAPI UniformResourceLocatorA_InvokeCommand(IUniformResourceLocatorA *url, PURLINVOKECOMMANDINFOA pCommandInfo)
277 {
278     FIXME("(%p, %p): stub\n", url, pCommandInfo);
279     return E_NOTIMPL;
280 }
281 
282 static HRESULT WINAPI PersistFile_QueryInterface(IPersistFile *pFile, REFIID riid, PVOID *ppvObject)
283 {
284     InternetShortcut *This = impl_from_IPersistFile(pFile);
285     TRACE("(%p, %s, %p)\n", pFile, debugstr_guid(riid), ppvObject);
286     return Unknown_QueryInterface(This, riid, ppvObject);
287 }
288 
289 static ULONG WINAPI PersistFile_AddRef(IPersistFile *pFile)
290 {
291     InternetShortcut *This = impl_from_IPersistFile(pFile);
292     TRACE("(%p)\n", pFile);
293     return Unknown_AddRef(This);
294 }
295 
296 static ULONG WINAPI PersistFile_Release(IPersistFile *pFile)
297 {
298     InternetShortcut *This = impl_from_IPersistFile(pFile);
299     TRACE("(%p)\n", pFile);
300     return Unknown_Release(This);
301 }
302 
303 static HRESULT WINAPI PersistFile_GetClassID(IPersistFile *pFile, CLSID *pClassID)
304 {
305     TRACE("(%p, %p)\n", pFile, pClassID);
306     *pClassID = CLSID_InternetShortcut;
307     return S_OK;
308 }
309 
310 static HRESULT WINAPI PersistFile_IsDirty(IPersistFile *pFile)
311 {
312     InternetShortcut *This = impl_from_IPersistFile(pFile);
313     TRACE("(%p)\n", pFile);
314     return This->isDirty ? S_OK : S_FALSE;
315 }
316 
317 static HRESULT WINAPI PersistFile_Load(IPersistFile *pFile, LPCOLESTR pszFileName, DWORD dwMode)
318 {
319     WCHAR str_header[] = {'I','n','t','e','r','n','e','t','S','h','o','r','t','c','u','t',0};
320     WCHAR str_URL[] = {'U','R','L',0};
321     WCHAR *filename = NULL;
322     HRESULT hr;
323     InternetShortcut *This = impl_from_IPersistFile(pFile);
324     TRACE("(%p, %s, 0x%x)\n", pFile, debugstr_w(pszFileName), dwMode);
325     if (dwMode != 0)
326         FIXME("ignoring unimplemented mode 0x%x\n", dwMode);
327     filename = co_strdupW(pszFileName);
328     if (filename != NULL)
329     {
330         DWORD len = 128;
331         DWORD r;
332         WCHAR *url = CoTaskMemAlloc(len*sizeof(WCHAR));
333         if (url != NULL)
334         {
335             r = GetPrivateProfileStringW(str_header, str_URL, NULL, url, len, pszFileName);
336             while (r == len-1)
337             {
338                 CoTaskMemFree(url);
339                 len *= 2;
340                 url = CoTaskMemAlloc(len);
341                 if (url == NULL)
342                     break;
343                 r = GetPrivateProfileStringW(str_header, str_URL, NULL, url, len, pszFileName);
344             }
345             if (r == 0)
346                 hr = E_FAIL;
347             else if (url != NULL)
348             {
349                 CoTaskMemFree(This->currentFile);
350                 This->currentFile = filename;
351                 CoTaskMemFree(This->url);
352                 This->url = url;
353                 This->isDirty = FALSE;
354                 return S_OK;
355             }
356             else
357                 hr = E_OUTOFMEMORY;
358             CoTaskMemFree(url);
359         }
360         else
361             hr = E_OUTOFMEMORY;
362         CoTaskMemFree(filename);
363     }
364     else
365         hr = E_OUTOFMEMORY;
366     return hr;
367 }
368 
369 static HRESULT WINAPI PersistFile_Save(IPersistFile *pFile, LPCOLESTR pszFileName, BOOL fRemember)
370 {
371     HRESULT hr = S_OK;
372     INT len;
373     CHAR *url;
374     InternetShortcut *This = impl_from_IPersistFile(pFile);
375 
376     TRACE("(%p, %s, %d)\n", pFile, debugstr_w(pszFileName), fRemember);
377 
378     if (pszFileName != NULL && fRemember)
379     {
380         LPOLESTR oldFile = This->currentFile;
381         This->currentFile = co_strdupW(pszFileName);
382         if (This->currentFile == NULL)
383         {
384             This->currentFile = oldFile;
385             return E_OUTOFMEMORY;
386         }
387         CoTaskMemFree(oldFile);
388     }
389     if (This->url == NULL)
390         return E_FAIL;
391 
392     /* Windows seems to always write:
393      *   ASCII "[InternetShortcut]" headers
394      *   ASCII names in "name=value" pairs
395      *   An ASCII (probably UTF8?) value in "URL=..."
396      */
397     len = WideCharToMultiByte(CP_UTF8, 0, This->url, -1, NULL, 0, 0, 0);
398     url = heap_alloc(len);
399     if (url != NULL)
400     {
401         HANDLE file;
402         WideCharToMultiByte(CP_UTF8, 0, This->url, -1, url, len, 0, 0);
403         file = CreateFileW(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
404         if (file != INVALID_HANDLE_VALUE)
405         {
406             DWORD bytesWritten;
407             char str_header[] = "[InternetShortcut]";
408             char str_URL[] = "URL=";
409             char str_eol[] = "\r\n";
410 
411             WriteFile(file, str_header, lstrlenA(str_header), &bytesWritten, NULL);
412             WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL);
413             WriteFile(file, str_URL, lstrlenA(str_URL), &bytesWritten, NULL);
414             WriteFile(file, url, lstrlenA(url), &bytesWritten, NULL);
415             WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL);
416             CloseHandle(file);
417             if (pszFileName == NULL || fRemember)
418                 This->isDirty = FALSE;
419             StartLinkProcessor(pszFileName);
420         }
421         else
422             hr = E_FAIL;
423         heap_free(url);
424     }
425     else
426         hr = E_OUTOFMEMORY;
427 
428     return hr;
429 }
430 
431 static HRESULT WINAPI PersistFile_SaveCompleted(IPersistFile *pFile, LPCOLESTR pszFileName)
432 {
433     FIXME("(%p, %p): stub\n", pFile, pszFileName);
434     return E_NOTIMPL;
435 }
436 
437 static HRESULT WINAPI PersistFile_GetCurFile(IPersistFile *pFile, LPOLESTR *ppszFileName)
438 {
439     HRESULT hr = S_OK;
440     InternetShortcut *This = impl_from_IPersistFile(pFile);
441     TRACE("(%p, %p)\n", pFile, ppszFileName);
442     if (This->currentFile == NULL)
443         *ppszFileName = NULL;
444     else
445     {
446         *ppszFileName = co_strdupW(This->currentFile);
447         if (*ppszFileName == NULL)
448             hr = E_OUTOFMEMORY;
449     }
450     return hr;
451 }
452 
453 
454 
455 static const IUniformResourceLocatorWVtbl uniformResourceLocatorWVtbl = {
456     UniformResourceLocatorW_QueryInterface,
457     UniformResourceLocatorW_AddRef,
458     UniformResourceLocatorW_Release,
459     UniformResourceLocatorW_SetUrl,
460     UniformResourceLocatorW_GetUrl,
461     UniformResourceLocatorW_InvokeCommand
462 };
463 
464 static const IUniformResourceLocatorAVtbl uniformResourceLocatorAVtbl = {
465     UniformResourceLocatorA_QueryInterface,
466     UniformResourceLocatorA_AddRef,
467     UniformResourceLocatorA_Release,
468     UniformResourceLocatorA_SetUrl,
469     UniformResourceLocatorA_GetUrl,
470     UniformResourceLocatorA_InvokeCommand
471 };
472 
473 static const IPersistFileVtbl persistFileVtbl = {
474     PersistFile_QueryInterface,
475     PersistFile_AddRef,
476     PersistFile_Release,
477     PersistFile_GetClassID,
478     PersistFile_IsDirty,
479     PersistFile_Load,
480     PersistFile_Save,
481     PersistFile_SaveCompleted,
482     PersistFile_GetCurFile
483 };
484 
485 HRESULT InternetShortcut_Create(IUnknown *pOuter, REFIID riid, void **ppv)
486 {
487     InternetShortcut *This;
488     HRESULT hr;
489 
490     TRACE("(%p, %s, %p)\n", pOuter, debugstr_guid(riid), ppv);
491 
492     *ppv = NULL;
493 
494     if(pOuter)
495         return CLASS_E_NOAGGREGATION;
496 
497     This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(InternetShortcut));
498     if (This)
499     {
500         This->uniformResourceLocatorA.lpVtbl = &uniformResourceLocatorAVtbl;
501         This->uniformResourceLocatorW.lpVtbl = &uniformResourceLocatorWVtbl;
502         This->persistFile.lpVtbl = &persistFileVtbl;
503         This->refCount = 0;
504         hr = Unknown_QueryInterface(This, riid, ppv);
505         if (SUCCEEDED(hr))
506             SHDOCVW_LockModule();
507         else
508             heap_free(This);
509         return hr;
510     }
511     else
512         return E_OUTOFMEMORY;
513 }
514 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.