+++ /dev/null
-/*
- * Copyright 2008 Damjan Jovanovic
- *
- * ShellLink's barely documented cousin that handles URLs.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
- */
-
-/*
- * TODO:
- * Implement the IShellLinkA/W interfaces
- * Handle the SetURL flags
- * Implement any other interfaces? Does any software actually use them?
- *
- * The installer for the Zuma Deluxe Popcap game is good for testing.
- */
-
-#include "ieframe.h"
-
-typedef struct
-{
- IUniformResourceLocatorA IUniformResourceLocatorA_iface;
- IUniformResourceLocatorW IUniformResourceLocatorW_iface;
- IPersistFile IPersistFile_iface;
- IPropertySetStorage IPropertySetStorage_iface;
-
- LONG refCount;
-
- IPropertySetStorage *property_set_storage;
- WCHAR *url;
- BOOLEAN isDirty;
- LPOLESTR currentFile;
-} InternetShortcut;
-
-/* utility functions */
-
-static inline InternetShortcut* impl_from_IUniformResourceLocatorA(IUniformResourceLocatorA *iface)
-{
- return CONTAINING_RECORD(iface, InternetShortcut, IUniformResourceLocatorA_iface);
-}
-
-static inline InternetShortcut* impl_from_IUniformResourceLocatorW(IUniformResourceLocatorW *iface)
-{
- return CONTAINING_RECORD(iface, InternetShortcut, IUniformResourceLocatorW_iface);
-}
-
-static inline InternetShortcut* impl_from_IPersistFile(IPersistFile *iface)
-{
- return CONTAINING_RECORD(iface, InternetShortcut, IPersistFile_iface);
-}
-
-static inline InternetShortcut* impl_from_IPropertySetStorage(IPropertySetStorage *iface)
-{
- return CONTAINING_RECORD(iface, InternetShortcut, IPropertySetStorage_iface);
-}
-
-static BOOL run_winemenubuilder( const WCHAR *args )
-{
- static const WCHAR menubuilder[] = {'\\','w','i','n','e','m','e','n','u','b','u','i','l','d','e','r','.','e','x','e',0};
- LONG len;
- LPWSTR buffer;
- STARTUPINFOW si;
- PROCESS_INFORMATION pi;
- BOOL ret;
- WCHAR app[MAX_PATH];
- void *redir;
-
- GetSystemDirectoryW( app, MAX_PATH - sizeof(menubuilder)/sizeof(WCHAR) );
- strcatW( app, menubuilder );
-
- len = (strlenW( app ) + strlenW( args ) + 1) * sizeof(WCHAR);
- buffer = heap_alloc( len );
- if( !buffer )
- return FALSE;
-
- strcpyW( buffer, app );
- strcatW( buffer, args );
-
- TRACE("starting %s\n",debugstr_w(buffer));
-
- memset(&si, 0, sizeof(si));
- si.cb = sizeof(si);
-
- Wow64DisableWow64FsRedirection( &redir );
- ret = CreateProcessW( app, buffer, NULL, NULL, FALSE, DETACHED_PROCESS, NULL, NULL, &si, &pi );
- Wow64RevertWow64FsRedirection( redir );
-
- heap_free( buffer );
-
- if (ret)
- {
- CloseHandle( pi.hProcess );
- CloseHandle( pi.hThread );
- }
-
- return ret;
-}
-
-static BOOL StartLinkProcessor( LPCOLESTR szLink )
-{
- static const WCHAR szFormat[] = { ' ','-','w',' ','-','u',' ','"','%','s','"',0 };
- LONG len;
- LPWSTR buffer;
- BOOL ret;
-
- len = sizeof(szFormat) + lstrlenW( szLink ) * sizeof(WCHAR);
- buffer = heap_alloc( len );
- if( !buffer )
- return FALSE;
-
- sprintfW( buffer, szFormat, szLink );
- ret = run_winemenubuilder( buffer );
- heap_free( buffer );
- return ret;
-}
-
-/* interface functions */
-
-static HRESULT Unknown_QueryInterface(InternetShortcut *This, REFIID riid, PVOID *ppvObject)
-{
- TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppvObject);
- *ppvObject = NULL;
- if (IsEqualGUID(&IID_IUnknown, riid))
- *ppvObject = &This->IUniformResourceLocatorA_iface;
- else if (IsEqualGUID(&IID_IUniformResourceLocatorA, riid))
- *ppvObject = &This->IUniformResourceLocatorA_iface;
- else if (IsEqualGUID(&IID_IUniformResourceLocatorW, riid))
- *ppvObject = &This->IUniformResourceLocatorW_iface;
- else if (IsEqualGUID(&IID_IPersistFile, riid))
- *ppvObject = &This->IPersistFile_iface;
- else if (IsEqualGUID(&IID_IPropertySetStorage, riid))
- *ppvObject = &This->IPropertySetStorage_iface;
- else if (IsEqualGUID(&IID_IShellLinkA, riid))
- {
- FIXME("The IShellLinkA interface is not yet supported by InternetShortcut\n");
- return E_NOINTERFACE;
- }
- else if (IsEqualGUID(&IID_IShellLinkW, riid))
- {
- FIXME("The IShellLinkW interface is not yet supported by InternetShortcut\n");
- return E_NOINTERFACE;
- }
- else
- {
- FIXME("Interface with GUID %s not yet implemented by InternetShortcut\n", debugstr_guid(riid));
- return E_NOINTERFACE;
- }
- IUnknown_AddRef((IUnknown*)*ppvObject);
- return S_OK;
-}
-
-static ULONG Unknown_AddRef(InternetShortcut *This)
-{
- TRACE("(%p)\n", This);
- return InterlockedIncrement(&This->refCount);
-}
-
-static ULONG Unknown_Release(InternetShortcut *This)
-{
- ULONG count;
- TRACE("(%p)\n", This);
- count = InterlockedDecrement(&This->refCount);
- if (count == 0)
- {
- CoTaskMemFree(This->url);
- CoTaskMemFree(This->currentFile);
- IPropertySetStorage_Release(This->property_set_storage);
- heap_free(This);
- unlock_module();
- }
- return count;
-}
-
-static HRESULT WINAPI UniformResourceLocatorW_QueryInterface(IUniformResourceLocatorW *url, REFIID riid, PVOID *ppvObject)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
- TRACE("(%p, %s, %p)\n", url, debugstr_guid(riid), ppvObject);
- return Unknown_QueryInterface(This, riid, ppvObject);
-}
-
-static ULONG WINAPI UniformResourceLocatorW_AddRef(IUniformResourceLocatorW *url)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
- TRACE("(%p)\n", url);
- return Unknown_AddRef(This);
-}
-
-static ULONG WINAPI UniformResourceLocatorW_Release(IUniformResourceLocatorW *url)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
- TRACE("(%p)\n", url);
- return Unknown_Release(This);
-}
-
-static HRESULT WINAPI UniformResourceLocatorW_SetUrl(IUniformResourceLocatorW *url, LPCWSTR pcszURL, DWORD dwInFlags)
-{
- WCHAR *newURL = NULL;
- InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
- TRACE("(%p, %s, 0x%x)\n", url, debugstr_w(pcszURL), dwInFlags);
- if (dwInFlags != 0)
- FIXME("ignoring unsupported flags 0x%x\n", dwInFlags);
- if (pcszURL != NULL)
- {
- newURL = co_strdupW(pcszURL);
- if (newURL == NULL)
- return E_OUTOFMEMORY;
- }
- CoTaskMemFree(This->url);
- This->url = newURL;
- This->isDirty = TRUE;
- return S_OK;
-}
-
-static HRESULT WINAPI UniformResourceLocatorW_GetUrl(IUniformResourceLocatorW *url, LPWSTR *ppszURL)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
-
- TRACE("(%p, %p)\n", url, ppszURL);
-
- if (!This->url) {
- *ppszURL = NULL;
- return S_FALSE;
- }
-
- *ppszURL = co_strdupW(This->url);
- if (!*ppszURL)
- return E_OUTOFMEMORY;
-
- return S_OK;
-}
-
-static HRESULT WINAPI UniformResourceLocatorW_InvokeCommand(IUniformResourceLocatorW *url, PURLINVOKECOMMANDINFOW pCommandInfo)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorW(url);
- WCHAR app[64];
- HKEY hkey;
- static const WCHAR wszURLProtocol[] = {'U','R','L',' ','P','r','o','t','o','c','o','l',0};
- SHELLEXECUTEINFOW sei;
- DWORD res, type;
- HRESULT hres;
-
- TRACE("%p %p\n", This, pCommandInfo );
-
- if (pCommandInfo->dwcbSize < sizeof (URLINVOKECOMMANDINFOW))
- return E_INVALIDARG;
-
- if (pCommandInfo->dwFlags != IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB)
- {
- FIXME("(%p, %p): non-default verbs not implemented\n", url, pCommandInfo);
- return E_NOTIMPL;
- }
-
- hres = CoInternetParseUrl(This->url, PARSE_SCHEMA, 0, app, sizeof(app)/sizeof(WCHAR), NULL, 0);
- if(FAILED(hres))
- return E_FAIL;
-
- res = RegOpenKeyW(HKEY_CLASSES_ROOT, app, &hkey);
- if(res != ERROR_SUCCESS)
- return E_FAIL;
-
- res = RegQueryValueExW(hkey, wszURLProtocol, NULL, &type, NULL, NULL);
- RegCloseKey(hkey);
- if(res != ERROR_SUCCESS || type != REG_SZ)
- return E_FAIL;
-
- memset(&sei, 0, sizeof(sei));
- sei.cbSize = sizeof(sei);
- sei.lpFile = This->url;
- sei.nShow = SW_SHOW;
-
- if( ShellExecuteExW(&sei) )
- return S_OK;
- else
- return E_FAIL;
-}
-
-static HRESULT WINAPI UniformResourceLocatorA_QueryInterface(IUniformResourceLocatorA *url, REFIID riid, PVOID *ppvObject)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
- TRACE("(%p, %s, %p)\n", url, debugstr_guid(riid), ppvObject);
- return Unknown_QueryInterface(This, riid, ppvObject);
-}
-
-static ULONG WINAPI UniformResourceLocatorA_AddRef(IUniformResourceLocatorA *url)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
- TRACE("(%p)\n", url);
- return Unknown_AddRef(This);
-}
-
-static ULONG WINAPI UniformResourceLocatorA_Release(IUniformResourceLocatorA *url)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
- TRACE("(%p)\n", url);
- return Unknown_Release(This);
-}
-
-static HRESULT WINAPI UniformResourceLocatorA_SetUrl(IUniformResourceLocatorA *url, LPCSTR pcszURL, DWORD dwInFlags)
-{
- WCHAR *newURL = NULL;
- InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
- TRACE("(%p, %s, 0x%x)\n", url, debugstr_a(pcszURL), dwInFlags);
- if (dwInFlags != 0)
- FIXME("ignoring unsupported flags 0x%x\n", dwInFlags);
- if (pcszURL != NULL)
- {
- newURL = co_strdupAtoW(pcszURL);
- if (newURL == NULL)
- return E_OUTOFMEMORY;
- }
- CoTaskMemFree(This->url);
- This->url = newURL;
- This->isDirty = TRUE;
- return S_OK;
-}
-
-static HRESULT WINAPI UniformResourceLocatorA_GetUrl(IUniformResourceLocatorA *url, LPSTR *ppszURL)
-{
- InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
-
- TRACE("(%p, %p)\n", url, ppszURL);
-
- if (!This->url) {
- *ppszURL = NULL;
- return S_FALSE;
-
- }
-
- *ppszURL = co_strdupWtoA(This->url);
- if (!*ppszURL)
- return E_OUTOFMEMORY;
-
- return S_OK;
-}
-
-static HRESULT WINAPI UniformResourceLocatorA_InvokeCommand(IUniformResourceLocatorA *url, PURLINVOKECOMMANDINFOA pCommandInfo)
-{
- URLINVOKECOMMANDINFOW wideCommandInfo;
- int len;
- WCHAR *wideVerb;
- HRESULT res;
- InternetShortcut *This = impl_from_IUniformResourceLocatorA(url);
-
- wideCommandInfo.dwcbSize = sizeof wideCommandInfo;
- wideCommandInfo.dwFlags = pCommandInfo->dwFlags;
- wideCommandInfo.hwndParent = pCommandInfo->hwndParent;
-
- len = MultiByteToWideChar(CP_ACP, 0, pCommandInfo->pcszVerb, -1, NULL, 0);
- wideVerb = heap_alloc(len * sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, pCommandInfo->pcszVerb, -1, wideVerb, len);
-
- wideCommandInfo.pcszVerb = wideVerb;
-
- res = UniformResourceLocatorW_InvokeCommand(&This->IUniformResourceLocatorW_iface, &wideCommandInfo);
- heap_free(wideVerb);
-
- return res;
-}
-
-static HRESULT WINAPI PersistFile_QueryInterface(IPersistFile *pFile, REFIID riid, PVOID *ppvObject)
-{
- InternetShortcut *This = impl_from_IPersistFile(pFile);
- TRACE("(%p, %s, %p)\n", pFile, debugstr_guid(riid), ppvObject);
- return Unknown_QueryInterface(This, riid, ppvObject);
-}
-
-static ULONG WINAPI PersistFile_AddRef(IPersistFile *pFile)
-{
- InternetShortcut *This = impl_from_IPersistFile(pFile);
- TRACE("(%p)\n", pFile);
- return Unknown_AddRef(This);
-}
-
-static ULONG WINAPI PersistFile_Release(IPersistFile *pFile)
-{
- InternetShortcut *This = impl_from_IPersistFile(pFile);
- TRACE("(%p)\n", pFile);
- return Unknown_Release(This);
-}
-
-static HRESULT WINAPI PersistFile_GetClassID(IPersistFile *pFile, CLSID *pClassID)
-{
- TRACE("(%p, %p)\n", pFile, pClassID);
- *pClassID = CLSID_InternetShortcut;
- return S_OK;
-}
-
-static HRESULT WINAPI PersistFile_IsDirty(IPersistFile *pFile)
-{
- InternetShortcut *This = impl_from_IPersistFile(pFile);
- TRACE("(%p)\n", pFile);
- return This->isDirty ? S_OK : S_FALSE;
-}
-
-/* Returns allocated profile string and a standard return code. */
-static HRESULT get_profile_string(LPCWSTR lpAppName, LPCWSTR lpKeyName,
- LPCWSTR lpFileName, WCHAR **rString )
-{
- DWORD r = 0;
- DWORD len = 128;
- WCHAR *buffer;
-
- *rString = NULL;
- buffer = CoTaskMemAlloc(len * sizeof(*buffer));
- if (!buffer)
- return E_OUTOFMEMORY;
-
- r = GetPrivateProfileStringW(lpAppName, lpKeyName, NULL, buffer, len, lpFileName);
- while (r == len-1)
- {
- WCHAR *realloc_buf;
-
- len *= 2;
- realloc_buf = CoTaskMemRealloc(buffer, len * sizeof(*buffer));
- if (realloc_buf == NULL)
- {
- CoTaskMemFree(buffer);
- return E_OUTOFMEMORY;
- }
- buffer = realloc_buf;
-
- r = GetPrivateProfileStringW(lpAppName, lpKeyName, NULL, buffer, len, lpFileName);
- }
-
- *rString = buffer;
- return r ? S_OK : E_FAIL;
-}
-
-static HRESULT WINAPI PersistFile_Load(IPersistFile *pFile, LPCOLESTR pszFileName, DWORD dwMode)
-{
- InternetShortcut *This = impl_from_IPersistFile(pFile);
- static WCHAR str_header[] = {'I','n','t','e','r','n','e','t','S','h','o','r','t','c','u','t',0};
- static WCHAR str_URL[] = {'U','R','L',0};
- static WCHAR str_iconfile[] = {'i','c','o','n','f','i','l','e',0};
- static WCHAR str_iconindex[] = {'i','c','o','n','i','n','d','e','x',0};
- WCHAR *filename = NULL;
- WCHAR *url;
- HRESULT hr;
- IPropertyStorage *pPropStg;
- WCHAR *iconfile;
- WCHAR *iconindexstring;
-
- TRACE("(%p, %s, 0x%x)\n", pFile, debugstr_w(pszFileName), dwMode);
-
- if (dwMode != 0)
- FIXME("ignoring unimplemented mode 0x%x\n", dwMode);
-
- filename = co_strdupW(pszFileName);
- if (!filename)
- return E_OUTOFMEMORY;
-
- if (FAILED(hr = get_profile_string(str_header, str_URL, pszFileName, &url)))
- {
- CoTaskMemFree(filename);
- return hr;
- }
-
- hr = IPropertySetStorage_Open(This->property_set_storage, &FMTID_Intshcut,
- STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &pPropStg);
- if (FAILED(hr))
- {
- CoTaskMemFree(filename);
- CoTaskMemFree(url);
- return hr;
- }
-
- CoTaskMemFree(This->currentFile);
- This->currentFile = filename;
- CoTaskMemFree(This->url);
- This->url = url;
- This->isDirty = FALSE;
-
- /* Now we're going to read in the iconfile and iconindex.
- If we don't find them, that's not a failure case -- it's possible
- that they just aren't in there. */
-
- if (get_profile_string(str_header, str_iconfile, pszFileName, &iconfile) == S_OK)
- {
- PROPSPEC ps;
- PROPVARIANT pv;
- ps.ulKind = PRSPEC_PROPID;
- ps.u.propid = PID_IS_ICONFILE;
- pv.vt = VT_LPWSTR;
- pv.u.pwszVal = iconfile;
- hr = IPropertyStorage_WriteMultiple(pPropStg, 1, &ps, &pv, 0);
- if (FAILED(hr))
- TRACE("Failed to store the iconfile to our property storage. hr = 0x%x\n", hr);
- }
- CoTaskMemFree(iconfile);
-
- if (get_profile_string(str_header, str_iconindex, pszFileName, &iconindexstring) == S_OK)
- {
- int iconindex;
- PROPSPEC ps;
- PROPVARIANT pv;
- iconindex = strtolW(iconindexstring, NULL, 10);
- ps.ulKind = PRSPEC_PROPID;
- ps.u.propid = PID_IS_ICONINDEX;
- pv.vt = VT_I4;
- pv.u.iVal = iconindex;
- hr = IPropertyStorage_WriteMultiple(pPropStg, 1, &ps, &pv, 0);
- if (FAILED(hr))
- TRACE("Failed to store the iconindex to our property storage. hr = 0x%x\n", hr);
- }
- CoTaskMemFree(iconindexstring);
-
- IPropertyStorage_Release(pPropStg);
- return hr;
-}
-
-static HRESULT WINAPI PersistFile_Save(IPersistFile *pFile, LPCOLESTR pszFileName, BOOL fRemember)
-{
- HRESULT hr = S_OK;
- INT len;
- CHAR *url;
- InternetShortcut *This = impl_from_IPersistFile(pFile);
-
- TRACE("(%p, %s, %d)\n", pFile, debugstr_w(pszFileName), fRemember);
-
- if (pszFileName != NULL && fRemember)
- {
- LPOLESTR oldFile = This->currentFile;
- This->currentFile = co_strdupW(pszFileName);
- if (This->currentFile == NULL)
- {
- This->currentFile = oldFile;
- return E_OUTOFMEMORY;
- }
- CoTaskMemFree(oldFile);
- }
- if (This->url == NULL)
- return E_FAIL;
-
- /* Windows seems to always write:
- * ASCII "[InternetShortcut]" headers
- * ASCII names in "name=value" pairs
- * An ASCII (probably UTF8?) value in "URL=..."
- */
- len = WideCharToMultiByte(CP_UTF8, 0, This->url, -1, NULL, 0, 0, 0);
- url = heap_alloc(len);
- if (url != NULL)
- {
- HANDLE file;
- WideCharToMultiByte(CP_UTF8, 0, This->url, -1, url, len, 0, 0);
- file = CreateFileW(pszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if (file != INVALID_HANDLE_VALUE)
- {
- DWORD bytesWritten;
- char *iconfile;
- char str_header[] = "[InternetShortcut]";
- char str_URL[] = "URL=";
- char str_ICONFILE[] = "ICONFILE=";
- char str_eol[] = "\r\n";
- IPropertyStorage *pPropStgRead;
- PROPSPEC ps[2];
- PROPVARIANT pvread[2];
- ps[0].ulKind = PRSPEC_PROPID;
- ps[0].u.propid = PID_IS_ICONFILE;
- ps[1].ulKind = PRSPEC_PROPID;
- ps[1].u.propid = PID_IS_ICONINDEX;
-
- WriteFile(file, str_header, lstrlenA(str_header), &bytesWritten, NULL);
- WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL);
- WriteFile(file, str_URL, lstrlenA(str_URL), &bytesWritten, NULL);
- WriteFile(file, url, lstrlenA(url), &bytesWritten, NULL);
- WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL);
-
- hr = IPropertySetStorage_Open(This->property_set_storage, &FMTID_Intshcut, STGM_READ|STGM_SHARE_EXCLUSIVE, &pPropStgRead);
- if (SUCCEEDED(hr))
- {
- hr = IPropertyStorage_ReadMultiple(pPropStgRead, 2, ps, pvread);
- if (hr == S_FALSE)
- {
- /* None of the properties are present, that's ok */
- hr = S_OK;
- IPropertyStorage_Release(pPropStgRead);
- }
- else if (SUCCEEDED(hr))
- {
- char indexString[50];
- len = WideCharToMultiByte(CP_UTF8, 0, pvread[0].u.pwszVal, -1, NULL, 0, 0, 0);
- iconfile = heap_alloc(len);
- if (iconfile != NULL)
- {
- WideCharToMultiByte(CP_UTF8, 0, pvread[0].u.pwszVal, -1, iconfile, len, 0, 0);
- WriteFile(file, str_ICONFILE, lstrlenA(str_ICONFILE), &bytesWritten, NULL);
- WriteFile(file, iconfile, lstrlenA(iconfile), &bytesWritten, NULL);
- WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL);
- }
-
- sprintf(indexString, "ICONINDEX=%d", pvread[1].u.iVal);
- WriteFile(file, indexString, lstrlenA(indexString), &bytesWritten, NULL);
- WriteFile(file, str_eol, lstrlenA(str_eol), &bytesWritten, NULL);
-
- IPropertyStorage_Release(pPropStgRead);
- PropVariantClear(&pvread[0]);
- PropVariantClear(&pvread[1]);
- }
- else
- {
- TRACE("Unable to read properties.\n");
- }
- }
- else
- {
- TRACE("Unable to get the IPropertyStorage.\n");
- }
-
- CloseHandle(file);
- if (pszFileName == NULL || fRemember)
- This->isDirty = FALSE;
- StartLinkProcessor(pszFileName);
- }
- else
- hr = E_FAIL;
- heap_free(url);
- }
- else
- hr = E_OUTOFMEMORY;
-
- return hr;
-}
-
-static HRESULT WINAPI PersistFile_SaveCompleted(IPersistFile *pFile, LPCOLESTR pszFileName)
-{
- FIXME("(%p, %p): stub\n", pFile, pszFileName);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI PersistFile_GetCurFile(IPersistFile *pFile, LPOLESTR *ppszFileName)
-{
- HRESULT hr = S_OK;
- InternetShortcut *This = impl_from_IPersistFile(pFile);
- TRACE("(%p, %p)\n", pFile, ppszFileName);
- if (This->currentFile == NULL)
- *ppszFileName = NULL;
- else
- {
- *ppszFileName = co_strdupW(This->currentFile);
- if (*ppszFileName == NULL)
- hr = E_OUTOFMEMORY;
- }
- return hr;
-}
-
-static HRESULT WINAPI PropertySetStorage_QueryInterface(IPropertySetStorage *iface, REFIID riid, PVOID *ppvObject)
-{
- InternetShortcut *This = impl_from_IPropertySetStorage(iface);
- TRACE("(%p)\n", iface);
- return Unknown_QueryInterface(This, riid, ppvObject);
-}
-
-static ULONG WINAPI PropertySetStorage_AddRef(IPropertySetStorage *iface)
-{
- InternetShortcut *This = impl_from_IPropertySetStorage(iface);
- TRACE("(%p)\n", iface);
- return Unknown_AddRef(This);
-}
-
-static ULONG WINAPI PropertySetStorage_Release(IPropertySetStorage *iface)
-{
- InternetShortcut *This = impl_from_IPropertySetStorage(iface);
- TRACE("(%p)\n", iface);
- return Unknown_Release(This);
-}
-
-static HRESULT WINAPI PropertySetStorage_Create(
- IPropertySetStorage* iface,
- REFFMTID rfmtid,
- const CLSID *pclsid,
- DWORD grfFlags,
- DWORD grfMode,
- IPropertyStorage **ppprstg)
-{
- InternetShortcut *This = impl_from_IPropertySetStorage(iface);
- TRACE("(%s, %p, 0x%x, 0x%x, %p)\n", debugstr_guid(rfmtid), pclsid, grfFlags, grfMode, ppprstg);
-
- return IPropertySetStorage_Create(This->property_set_storage,
- rfmtid,
- pclsid,
- grfFlags,
- grfMode,
- ppprstg);
-}
-
-static HRESULT WINAPI PropertySetStorage_Open(
- IPropertySetStorage* iface,
- REFFMTID rfmtid,
- DWORD grfMode,
- IPropertyStorage **ppprstg)
-{
- InternetShortcut *This = impl_from_IPropertySetStorage(iface);
- TRACE("(%s, 0x%x, %p)\n", debugstr_guid(rfmtid), grfMode, ppprstg);
-
- /* Note: The |STGM_SHARE_EXCLUSIVE is to cope with a bug in the implementation. Should be fixed in ole32. */
- return IPropertySetStorage_Open(This->property_set_storage,
- rfmtid,
- grfMode|STGM_SHARE_EXCLUSIVE,
- ppprstg);
-}
-
-static HRESULT WINAPI PropertySetStorage_Delete(IPropertySetStorage *iface, REFFMTID rfmtid)
-{
- InternetShortcut *This = impl_from_IPropertySetStorage(iface);
- TRACE("(%s)\n", debugstr_guid(rfmtid));
-
-
- return IPropertySetStorage_Delete(This->property_set_storage,
- rfmtid);
-}
-
-static HRESULT WINAPI PropertySetStorage_Enum(IPropertySetStorage *iface, IEnumSTATPROPSETSTG **ppenum)
-{
- FIXME("(%p): stub\n", ppenum);
- return E_NOTIMPL;
-}
-
-static const IUniformResourceLocatorWVtbl uniformResourceLocatorWVtbl = {
- UniformResourceLocatorW_QueryInterface,
- UniformResourceLocatorW_AddRef,
- UniformResourceLocatorW_Release,
- UniformResourceLocatorW_SetUrl,
- UniformResourceLocatorW_GetUrl,
- UniformResourceLocatorW_InvokeCommand
-};
-
-static const IUniformResourceLocatorAVtbl uniformResourceLocatorAVtbl = {
- UniformResourceLocatorA_QueryInterface,
- UniformResourceLocatorA_AddRef,
- UniformResourceLocatorA_Release,
- UniformResourceLocatorA_SetUrl,
- UniformResourceLocatorA_GetUrl,
- UniformResourceLocatorA_InvokeCommand
-};
-
-static const IPersistFileVtbl persistFileVtbl = {
- PersistFile_QueryInterface,
- PersistFile_AddRef,
- PersistFile_Release,
- PersistFile_GetClassID,
- PersistFile_IsDirty,
- PersistFile_Load,
- PersistFile_Save,
- PersistFile_SaveCompleted,
- PersistFile_GetCurFile
-};
-
-static const IPropertySetStorageVtbl propertySetStorageVtbl = {
- PropertySetStorage_QueryInterface,
- PropertySetStorage_AddRef,
- PropertySetStorage_Release,
- PropertySetStorage_Create,
- PropertySetStorage_Open,
- PropertySetStorage_Delete,
- PropertySetStorage_Enum
-};
-
-static InternetShortcut *create_shortcut(void)
-{
- InternetShortcut *newshortcut;
-
- newshortcut = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(InternetShortcut));
- if (newshortcut)
- {
- HRESULT hr;
- IPropertyStorage *dummy;
-
- newshortcut->IUniformResourceLocatorA_iface.lpVtbl = &uniformResourceLocatorAVtbl;
- newshortcut->IUniformResourceLocatorW_iface.lpVtbl = &uniformResourceLocatorWVtbl;
- newshortcut->IPersistFile_iface.lpVtbl = &persistFileVtbl;
- newshortcut->IPropertySetStorage_iface.lpVtbl = &propertySetStorageVtbl;
- newshortcut->refCount = 1;
- hr = StgCreateStorageEx(NULL, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE | STGM_DELETEONRELEASE,
- STGFMT_STORAGE, 0, NULL, NULL, &IID_IPropertySetStorage, (void **) &newshortcut->property_set_storage);
- if (FAILED(hr))
- {
- TRACE("Failed to create the storage object needed for the shortcut.\n");
- heap_free(newshortcut);
- return NULL;
- }
-
- hr = IPropertySetStorage_Create(newshortcut->property_set_storage, &FMTID_Intshcut, NULL, PROPSETFLAG_DEFAULT, STGM_CREATE | STGM_READWRITE | STGM_SHARE_EXCLUSIVE, &dummy);
- if (FAILED(hr))
- {
- TRACE("Failed to create the property object needed for the shortcut.\n");
- IPropertySetStorage_Release(newshortcut->property_set_storage);
- heap_free(newshortcut);
- return NULL;
- }
- IPropertyStorage_Release(dummy);
- }
-
- return newshortcut;
-}
-
-HRESULT WINAPI InternetShortcut_Create(IClassFactory *iface, IUnknown *outer, REFIID riid, void **ppv)
-{
- InternetShortcut *This;
- HRESULT hres;
-
- TRACE("(%p, %s, %p)\n", outer, debugstr_guid(riid), ppv);
-
- *ppv = NULL;
-
- if(outer)
- return CLASS_E_NOAGGREGATION;
-
- This = create_shortcut();
- if(!This)
- return E_OUTOFMEMORY;
-
- hres = Unknown_QueryInterface(This, riid, ppv);
- Unknown_Release(This);
- return hres;
-}
-
-
-/**********************************************************************
- * OpenURL (ieframe.@)
- */
-void WINAPI OpenURL(HWND hWnd, HINSTANCE hInst, LPCSTR lpcstrUrl, int nShowCmd)
-{
- InternetShortcut *shortcut;
- WCHAR* urlfilepath = NULL;
- int len;
-
- shortcut = create_shortcut();
-
- if(!shortcut)
- return;
-
- len = MultiByteToWideChar(CP_ACP, 0, lpcstrUrl, -1, NULL, 0);
- urlfilepath = heap_alloc(len * sizeof(WCHAR));
- MultiByteToWideChar(CP_ACP, 0, lpcstrUrl, -1, urlfilepath, len);
-
- if(SUCCEEDED(IPersistFile_Load(&shortcut->IPersistFile_iface, urlfilepath, 0))) {
- URLINVOKECOMMANDINFOW ici;
-
- memset( &ici, 0, sizeof ici );
- ici.dwcbSize = sizeof ici;
- ici.dwFlags = IURL_INVOKECOMMAND_FL_USE_DEFAULT_VERB;
- ici.hwndParent = hWnd;
-
- if(FAILED(UniformResourceLocatorW_InvokeCommand(&shortcut->IUniformResourceLocatorW_iface, (PURLINVOKECOMMANDINFOW) &ici)))
- TRACE("failed to open URL: %s\n", debugstr_a(lpcstrUrl));
- }
-
- heap_free(urlfilepath);
- Unknown_Release(shortcut);
-}