Autosyncing with Wine HEAD

svn path=/trunk/; revision=31597
This commit is contained in:
Hervé Poussineau 2008-01-04 21:53:35 +00:00
parent 27f5377445
commit a2fb8f72ae
7 changed files with 1954 additions and 0 deletions

View file

@ -0,0 +1,270 @@
/*
* Implementation of hyperlinking (hlink.dll)
*
* Copyright 2005 Aric Stewart for CodeWeavers
*
* 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
*/
#include "hlink_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(hlink);
static const IHlinkBrowseContextVtbl hlvt;
typedef struct
{
const IHlinkBrowseContextVtbl *lpVtbl;
LONG ref;
HLBWINFO* BrowseWindowInfo;
IHlink* CurrentPage;
} HlinkBCImpl;
HRESULT WINAPI HLinkBrowseContext_Constructor(IUnknown *pUnkOuter, REFIID riid,
LPVOID *ppv)
{
HlinkBCImpl * hl;
TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
*ppv = NULL;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
hl = heap_alloc_zero(sizeof(HlinkBCImpl));
if (!hl)
return E_OUTOFMEMORY;
hl->ref = 1;
hl->lpVtbl = &hlvt;
*ppv = hl;
return S_OK;
}
static HRESULT WINAPI IHlinkBC_fnQueryInterface( IHlinkBrowseContext *iface,
REFIID riid, LPVOID* ppvObj)
{
HlinkBCImpl *This = (HlinkBCImpl*)iface;
TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IHlinkBrowseContext))
*ppvObj = This;
if (*ppvObj)
{
IUnknown_AddRef((IUnknown*)(*ppvObj));
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI IHlinkBC_fnAddRef (IHlinkBrowseContext* iface)
{
HlinkBCImpl *This = (HlinkBCImpl*)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(count=%u)\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI IHlinkBC_fnRelease (IHlinkBrowseContext* iface)
{
HlinkBCImpl *This = (HlinkBCImpl*)iface;
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(count=%u)\n", This, refCount + 1);
if (refCount)
return refCount;
TRACE("-- destroying IHlinkBrowseContext (%p)\n", This);
heap_free(This->BrowseWindowInfo);
if (This->CurrentPage)
IHlink_Release(This->CurrentPage);
heap_free(This);
return 0;
}
static HRESULT WINAPI IHlinkBC_Register(IHlinkBrowseContext* iface,
DWORD dwReserved, IUnknown *piunk, IMoniker *pimk, DWORD *pdwRegister)
{
static const WCHAR szIdent[] = {'W','I','N','E','H','L','I','N','K',0};
HlinkBCImpl *This = (HlinkBCImpl*)iface;
IMoniker *mon;
IMoniker *composite;
IRunningObjectTable *ROT;
FIXME("(%p)->(%i %p %p %p)\n", This, dwReserved, piunk, pimk, pdwRegister);
CreateItemMoniker(NULL, szIdent, &mon);
CreateGenericComposite(mon, pimk, &composite);
GetRunningObjectTable(0, &ROT);
IRunningObjectTable_Register(ROT, 0, piunk, composite, pdwRegister);
IRunningObjectTable_Release(ROT);
IMoniker_Release(composite);
IMoniker_Release(mon);
return S_OK;
}
static HRESULT WINAPI IHlinkBC_GetObject(IHlinkBrowseContext* face,
IMoniker *pimk, BOOL fBindifRootRegistered, IUnknown **ppiunk)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_Revoke(IHlinkBrowseContext* iface,
DWORD dwRegister)
{
HRESULT r = S_OK;
IRunningObjectTable *ROT;
HlinkBCImpl *This = (HlinkBCImpl*)iface;
FIXME("(%p)->(%i)\n", This, dwRegister);
GetRunningObjectTable(0, &ROT);
r = IRunningObjectTable_Revoke(ROT, dwRegister);
IRunningObjectTable_Release(ROT);
return r;
}
static HRESULT WINAPI IHlinkBC_SetBrowseWindowInfo(IHlinkBrowseContext* iface,
HLBWINFO *phlbwi)
{
HlinkBCImpl *This = (HlinkBCImpl*)iface;
TRACE("(%p)->(%p)\n", This, phlbwi);
heap_free(This->BrowseWindowInfo);
This->BrowseWindowInfo = heap_alloc(phlbwi->cbSize);
memcpy(This->BrowseWindowInfo, phlbwi, phlbwi->cbSize);
return S_OK;
}
static HRESULT WINAPI IHlinkBC_GetBrowseWindowInfo(IHlinkBrowseContext* iface,
HLBWINFO *phlbwi)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_SetInitialHlink(IHlinkBrowseContext* iface,
IMoniker *pimkTarget, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
{
HlinkBCImpl *This = (HlinkBCImpl*)iface;
FIXME("(%p)->(%p %s %s)\n", This, pimkTarget,
debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName));
if (This->CurrentPage)
IHlink_Release(This->CurrentPage);
HlinkCreateFromMoniker(pimkTarget, pwzLocation, pwzFriendlyName, NULL,
0, NULL, &IID_IHlink, (LPVOID*) &This->CurrentPage);
return S_OK;
}
static HRESULT WINAPI IHlinkBC_OnNavigateHlink(IHlinkBrowseContext *iface,
DWORD grfHLNF, IMoniker* pmkTarget, LPCWSTR pwzLocation, LPCWSTR
pwzFriendlyName, ULONG *puHLID)
{
HlinkBCImpl *This = (HlinkBCImpl*)iface;
FIXME("(%p)->(%i %p %s %s %p)\n", This, grfHLNF, pmkTarget,
debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), puHLID);
return S_OK;
}
static HRESULT WINAPI IHlinkBC_UpdateHlink(IHlinkBrowseContext* iface,
ULONG uHLID, IMoniker* pimkTarget, LPCWSTR pwzLocation,
LPCWSTR pwzFriendlyName)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_EnumNavigationStack( IHlinkBrowseContext *iface,
DWORD dwReserved, DWORD grfHLFNAMEF, IEnumHLITEM** ppienumhlitem)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_QueryHlink( IHlinkBrowseContext* iface,
DWORD grfHLONG, ULONG uHLID)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_GetHlink( IHlinkBrowseContext* iface,
ULONG uHLID, IHlink** ppihl)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_SetCurrentHlink( IHlinkBrowseContext* iface,
ULONG uHLID)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_Clone( IHlinkBrowseContext* iface,
IUnknown* piunkOuter, REFIID riid, IUnknown** ppiunkOjb)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlinkBC_Close(IHlinkBrowseContext* iface,
DWORD reserverd)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IHlinkBrowseContextVtbl hlvt =
{
IHlinkBC_fnQueryInterface,
IHlinkBC_fnAddRef,
IHlinkBC_fnRelease,
IHlinkBC_Register,
IHlinkBC_GetObject,
IHlinkBC_Revoke,
IHlinkBC_SetBrowseWindowInfo,
IHlinkBC_GetBrowseWindowInfo,
IHlinkBC_SetInitialHlink,
IHlinkBC_OnNavigateHlink,
IHlinkBC_UpdateHlink,
IHlinkBC_EnumNavigationStack,
IHlinkBC_QueryHlink,
IHlinkBC_GetHlink,
IHlinkBC_SetCurrentHlink,
IHlinkBC_Clone,
IHlinkBC_Close
};

View file

@ -0,0 +1,259 @@
/*
* Copyright 2007 Jacek Caban for CodeWeavers
*
* 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
*/
#include "hlink_private.h"
#include "wine/debug.h"
#include "wine/unicode.h"
WINE_DEFAULT_DEBUG_CHANNEL(hlink);
#define DEFINE_THIS(cls,ifc,iface) ((cls*)((BYTE*)(iface)-offsetof(cls,lp ## ifc ## Vtbl)))
typedef struct {
const IUnknownVtbl *lpIUnknownVtbl;
const IAuthenticateVtbl *lpIAuthenticateVtbl;
const IHttpNegotiateVtbl *lpIHttpNegotiateVtbl;
LONG ref;
IUnknown *outer;
HWND hwnd;
LPWSTR username;
LPWSTR password;
LPWSTR headers;
} ExtensionService;
#define EXTSERVUNK(x) ((IUnknown*) &(x)->lpIUnknownVtbl)
#define AUTHENTICATE(x) ((IAuthenticate*) &(x)->lpIAuthenticateVtbl)
#define HTTPNEGOTIATE(x) ((IHttpNegotiate*) &(x)->lpIHttpNegotiateVtbl)
#define EXTSERVUNK_THIS(iface) DEFINE_THIS(ExtensionService, IUnknown, iface)
static HRESULT WINAPI ExtServUnk_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
{
ExtensionService *This = EXTSERVUNK_THIS(iface);
*ppv = NULL;
if(IsEqualGUID(&IID_IUnknown, riid)) {
TRACE("(%p)->(IID_IUnknown %p)\n", This, ppv);
*ppv = EXTSERVUNK(This);
}else if(IsEqualGUID(&IID_IAuthenticate, riid)) {
TRACE("(%p)->(IID_IAuthenticate %p)\n", This, ppv);
*ppv = AUTHENTICATE(This);
}else if(IsEqualGUID(&IID_IHttpNegotiate, riid)) {
TRACE("(%p)->(IID_IHttpNegotiate %p)\n", This, ppv);
*ppv = HTTPNEGOTIATE(This);
}
if(*ppv) {
IUnknown_AddRef(EXTSERVUNK(This));
return S_OK;
}
FIXME("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
return E_NOINTERFACE;
}
static ULONG WINAPI ExtServUnk_AddRef(IUnknown *iface)
{
ExtensionService *This = EXTSERVUNK_THIS(iface);
LONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
return ref;
}
static ULONG WINAPI ExtServUnk_Release(IUnknown *iface)
{
ExtensionService *This = EXTSERVUNK_THIS(iface);
LONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p) ref=%d\n", This, ref);
if(!ref) {
heap_free(This->username);
heap_free(This->password);
heap_free(This->headers);
heap_free(This);
}
return ref;
}
#undef EXTSERVUNK_THIS
static const IUnknownVtbl ExtServUnkVtbl = {
ExtServUnk_QueryInterface,
ExtServUnk_AddRef,
ExtServUnk_Release
};
#define AUTHENTICATE_THIS(iface) DEFINE_THIS(ExtensionService, IAuthenticate, iface)
static HRESULT WINAPI Authenticate_QueryInterface(IAuthenticate *iface, REFIID riid, void **ppv)
{
ExtensionService *This = AUTHENTICATE_THIS(iface);
return IUnknown_QueryInterface(This->outer, riid, ppv);
}
static ULONG WINAPI Authenticate_AddRef(IAuthenticate *iface)
{
ExtensionService *This = AUTHENTICATE_THIS(iface);
return IUnknown_AddRef(This->outer);
}
static ULONG WINAPI Authenticate_Release(IAuthenticate *iface)
{
ExtensionService *This = AUTHENTICATE_THIS(iface);
return IUnknown_Release(This->outer);
}
static HRESULT WINAPI Authenticate_Authenticate(IAuthenticate *iface,
HWND *phwnd, LPWSTR *pszUsername, LPWSTR *pszPassword)
{
ExtensionService *This = AUTHENTICATE_THIS(iface);
TRACE("(%p)->(%p %p %p)\n", This, phwnd, pszUsername, pszPassword);
if(!phwnd || !pszUsername || !pszPassword)
return E_INVALIDARG;
*phwnd = This->hwnd;
*pszUsername = hlink_co_strdupW(This->username);
*pszPassword = hlink_co_strdupW(This->password);
return S_OK;
}
#undef AUTHENTICATE_THIS
static const IAuthenticateVtbl AuthenticateVtbl = {
Authenticate_QueryInterface,
Authenticate_AddRef,
Authenticate_Release,
Authenticate_Authenticate
};
#define HTTPNEGOTIATE_THIS(iface) DEFINE_THIS(ExtensionService, IHttpNegotiate, iface)
static HRESULT WINAPI HttpNegotiate_QueryInterface(IHttpNegotiate *iface, REFIID riid, void **ppv)
{
ExtensionService *This = HTTPNEGOTIATE_THIS(iface);
return IUnknown_QueryInterface(This->outer, riid, ppv);
}
static ULONG WINAPI HttpNegotiate_AddRef(IHttpNegotiate *iface)
{
ExtensionService *This = HTTPNEGOTIATE_THIS(iface);
return IUnknown_AddRef(This->outer);
}
static ULONG WINAPI HttpNegotiate_Release(IHttpNegotiate *iface)
{
ExtensionService *This = HTTPNEGOTIATE_THIS(iface);
return IUnknown_Release(This->outer);
}
static HRESULT WINAPI HttpNegotiate_BeginningTransaction(IHttpNegotiate *iface,
LPCWSTR szURL, LPCWSTR szHeaders, DWORD dwReserved, LPWSTR *pszAdditionalHeaders)
{
ExtensionService *This = HTTPNEGOTIATE_THIS(iface);
TRACE("(%p)->(%s %s %x %p)\n", This, debugstr_w(szURL), debugstr_w(szHeaders), dwReserved,
pszAdditionalHeaders);
if(!pszAdditionalHeaders)
return E_INVALIDARG;
*pszAdditionalHeaders = hlink_co_strdupW(This->headers);
return S_OK;
}
static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD dwResponseCode,
LPCWSTR szResponseHeaders, LPCWSTR szRequestHeaders, LPWSTR *pszAdditionalRequestHeaders)
{
ExtensionService *This = HTTPNEGOTIATE_THIS(iface);
TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders),
debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
*pszAdditionalRequestHeaders = NULL;
return S_OK;
}
#undef HTTPNEGOTIATE_THIS
static const IHttpNegotiateVtbl HttpNegotiateVtbl = {
HttpNegotiate_QueryInterface,
HttpNegotiate_AddRef,
HttpNegotiate_Release,
HttpNegotiate_BeginningTransaction,
HttpNegotiate_OnResponse
};
HRESULT WINAPI HlinkCreateExtensionServices(LPCWSTR pwzAdditionalHeaders,
HWND phwnd, LPCWSTR pszUsername, LPCWSTR pszPassword,
IUnknown *punkOuter, REFIID riid, void** ppv)
{
ExtensionService *ret;
int len = 0;
HRESULT hres = S_OK;
TRACE("%s %p %s %s %p %s %p\n",debugstr_w(pwzAdditionalHeaders),
phwnd, debugstr_w(pszUsername), debugstr_w(pszPassword),
punkOuter, debugstr_guid(riid), ppv);
ret = heap_alloc(sizeof(*ret));
ret->lpIUnknownVtbl = &ExtServUnkVtbl;
ret->lpIAuthenticateVtbl = &AuthenticateVtbl;
ret->lpIHttpNegotiateVtbl = &HttpNegotiateVtbl;
ret->ref = 1;
ret->hwnd = phwnd;
ret->username = hlink_strdupW(pszUsername);
ret->password = hlink_strdupW(pszPassword);
if(pwzAdditionalHeaders)
len = strlenW(pwzAdditionalHeaders);
if(len && pwzAdditionalHeaders[len-1] != '\n' && pwzAdditionalHeaders[len-1] != '\r') {
static const WCHAR endlW[] = {'\r','\n',0};
ret->headers = heap_alloc(len*sizeof(WCHAR) + sizeof(endlW));
memcpy(ret->headers, pwzAdditionalHeaders, len*sizeof(WCHAR));
memcpy(ret->headers+len, endlW, sizeof(endlW));
}else {
ret->headers = hlink_strdupW(pwzAdditionalHeaders);
}
if(!punkOuter) {
ret->outer = EXTSERVUNK(ret);
hres = IUnknown_QueryInterface(EXTSERVUNK(ret), riid, ppv);
IUnknown_Release(EXTSERVUNK(ret));
}else if(IsEqualGUID(&IID_IUnknown, riid)) {
ret->outer = punkOuter;
*ppv = EXTSERVUNK(ret);
}else {
IUnknown_Release(EXTSERVUNK(ret));
hres = E_INVALIDARG;
}
return hres;
}

View file

@ -0,0 +1,24 @@
<?xml version="1.0"?>
<!DOCTYPE module SYSTEM "../../../tools/rbuild/project.dtd">
<module name="hlink" type="win32dll" baseaddress="${BASEADDRESS_HLINK}" installbase="system32" installname="hlink.dll" allowwarnings="true">
<autoregister infsection="OleControlDlls" type="DllRegisterServer" />
<importlibrary definition="hlink.spec.def" />
<include base="hlink">.</include>
<include base="ReactOS">include/reactos/wine</include>
<define name="__WINESRC__" />
<define name="WINVER">0x600</define>
<define name="_WIN32_WINNT">0x600</define>
<library>wine</library>
<library>shell32</library>
<library>ole32</library>
<library>advapi32</library>
<library>kernel32</library>
<library>urlmon</library>
<library>uuid</library>
<library>ntdll</library>
<file>browse_ctx.c</file>
<file>extserv.c</file>
<file>hlink_main.c</file>
<file>link.c</file>
<file>hlink.spec</file>
</module>

View file

@ -0,0 +1,33 @@
3 stdcall HlinkCreateFromMoniker(ptr wstr wstr ptr long ptr ptr ptr)
4 stdcall HlinkCreateFromString(wstr wstr wstr ptr long ptr ptr ptr)
5 stdcall HlinkCreateFromData(ptr ptr long ptr ptr ptr)
6 stdcall HlinkCreateBrowseContext(ptr ptr ptr)
7 stub HlinkClone
8 stdcall HlinkNavigateToStringReference(wstr wstr ptr long ptr long ptr ptr ptr)
9 stdcall HlinkOnNavigate(ptr ptr long ptr wstr wstr ptr)
10 stdcall HlinkNavigate(ptr ptr long ptr ptr ptr)
11 stdcall HlinkUpdateStackItem(ptr ptr long ptr wstr wstr)
12 stub HlinkOnRenameDocument
14 stub HlinkResolveMonikerForData
15 stub HlinkResolveStringForData
16 stub OleSaveToStreamEx
18 stub HlinkParseDisplayName
20 stdcall HlinkQueryCreateFromData(ptr)
21 stub HlinkSetSpecialReference
22 stdcall HlinkGetSpecialReference(long ptr)
23 stub HlinkCreateShortcut
24 stub HlinkResolveShortcut
25 stdcall HlinkIsShortcut(wstr)
26 stub HlinkResolveShortcutToString
27 stub HlinkCreateShortcutFromString
28 stub HlinkGetValueFromParams
29 stub HlinkCreateShortcutFromMoniker
30 stub HlinkResolveShortcutToMoniker
31 stdcall HlinkTranslateURL(wstr long ptr)
32 stdcall HlinkCreateExtensionServices(wstr long wstr wstr ptr ptr ptr)
33 stub HlinkPreprocessMoniker
@ stdcall -private DllCanUnloadNow()
@ stdcall -private DllGetClassObject(ptr ptr ptr)
@ stdcall -private DllRegisterServer()
# @ stub -private DllUnregisterServer

View file

@ -0,0 +1,447 @@
/*
* Implementation of hyperlinking (hlink.dll)
*
* Copyright 2005 Aric Stewart for CodeWeavers
*
* 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
*/
#include "hlink_private.h"
#include "winreg.h"
#include "hlguids.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(hlink);
typedef HRESULT (CALLBACK *LPFNCREATEINSTANCE)(IUnknown*, REFIID, LPVOID*);
typedef struct
{
const IClassFactoryVtbl *lpVtbl;
LPFNCREATEINSTANCE lpfnCI;
} CFImpl;
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
TRACE("%p %d %p\n", hinstDLL, fdwReason, lpvReserved);
switch (fdwReason)
{
case DLL_WINE_PREATTACH:
return FALSE; /* prefer native version */
case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL);
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
HRESULT WINAPI DllCanUnloadNow( void )
{
FIXME("\n");
return S_OK;
}
HRESULT WINAPI HlinkCreateFromMoniker( IMoniker *pimkTrgt, LPCWSTR pwzLocation,
LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData,
IUnknown* piunkOuter, REFIID riid, void** ppvObj)
{
IHlink *hl = NULL;
HRESULT r = S_OK;
TRACE("%p %s %s %p %i %p %s %p\n", pimkTrgt, debugstr_w(pwzLocation),
debugstr_w(pwzFriendlyName), pihlsite, dwSiteData, piunkOuter,
debugstr_guid(riid), ppvObj);
r = CoCreateInstance(&CLSID_StdHlink, piunkOuter, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&hl);
if (FAILED(r))
return r;
if (pwzLocation)
IHlink_SetStringReference(hl, HLINKSETF_LOCATION, NULL, pwzLocation);
if (pwzFriendlyName)
IHlink_SetFriendlyName(hl, pwzFriendlyName);
if (pihlsite)
IHlink_SetHlinkSite(hl, pihlsite, dwSiteData);
if (pimkTrgt)
IHlink_SetMonikerReference(hl, 0, pimkTrgt, pwzLocation);
*ppvObj = hl;
TRACE("Returning %i\n",r);
return r;
}
HRESULT WINAPI HlinkCreateFromString( LPCWSTR pwzTarget, LPCWSTR pwzLocation,
LPCWSTR pwzFriendlyName, IHlinkSite* pihlsite, DWORD dwSiteData,
IUnknown* piunkOuter, REFIID riid, void** ppvObj)
{
IHlink *hl = NULL;
HRESULT r = S_OK;
TRACE("%s %s %s %p %i %p %s %p\n", debugstr_w(pwzTarget),
debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), pihlsite,
dwSiteData, piunkOuter, debugstr_guid(riid), ppvObj);
r = CoCreateInstance(&CLSID_StdHlink, piunkOuter, CLSCTX_INPROC_SERVER, riid, (LPVOID*)&hl);
if (FAILED(r))
return r;
if (pwzLocation)
IHlink_SetStringReference(hl, HLINKSETF_LOCATION, NULL, pwzLocation);
if (pwzTarget)
{
IMoniker *pTgtMk = NULL;
IBindCtx *pbc = NULL;
ULONG eaten;
CreateBindCtx(0, &pbc);
r = MkParseDisplayName(pbc, pwzTarget, &eaten, &pTgtMk);
IBindCtx_Release(pbc);
if (FAILED(r))
{
LPCWSTR p = strchrW(pwzTarget, ':');
if (p && (p - pwzTarget > 1))
r = CreateURLMoniker(NULL, pwzTarget, &pTgtMk);
else
r = CreateFileMoniker(pwzTarget,&pTgtMk);
}
if (FAILED(r))
{
ERR("couldn't create moniker for %s, failed with error 0x%08x\n",
debugstr_w(pwzTarget), r);
return r;
}
IHlink_SetMonikerReference(hl, 0, pTgtMk, pwzLocation);
IMoniker_Release(pTgtMk);
IHlink_SetStringReference(hl, HLINKSETF_TARGET, pwzTarget, NULL);
}
if (pwzFriendlyName)
IHlink_SetFriendlyName(hl, pwzFriendlyName);
if (pihlsite)
IHlink_SetHlinkSite(hl, pihlsite, dwSiteData);
TRACE("Returning %i\n",r);
*ppvObj = hl;
return r;
}
HRESULT WINAPI HlinkCreateBrowseContext( IUnknown* piunkOuter, REFIID riid, void** ppvObj)
{
HRESULT r = S_OK;
TRACE("%p %s %p\n", piunkOuter, debugstr_guid(riid), ppvObj);
r = CoCreateInstance(&CLSID_StdHlinkBrowseContext, piunkOuter, CLSCTX_INPROC_SERVER, riid, ppvObj);
TRACE("returning %i\n",r);
return r;
}
HRESULT WINAPI HlinkNavigate(IHlink *phl, IHlinkFrame *phlFrame,
DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pbsc,
IHlinkBrowseContext *phlbc)
{
HRESULT r = S_OK;
TRACE("%p %p %i %p %p %p\n", phl, phlFrame, grfHLNF, pbc, pbsc, phlbc);
if (phlFrame)
r = IHlinkFrame_Navigate(phlFrame, grfHLNF, pbc, pbsc, phl);
else if (phl)
r = IHlink_Navigate(phl, grfHLNF, pbc, pbsc, phlbc);
return r;
}
HRESULT WINAPI HlinkOnNavigate( IHlinkFrame *phlFrame,
IHlinkBrowseContext* phlbc, DWORD grfHLNF, IMoniker *pmkTarget,
LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName, ULONG* puHLID)
{
HRESULT r = S_OK;
TRACE("%p %p %i %p %s %s %p\n",phlFrame, phlbc, grfHLNF, pmkTarget,
debugstr_w(pwzLocation), debugstr_w(pwzFriendlyName), puHLID);
r = IHlinkBrowseContext_OnNavigateHlink(phlbc, grfHLNF, pmkTarget,
pwzLocation, pwzFriendlyName, puHLID);
if (phlFrame)
r = IHlinkFrame_OnNavigate(phlFrame,grfHLNF,pmkTarget, pwzLocation,
pwzFriendlyName, 0);
return r;
}
HRESULT WINAPI HlinkCreateFromData(IDataObject *piDataObj,
IHlinkSite *pihlsite, DWORD dwSiteData, IUnknown *piunkOuter,
REFIID riid, void **ppvObj)
{
FIXME("%p %p %d %p %p %p\n",
piDataObj, pihlsite, dwSiteData, piunkOuter, riid, ppvObj);
*ppvObj = NULL;
return E_NOTIMPL;
}
HRESULT WINAPI HlinkQueryCreateFromData(IDataObject* piDataObj)
{
FIXME("%p\n", piDataObj);
return E_NOTIMPL;
}
HRESULT WINAPI HlinkNavigateToStringReference( LPCWSTR pwzTarget,
LPCWSTR pwzLocation, IHlinkSite *pihlsite, DWORD dwSiteData,
IHlinkFrame *pihlframe, DWORD grfHLNF, LPBC pibc,
IBindStatusCallback *pibsc, IHlinkBrowseContext *pihlbc)
{
HRESULT r;
IHlink *hlink = NULL;
FIXME("%s %s %p %08x %p %08x %p %p %p\n",
debugstr_w(pwzTarget), debugstr_w(pwzLocation), pihlsite,
dwSiteData, pihlframe, grfHLNF, pibc, pibsc, pihlbc);
r = HlinkCreateFromString( pwzTarget, pwzLocation, NULL, pihlsite,
dwSiteData, NULL, &IID_IHlink, (LPVOID*) &hlink );
if (SUCCEEDED(r))
r = HlinkNavigate(hlink, pihlframe, grfHLNF, pibc, pibsc, pihlbc);
return r;
}
HRESULT WINAPI HlinkIsShortcut(LPCWSTR pwzFileName)
{
int len;
static const WCHAR url_ext[] = {'.','u','r','l',0};
TRACE("(%s)\n", debugstr_w(pwzFileName));
if(!pwzFileName)
return E_INVALIDARG;
len = strlenW(pwzFileName)-4;
if(len < 0)
return S_FALSE;
return strcmpiW(pwzFileName+len, url_ext) ? S_FALSE : S_OK;
}
HRESULT WINAPI HlinkGetSpecialReference(ULONG uReference, LPWSTR *ppwzReference)
{
DWORD res, type, size = 100;
LPCWSTR value_name;
WCHAR *buf;
HKEY hkey;
static const WCHAR start_pageW[] = {'S','t','a','r','t',' ','P','a','g','e',0};
static const WCHAR search_pageW[] = {'S','e','a','r','c','h',' ','P','a','g','e',0};
static const WCHAR ie_main_keyW[] =
{'S','o','f','t','w','a','r','e',
'\\','M','i','c','r','o','s','o','f','t','\\',
'I','n','t','e','r','n','e','t',' ','E','x','p','l','o','r','e','r',
'\\','M','a','i','n',0};
TRACE("(%u %p)\n", uReference, ppwzReference);
*ppwzReference = NULL;
switch(uReference) {
case HLSR_HOME:
value_name = start_pageW;
break;
case HLSR_SEARCHPAGE:
value_name = search_pageW;
break;
case HLSR_HISTORYFOLDER:
return E_NOTIMPL;
default:
return E_INVALIDARG;
}
res = RegOpenKeyW(HKEY_CURRENT_USER, ie_main_keyW, &hkey);
if(res != ERROR_SUCCESS) {
WARN("Could not open key: %u\n", res);
return HRESULT_FROM_WIN32(res);
}
buf = CoTaskMemAlloc(size);
res = RegQueryValueExW(hkey, value_name, NULL, &type, (PBYTE)buf, &size);
buf = CoTaskMemRealloc(buf, size);
if(res == ERROR_MORE_DATA)
res = RegQueryValueExW(hkey, value_name, NULL, &type, (PBYTE)buf, &size);
RegCloseKey(hkey);
if(res != ERROR_SUCCESS) {
WARN("Could not query value %s: %u\n", debugstr_w(value_name), res);
CoTaskMemFree(buf);
return HRESULT_FROM_WIN32(res);
}
*ppwzReference = buf;
return S_OK;
}
HRESULT WINAPI HlinkTranslateURL(LPCWSTR pwzURL, DWORD grfFlags, LPWSTR *ppwzTranslatedURL)
{
FIXME("(%s %08x %p)\n", debugstr_w(pwzURL), grfFlags, ppwzTranslatedURL);
return E_NOTIMPL;
}
HRESULT WINAPI HlinkUpdateStackItem(IHlinkFrame *pihlframe, IHlinkBrowseContext *pihlbc,
ULONG uHLID, IMoniker *pimkTrgt, LPCWSTR pwzLocation, LPCWSTR pwzFriendlyName)
{
FIXME("(%p %p %u %p %s %s)\n", pihlframe, pihlbc, uHLID, pimkTrgt, debugstr_w(pwzLocation),
debugstr_w(pwzFriendlyName));
return E_NOTIMPL;
}
static HRESULT WINAPI HLinkCF_fnQueryInterface ( LPCLASSFACTORY iface,
REFIID riid, LPVOID *ppvObj)
{
CFImpl *This = (CFImpl *)iface;
TRACE("(%p)->(%s)\n",This,debugstr_guid(riid));
*ppvObj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) ||
IsEqualIID(riid, &IID_IClassFactory))
{
*ppvObj = This;
return S_OK;
}
TRACE("-- E_NOINTERFACE\n");
return E_NOINTERFACE;
}
static ULONG WINAPI HLinkCF_fnAddRef (LPCLASSFACTORY iface)
{
return 2;
}
static ULONG WINAPI HLinkCF_fnRelease(LPCLASSFACTORY iface)
{
return 1;
}
static HRESULT WINAPI HLinkCF_fnCreateInstance( LPCLASSFACTORY iface,
LPUNKNOWN pUnkOuter, REFIID riid, LPVOID *ppvObject)
{
CFImpl *This = (CFImpl *)iface;
TRACE("%p->(%p,%s,%p)\n", This, pUnkOuter, debugstr_guid(riid), ppvObject);
*ppvObject = NULL;
return This->lpfnCI(pUnkOuter, riid, ppvObject);
}
static HRESULT WINAPI HLinkCF_fnLockServer(LPCLASSFACTORY iface, BOOL fLock)
{
FIXME("%p %d\n", iface, fLock);
return E_NOTIMPL;
}
static const IClassFactoryVtbl hlcfvt =
{
HLinkCF_fnQueryInterface,
HLinkCF_fnAddRef,
HLinkCF_fnRelease,
HLinkCF_fnCreateInstance,
HLinkCF_fnLockServer
};
static CFImpl HLink_cf = { &hlcfvt, &HLink_Constructor };
static CFImpl HLinkBrowseContext_cf = { &hlcfvt, &HLinkBrowseContext_Constructor };
/***********************************************************************
* DllGetClassObject (HLINK.@)
*/
HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID iid, LPVOID *ppv)
{
IClassFactory *pcf = NULL;
TRACE("%s %s %p\n", debugstr_guid(rclsid), debugstr_guid(iid), ppv);
if (!ppv)
return E_INVALIDARG;
*ppv = NULL;
if (IsEqualIID(rclsid, &CLSID_StdHlink))
pcf = (IClassFactory*) &HLink_cf;
else if (IsEqualIID(rclsid, &CLSID_StdHlinkBrowseContext))
pcf = (IClassFactory*) &HLinkBrowseContext_cf;
else
return CLASS_E_CLASSNOTAVAILABLE;
return IClassFactory_QueryInterface(pcf, iid, ppv);
}
static HRESULT register_clsid(LPCGUID guid)
{
static const WCHAR clsid[] =
{'C','L','S','I','D','\\',0};
static const WCHAR ips[] =
{'\\','I','n','p','r','o','c','S','e','r','v','e','r','3','2',0};
static const WCHAR hlink[] =
{'h','l','i','n','k','.','d','l','l',0};
static const WCHAR threading_model[] =
{'T','h','r','e','a','d','i','n','g','M','o','d','e','l',0};
static const WCHAR apartment[] =
{'A','p','a','r','t','m','e','n','t',0};
WCHAR path[80];
HKEY key = NULL;
LONG r;
lstrcpyW(path, clsid);
StringFromGUID2(guid, &path[6], 80);
lstrcatW(path, ips);
r = RegCreateKeyW(HKEY_CLASSES_ROOT, path, &key);
if (r != ERROR_SUCCESS)
return E_FAIL;
RegSetValueExW(key, NULL, 0, REG_SZ, (const BYTE *)hlink, sizeof hlink);
RegSetValueExW(key, threading_model, 0, REG_SZ, (const BYTE *)apartment, sizeof apartment);
RegCloseKey(key);
return S_OK;
}
HRESULT WINAPI DllRegisterServer(void)
{
HRESULT r;
r = register_clsid(&CLSID_StdHlink);
if (SUCCEEDED(r))
r = register_clsid(&CLSID_StdHlinkBrowseContext);
return S_OK;
}

View file

@ -0,0 +1,78 @@
/*
* Copyright 2007 Jacek Caban for CodeWeavers
*
* 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
*/
#include <stdarg.h>
#define COBJMACROS
#include "winerror.h"
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "ole2.h"
#include "hlink.h"
#include "wine/unicode.h"
extern HRESULT WINAPI HLink_Constructor(IUnknown*,REFIID,void**);
extern HRESULT WINAPI HLinkBrowseContext_Constructor(IUnknown*,REFIID,void**);
static inline void *heap_alloc(size_t len)
{
return HeapAlloc(GetProcessHeap(), 0, len);
}
static inline void *heap_alloc_zero(size_t len)
{
return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
}
static inline BOOL heap_free(void *mem)
{
return HeapFree(GetProcessHeap(), 0, mem);
}
static inline LPWSTR hlink_strdupW(LPCWSTR str)
{
LPWSTR ret = NULL;
if(str) {
DWORD size;
size = (strlenW(str)+1)*sizeof(WCHAR);
ret = heap_alloc(size);
memcpy(ret, str, size);
}
return ret;
}
static inline LPWSTR hlink_co_strdupW(LPCWSTR str)
{
LPWSTR ret = NULL;
if(str) {
DWORD size;
size = (strlenW(str)+1)*sizeof(WCHAR);
ret = CoTaskMemAlloc(size);
memcpy(ret, str, size);
}
return ret;
}

View file

@ -0,0 +1,843 @@
/*
* Implementation of hyperlinking (hlink.dll)
*
* Copyright 2005 Aric Stewart for CodeWeavers
*
* 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
*/
#include "hlink_private.h"
#include "shellapi.h"
#include "hlguids.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(hlink);
#define HLINK_SAVE_MAGIC 0x00000002
#define HLINK_SAVE_MONIKER_PRESENT 0x01
#define HLINK_SAVE_MONIKER_IS_ABSOLUTE 0x02
#define HLINK_SAVE_LOCATION_PRESENT 0x08
#define HLINK_SAVE_FRIENDLY_PRESENT 0x10
/* 0x20, 0x40 unknown */
#define HLINK_SAVE_TARGET_FRAME_PRESENT 0x80
/* known flags */
#define HLINK_SAVE_ALL (HLINK_SAVE_TARGET_FRAME_PRESENT|HLINK_SAVE_FRIENDLY_PRESENT|HLINK_SAVE_LOCATION_PRESENT|0x04|HLINK_SAVE_MONIKER_IS_ABSOLUTE|HLINK_SAVE_MONIKER_PRESENT)
static const IHlinkVtbl hlvt;
static const IPersistStreamVtbl psvt;
static const IDataObjectVtbl dovt;
typedef struct
{
const IHlinkVtbl *lpVtbl;
LONG ref;
const IPersistStreamVtbl *lpPSVtbl;
const IDataObjectVtbl *lpDOVtbl;
LPWSTR FriendlyName;
LPWSTR Location;
LPWSTR Target;
LPWSTR TargetFrameName;
IMoniker *Moniker;
IHlinkSite *Site;
DWORD SiteData;
BOOL absolute;
} HlinkImpl;
static inline HlinkImpl* HlinkImpl_from_IPersistStream( IPersistStream* iface)
{
return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpPSVtbl));
}
static inline HlinkImpl* HlinkImpl_from_IDataObject( IDataObject* iface)
{
return (HlinkImpl*) ((CHAR*)iface - FIELD_OFFSET(HlinkImpl, lpDOVtbl));
}
static inline void __GetMoniker(HlinkImpl* This, IMoniker** moniker)
{
*moniker = NULL;
if (This->Moniker)
{
*moniker = This->Moniker;
if (*moniker)
IMoniker_AddRef(*moniker);
}
else if (This->Site)
{
IHlinkSite_GetMoniker(This->Site, This->SiteData,
OLEGETMONIKER_FORCEASSIGN, OLEWHICHMK_CONTAINER,
(LPVOID)moniker);
}
}
HRESULT WINAPI HLink_Constructor(IUnknown *pUnkOuter, REFIID riid,
LPVOID *ppv)
{
HlinkImpl * hl;
TRACE("unkOut=%p riid=%s\n", pUnkOuter, debugstr_guid(riid));
*ppv = NULL;
if (pUnkOuter)
return CLASS_E_NOAGGREGATION;
hl = heap_alloc_zero(sizeof(HlinkImpl));
if (!hl)
return E_OUTOFMEMORY;
hl->ref = 1;
hl->lpVtbl = &hlvt;
hl->lpPSVtbl = &psvt;
hl->lpDOVtbl = &dovt;
*ppv = hl;
return S_OK;
}
static HRESULT WINAPI IHlink_fnQueryInterface(IHlink* iface, REFIID riid,
LPVOID *ppvObj)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE ("(%p)->(%s,%p)\n", This, debugstr_guid (riid), ppvObj);
*ppvObj = NULL;
if (IsEqualIID(riid, &IID_IUnknown) || (IsEqualIID(riid, &IID_IHlink)))
*ppvObj = This;
else if (IsEqualIID(riid, &IID_IPersistStream))
*ppvObj = (LPVOID*)&(This->lpPSVtbl);
else if (IsEqualIID(riid, &IID_IDataObject))
*ppvObj = (LPVOID*)&(This->lpDOVtbl);
if (*ppvObj)
{
IUnknown_AddRef((IUnknown*)(*ppvObj));
return S_OK;
}
return E_NOINTERFACE;
}
static ULONG WINAPI IHlink_fnAddRef (IHlink* iface)
{
HlinkImpl *This = (HlinkImpl*)iface;
ULONG refCount = InterlockedIncrement(&This->ref);
TRACE("(%p)->(count=%u)\n", This, refCount - 1);
return refCount;
}
static ULONG WINAPI IHlink_fnRelease (IHlink* iface)
{
HlinkImpl *This = (HlinkImpl*)iface;
ULONG refCount = InterlockedDecrement(&This->ref);
TRACE("(%p)->(count=%u)\n", This, refCount + 1);
if (refCount)
return refCount;
TRACE("-- destroying IHlink (%p)\n", This);
heap_free(This->FriendlyName);
heap_free(This->Target);
heap_free(This->TargetFrameName);
heap_free(This->Location);
if (This->Moniker)
IMoniker_Release(This->Moniker);
if (This->Site)
IHlinkSite_Release(This->Site);
heap_free(This);
return 0;
}
static HRESULT WINAPI IHlink_fnSetHlinkSite( IHlink* iface,
IHlinkSite* pihlSite, DWORD dwSiteData)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p)->(%p %i)\n", This, pihlSite, dwSiteData);
if (This->Site)
IHlinkSite_Release(This->Site);
This->Site = pihlSite;
if (This->Site)
IHlinkSite_AddRef(This->Site);
This->SiteData = dwSiteData;
return S_OK;
}
static HRESULT WINAPI IHlink_fnGetHlinkSite( IHlink* iface,
IHlinkSite** ppihlSite, DWORD *pdwSiteData)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p)->(%p %p)\n", This, ppihlSite, pdwSiteData);
*ppihlSite = This->Site;
*pdwSiteData = This->SiteData;
if (This->Site)
IHlinkSite_AddRef(This->Site);
return S_OK;
}
static HRESULT WINAPI IHlink_fnSetMonikerReference( IHlink* iface,
DWORD rfHLSETF, IMoniker *pmkTarget, LPCWSTR pwzLocation)
{
HlinkImpl *This = (HlinkImpl*)iface;
FIXME("(%p)->(%i %p %s)\n", This, rfHLSETF, pmkTarget,
debugstr_w(pwzLocation));
if (This->Moniker)
IMoniker_Release(This->Moniker);
This->Moniker = pmkTarget;
if (This->Moniker)
{
LPOLESTR display_name;
IMoniker_AddRef(This->Moniker);
IMoniker_GetDisplayName(This->Moniker, NULL, NULL, &display_name);
This->absolute = display_name && strchrW(display_name, ':');
CoTaskMemFree(display_name);
}
heap_free(This->Location);
This->Location = hlink_strdupW( pwzLocation );
return S_OK;
}
static HRESULT WINAPI IHlink_fnSetStringReference(IHlink* iface,
DWORD grfHLSETF, LPCWSTR pwzTarget, LPCWSTR pwzLocation)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p)->(%i %s %s)\n", This, grfHLSETF, debugstr_w(pwzTarget),
debugstr_w(pwzLocation));
if (grfHLSETF & HLINKSETF_TARGET)
{
heap_free(This->Target);
This->Target = hlink_strdupW( pwzTarget );
}
if (grfHLSETF & HLINKSETF_LOCATION)
{
heap_free(This->Location);
This->Location = hlink_strdupW( pwzLocation );
}
return S_OK;
}
static HRESULT WINAPI IHlink_fnGetMonikerReference(IHlink* iface,
DWORD dwWhichRef, IMoniker **ppimkTarget, LPWSTR *ppwzLocation)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppimkTarget,
ppwzLocation);
if(ppimkTarget)
__GetMoniker(This, ppimkTarget);
if (ppwzLocation)
IHlink_GetStringReference(iface, dwWhichRef, NULL, ppwzLocation);
return S_OK;
}
static HRESULT WINAPI IHlink_fnGetStringReference (IHlink* iface,
DWORD dwWhichRef, LPWSTR *ppwzTarget, LPWSTR *ppwzLocation)
{
HlinkImpl *This = (HlinkImpl*)iface;
FIXME("(%p) -> (%i %p %p)\n", This, dwWhichRef, ppwzTarget, ppwzLocation);
if (ppwzTarget)
{
*ppwzTarget = hlink_co_strdupW( This->Target );
if (!This->Target)
{
IMoniker* mon;
__GetMoniker(This, &mon);
if (mon)
{
IBindCtx *pbc;
CreateBindCtx( 0, &pbc);
IMoniker_GetDisplayName(mon, pbc, NULL, ppwzTarget);
IBindCtx_Release(pbc);
IMoniker_Release(mon);
}
else
FIXME("Unhandled case, no set Target and no moniker\n");
}
}
if (ppwzLocation)
*ppwzLocation = hlink_co_strdupW( This->Location );
TRACE("(Target: %s Location: %s)\n",
(ppwzTarget)?debugstr_w(*ppwzTarget):"<NULL>",
(ppwzLocation)?debugstr_w(*ppwzLocation):"<NULL>");
return S_OK;
}
static HRESULT WINAPI IHlink_fnSetFriendlyName (IHlink *iface,
LPCWSTR pwzFriendlyName)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p) -> (%s)\n", This, debugstr_w(pwzFriendlyName));
heap_free(This->FriendlyName);
This->FriendlyName = hlink_strdupW( pwzFriendlyName );
return S_OK;
}
static HRESULT WINAPI IHlink_fnGetFriendlyName (IHlink* iface,
DWORD grfHLFNAMEF, LPWSTR* ppwzFriendlyName)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p) -> (%i %p)\n", This, grfHLFNAMEF, ppwzFriendlyName);
/* FIXME: Only using explicitly set and cached friendly names */
if (This->FriendlyName)
*ppwzFriendlyName = hlink_co_strdupW( This->FriendlyName );
else
{
IMoniker *moniker;
__GetMoniker(This, &moniker);
if (moniker)
{
IBindCtx *bcxt;
CreateBindCtx(0, &bcxt);
IMoniker_GetDisplayName(moniker, bcxt, NULL, ppwzFriendlyName);
IBindCtx_Release(bcxt);
IMoniker_Release(moniker);
}
else
*ppwzFriendlyName = NULL;
}
return S_OK;
}
static HRESULT WINAPI IHlink_fnSetTargetFrameName(IHlink* iface,
LPCWSTR pwzTargetFramename)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p)->(%s)\n", This, debugstr_w(pwzTargetFramename));
heap_free(This->TargetFrameName);
This->TargetFrameName = hlink_strdupW( pwzTargetFramename );
return S_OK;
}
static HRESULT WINAPI IHlink_fnGetTargetFrameName(IHlink* iface,
LPWSTR *ppwzTargetFrameName)
{
HlinkImpl *This = (HlinkImpl*)iface;
TRACE("(%p)->(%p)\n", This, ppwzTargetFrameName);
*ppwzTargetFrameName = hlink_co_strdupW( This->TargetFrameName );
return S_OK;
}
static HRESULT WINAPI IHlink_fnGetMiscStatus(IHlink* iface, DWORD* pdwStatus)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlink_fnNavigate(IHlink* iface, DWORD grfHLNF, LPBC pbc,
IBindStatusCallback *pbsc, IHlinkBrowseContext *phbc)
{
HlinkImpl *This = (HlinkImpl*)iface;
IMoniker *mon = NULL;
FIXME("Semi-Stub:(%p)->(%i %p %p %p)\n", This, grfHLNF, pbc, pbsc, phbc);
if (This->Site)
IHlinkSite_ReadyToNavigate(This->Site, This->SiteData, 0);
__GetMoniker(This, &mon);
TRACE("Moniker %p\n", mon);
if (mon)
{
IBindCtx *bcxt;
IHlinkTarget *target = NULL;
HRESULT r = S_OK;
CreateBindCtx(0, &bcxt);
RegisterBindStatusCallback(bcxt, pbsc, NULL, 0);
r = IMoniker_BindToObject(mon, bcxt, NULL, &IID_IHlinkTarget,
(LPVOID*)&target);
TRACE("IHlinkTarget returned 0x%x\n", r);
if (r == S_OK)
{
IHlinkTarget_SetBrowseContext(target, phbc);
IHlinkTarget_Navigate(target, grfHLNF, This->Location);
IHlinkTarget_Release(target);
}
else
{
static const WCHAR szOpen[] = {'o','p','e','n',0};
LPWSTR target = NULL;
r = IHlink_GetStringReference(iface, HLINKGETREF_DEFAULT, &target, NULL);
if (SUCCEEDED(r) && target)
{
ShellExecuteW(NULL, szOpen, target, NULL, NULL, SW_SHOW);
CoTaskMemFree(target);
}
}
RevokeBindStatusCallback(bcxt, pbsc);
IBindCtx_Release(bcxt);
IMoniker_Release(mon);
}
if (This->Site)
IHlinkSite_OnNavigationComplete(This->Site, This->SiteData, 0, 0, NULL);
TRACE("Finished Navigation\n");
return S_OK;
}
static HRESULT WINAPI IHlink_fnSetAdditonalParams(IHlink* iface,
LPCWSTR pwzAdditionalParams)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IHlink_fnGetAdditionalParams(IHlink* iface,
LPWSTR* ppwzAdditionalParams)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IHlinkVtbl hlvt =
{
IHlink_fnQueryInterface,
IHlink_fnAddRef,
IHlink_fnRelease,
IHlink_fnSetHlinkSite,
IHlink_fnGetHlinkSite,
IHlink_fnSetMonikerReference,
IHlink_fnGetMonikerReference,
IHlink_fnSetStringReference,
IHlink_fnGetStringReference,
IHlink_fnSetFriendlyName,
IHlink_fnGetFriendlyName,
IHlink_fnSetTargetFrameName,
IHlink_fnGetTargetFrameName,
IHlink_fnGetMiscStatus,
IHlink_fnNavigate,
IHlink_fnSetAdditonalParams,
IHlink_fnGetAdditionalParams
};
static HRESULT WINAPI IDataObject_fnQueryInterface(IDataObject* iface,
REFIID riid, LPVOID *ppvObj)
{
HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
TRACE("%p\n", This);
return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
}
static ULONG WINAPI IDataObject_fnAddRef (IDataObject* iface)
{
HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
TRACE("%p\n", This);
return IHlink_AddRef((IHlink*)This);
}
static ULONG WINAPI IDataObject_fnRelease (IDataObject* iface)
{
HlinkImpl *This = HlinkImpl_from_IDataObject(iface);
TRACE("%p\n", This);
return IHlink_Release((IHlink*)This);
}
static HRESULT WINAPI IDataObject_fnGetData(IDataObject* iface,
FORMATETC* pformatetcIn, STGMEDIUM* pmedium)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnGetDataHere(IDataObject* iface,
FORMATETC* pformatetc, STGMEDIUM* pmedium)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnQueryGetData(IDataObject* iface,
FORMATETC* pformatetc)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnGetConicalFormatEtc(IDataObject* iface,
FORMATETC* pformatetcIn, FORMATETC* pformatetcOut)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnSetData(IDataObject* iface,
FORMATETC* pformatetc, STGMEDIUM* pmedium, BOOL fRelease)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnEnumFormatEtc(IDataObject* iface,
DWORD dwDirection, IEnumFORMATETC** ppenumFormatEtc)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnDAdvise(IDataObject* iface,
FORMATETC* pformatetc, DWORD advf, IAdviseSink* pAdvSink,
DWORD* pdwConnection)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnDUnadvise(IDataObject* iface,
DWORD dwConnection)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT WINAPI IDataObject_fnEnumDAdvise(IDataObject* iface,
IEnumSTATDATA** ppenumAdvise)
{
FIXME("\n");
return E_NOTIMPL;
}
static const IDataObjectVtbl dovt =
{
IDataObject_fnQueryInterface,
IDataObject_fnAddRef,
IDataObject_fnRelease,
IDataObject_fnGetData,
IDataObject_fnGetDataHere,
IDataObject_fnQueryGetData,
IDataObject_fnGetConicalFormatEtc,
IDataObject_fnSetData,
IDataObject_fnEnumFormatEtc,
IDataObject_fnDAdvise,
IDataObject_fnDUnadvise,
IDataObject_fnEnumDAdvise
};
static HRESULT WINAPI IPersistStream_fnQueryInterface(IPersistStream* iface,
REFIID riid, LPVOID *ppvObj)
{
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
TRACE("(%p)\n", This);
return IHlink_QueryInterface((IHlink*)This, riid, ppvObj);
}
static ULONG WINAPI IPersistStream_fnAddRef (IPersistStream* iface)
{
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
TRACE("(%p)\n", This);
return IHlink_AddRef((IHlink*)This);
}
static ULONG WINAPI IPersistStream_fnRelease (IPersistStream* iface)
{
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
TRACE("(%p)\n", This);
return IHlink_Release((IHlink*)This);
}
static HRESULT WINAPI IPersistStream_fnGetClassID(IPersistStream* iface,
CLSID* pClassID)
{
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
TRACE("(%p)\n", This);
memcpy(pClassID, &CLSID_StdHlink, sizeof(CLSID));
return S_OK;
}
static HRESULT WINAPI IPersistStream_fnIsDirty(IPersistStream* iface)
{
FIXME("\n");
return E_NOTIMPL;
}
static HRESULT write_hlink_string(IStream *pStm, LPCWSTR str)
{
DWORD len;
HRESULT hr;
TRACE("(%p, %s)\n", pStm, debugstr_w(str));
len = strlenW(str) + 1;
hr = IStream_Write(pStm, &len, sizeof(len), NULL);
if (FAILED(hr)) return hr;
hr = IStream_Write(pStm, str, len * sizeof(WCHAR), NULL);
if (FAILED(hr)) return hr;
return S_OK;
}
static inline ULONG size_hlink_string(LPCWSTR str)
{
return sizeof(DWORD) + (strlenW(str) + 1) * sizeof(WCHAR);
}
static HRESULT read_hlink_string(IStream *pStm, LPWSTR *out_str)
{
LPWSTR str;
DWORD len;
ULONG read;
HRESULT hr;
hr = IStream_Read(pStm, &len, sizeof(len), &read);
if (FAILED(hr)) return hr;
if (read != sizeof(len)) return STG_E_READFAULT;
TRACE("read len %d\n", len);
str = heap_alloc(len * sizeof(WCHAR));
if (!str) return E_OUTOFMEMORY;
hr = IStream_Read(pStm, str, len * sizeof(WCHAR), &read);
if (FAILED(hr))
{
heap_free(str);
return hr;
}
if (read != len * sizeof(WCHAR))
{
heap_free(str);
return STG_E_READFAULT;
}
TRACE("read string %s\n", debugstr_w(str));
*out_str = str;
return S_OK;
}
static HRESULT WINAPI IPersistStream_fnLoad(IPersistStream* iface,
IStream* pStm)
{
HRESULT r;
DWORD hdr[2];
DWORD read;
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
r = IStream_Read(pStm, &hdr, sizeof(hdr), &read);
if (read != sizeof(hdr) || (hdr[0] != HLINK_SAVE_MAGIC))
{
r = E_FAIL;
goto end;
}
if (hdr[1] & ~HLINK_SAVE_ALL)
FIXME("unknown flag(s) 0x%x\n", hdr[1] & ~HLINK_SAVE_ALL);
if (hdr[1] & HLINK_SAVE_TARGET_FRAME_PRESENT)
{
TRACE("loading target frame name\n");
r = read_hlink_string(pStm, &This->TargetFrameName);
if (FAILED(r)) goto end;
}
if (hdr[1] & HLINK_SAVE_FRIENDLY_PRESENT)
{
TRACE("loading target friendly name\n");
if (!(hdr[1] & 0x4))
FIXME("0x4 flag not present with friendly name flag - not sure what this means\n");
r = read_hlink_string(pStm, &This->FriendlyName);
if (FAILED(r)) goto end;
}
if (hdr[1] & HLINK_SAVE_MONIKER_PRESENT)
{
TRACE("loading moniker\n");
r = OleLoadFromStream(pStm, &IID_IMoniker, (LPVOID*)&(This->Moniker));
if (FAILED(r))
goto end;
This->absolute = hdr[1] & HLINK_SAVE_MONIKER_IS_ABSOLUTE ? TRUE : FALSE;
}
if (hdr[1] & HLINK_SAVE_LOCATION_PRESENT)
{
TRACE("loading location\n");
r = read_hlink_string(pStm, &This->Location);
if (FAILED(r)) goto end;
}
end:
TRACE("Load Result 0x%x (%p)\n", r, This->Moniker);
return r;
}
static HRESULT WINAPI IPersistStream_fnSave(IPersistStream* iface,
IStream* pStm, BOOL fClearDirty)
{
HRESULT r = E_FAIL;
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
DWORD hdr[2];
IMoniker *moniker;
TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
__GetMoniker(This, &moniker);
hdr[0] = HLINK_SAVE_MAGIC;
hdr[1] = 0;
if (moniker)
hdr[1] |= HLINK_SAVE_MONIKER_PRESENT;
if (This->absolute)
hdr[1] |= HLINK_SAVE_MONIKER_IS_ABSOLUTE;
if (This->Location)
hdr[1] |= HLINK_SAVE_LOCATION_PRESENT;
if (This->FriendlyName)
hdr[1] |= HLINK_SAVE_FRIENDLY_PRESENT | 4 /* FIXME */;
if (This->TargetFrameName)
hdr[1] |= HLINK_SAVE_TARGET_FRAME_PRESENT;
IStream_Write(pStm, &hdr, sizeof(hdr), NULL);
if (This->TargetFrameName)
{
r = write_hlink_string(pStm, This->TargetFrameName);
if (FAILED(r)) goto end;
}
if (This->FriendlyName)
{
r = write_hlink_string(pStm, This->FriendlyName);
if (FAILED(r)) goto end;
}
if (moniker)
{
IPersistStream* monstream;
monstream = NULL;
IMoniker_QueryInterface(moniker, &IID_IPersistStream,
(LPVOID*)&monstream);
if (monstream)
{
r = OleSaveToStream(monstream, pStm);
IPersistStream_Release(monstream);
}
if (FAILED(r)) goto end;
}
if (This->Location)
{
r = write_hlink_string(pStm, This->Location);
if (FAILED(r)) goto end;
}
end:
if (moniker) IMoniker_Release(moniker);
TRACE("Save Result 0x%x\n", r);
return r;
}
static HRESULT WINAPI IPersistStream_fnGetSizeMax(IPersistStream* iface,
ULARGE_INTEGER* pcbSize)
{
HRESULT r = E_FAIL;
HlinkImpl *This = HlinkImpl_from_IPersistStream(iface);
IMoniker *moniker;
TRACE("(%p) Moniker(%p)\n", This, This->Moniker);
pcbSize->QuadPart = sizeof(DWORD)*2;
if (This->TargetFrameName)
pcbSize->QuadPart += size_hlink_string(This->TargetFrameName);
if (This->FriendlyName)
pcbSize->QuadPart += size_hlink_string(This->FriendlyName);
__GetMoniker(This, &moniker);
if (moniker)
{
IPersistStream* monstream = NULL;
IMoniker_QueryInterface(moniker, &IID_IPersistStream,
(LPVOID*)&monstream);
if (monstream)
{
ULARGE_INTEGER mon_size;
r = IPersistStream_GetSizeMax(monstream, &mon_size);
pcbSize->QuadPart += mon_size.QuadPart;
IPersistStream_Release(monstream);
}
IMoniker_Release(moniker);
}
if (This->Location)
pcbSize->QuadPart += size_hlink_string(This->Location);
return r;
}
static const IPersistStreamVtbl psvt =
{
IPersistStream_fnQueryInterface,
IPersistStream_fnAddRef,
IPersistStream_fnRelease,
IPersistStream_fnGetClassID,
IPersistStream_fnIsDirty,
IPersistStream_fnLoad,
IPersistStream_fnSave,
IPersistStream_fnGetSizeMax,
};