Commit 1c26b3dc authored by Myah Caron's avatar Myah Caron Committed by Alexandre Julliard

shell32: Add ShellLinkObject stubs.

parent 72f42516
...@@ -222,6 +222,7 @@ enum tid_t { ...@@ -222,6 +222,7 @@ enum tid_t {
FolderItems3_tid, FolderItems3_tid,
FolderItemVerb_tid, FolderItemVerb_tid,
FolderItemVerbs_tid, FolderItemVerbs_tid,
IShellLinkDual2_tid,
LAST_tid LAST_tid
}; };
......
...@@ -51,7 +51,8 @@ static const IID * const tid_ids[] = ...@@ -51,7 +51,8 @@ static const IID * const tid_ids[] =
&IID_FolderItem2, &IID_FolderItem2,
&IID_FolderItems3, &IID_FolderItems3,
&IID_FolderItemVerb, &IID_FolderItemVerb,
&IID_FolderItemVerbs &IID_FolderItemVerbs,
&IID_IShellLinkDual2
}; };
static ITypeInfo *typeinfos[LAST_tid]; static ITypeInfo *typeinfos[LAST_tid];
...@@ -102,6 +103,11 @@ typedef struct { ...@@ -102,6 +103,11 @@ typedef struct {
BSTR name; BSTR name;
} FolderItemVerbImpl; } FolderItemVerbImpl;
typedef struct {
IShellLinkDual2 IShellLinkDual2_iface;
LONG ref;
} ShellLinkObjectImpl;
static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface) static inline ShellDispatch *impl_from_IShellDispatch6(IShellDispatch6 *iface)
{ {
return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch6_iface); return CONTAINING_RECORD(iface, ShellDispatch, IShellDispatch6_iface);
...@@ -132,6 +138,11 @@ static inline FolderItemVerbImpl *impl_from_FolderItemVerb(FolderItemVerb *iface ...@@ -132,6 +138,11 @@ static inline FolderItemVerbImpl *impl_from_FolderItemVerb(FolderItemVerb *iface
return CONTAINING_RECORD(iface, FolderItemVerbImpl, FolderItemVerb_iface); return CONTAINING_RECORD(iface, FolderItemVerbImpl, FolderItemVerb_iface);
} }
static inline ShellLinkObjectImpl *impl_from_IShellLinkDual(IShellLinkDual2 *iface)
{
return CONTAINING_RECORD(iface, ShellLinkObjectImpl, IShellLinkDual2_iface);
}
static HRESULT load_typelib(void) static HRESULT load_typelib(void)
{ {
ITypeLib *tl; ITypeLib *tl;
...@@ -617,6 +628,273 @@ failed: ...@@ -617,6 +628,273 @@ failed:
return hr; return hr;
} }
static HRESULT WINAPI ShellLinkObject_QueryInterface(IShellLinkDual2 *iface, REFIID riid,
LPVOID *ppv)
{
ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppv);
if (!ppv) return E_INVALIDARG;
if (IsEqualIID(&IID_IUnknown, riid) ||
IsEqualIID(&IID_IDispatch, riid) ||
IsEqualIID(&IID_IShellLinkDual, riid) ||
IsEqualIID(&IID_IShellLinkDual2, riid))
*ppv = &This->IShellLinkDual2_iface;
else
{
WARN("not implemented for %s\n", debugstr_guid(riid));
*ppv = NULL;
return E_NOINTERFACE;
}
IUnknown_AddRef((IUnknown*)*ppv);
return S_OK;
}
static ULONG WINAPI ShellLinkObject_AddRef(IShellLinkDual2 *iface)
{
ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
ULONG ref = InterlockedIncrement(&This->ref);
TRACE("(%p), new refcount=%i\n", iface, ref);
return ref;
}
static ULONG WINAPI ShellLinkObject_Release(IShellLinkDual2 *iface)
{
ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
ULONG ref = InterlockedDecrement(&This->ref);
TRACE("(%p), new refcount=%i\n", iface, ref);
if (!ref)
{
heap_free(This);
}
return ref;
}
static HRESULT WINAPI ShellLinkObject_GetTypeInfoCount(IShellLinkDual2 *iface, UINT *pctinfo)
{
TRACE("(%p,%p)\n", iface, pctinfo);
*pctinfo = 1;
return S_OK;
}
static HRESULT WINAPI ShellLinkObject_GetTypeInfo(IShellLinkDual2 *iface, UINT iTInfo,
LCID lcid, ITypeInfo **ppTInfo)
{
HRESULT hr;
TRACE("(%p,%u,%d,%p)\n", iface, iTInfo, lcid, ppTInfo);
hr = get_typeinfo(IShellLinkDual2_tid, ppTInfo);
if (SUCCEEDED(hr))
ITypeInfo_AddRef(*ppTInfo);
return hr;
}
static HRESULT WINAPI ShellLinkObject_GetIDsOfNames(IShellLinkDual2 *iface, REFIID riid,
LPOLESTR *rgszNames, UINT cNames, LCID lcid, DISPID *rgDispId)
{
ITypeInfo *ti;
HRESULT hr;
TRACE("(%p,%s,%p,%u,%d,%p)\n", iface, shdebugstr_guid(riid), rgszNames, cNames, lcid,
rgDispId);
hr = get_typeinfo(IShellLinkDual2_tid, &ti);
if (SUCCEEDED(hr))
hr = ITypeInfo_GetIDsOfNames(ti, rgszNames, cNames, rgDispId);
return hr;
}
static HRESULT WINAPI ShellLinkObject_Invoke(IShellLinkDual2 *iface, DISPID dispIdMember,
REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS *pDispParams,
VARIANT *pVarResult, EXCEPINFO *pExcepInfo, UINT *puArgErr)
{
ShellLinkObjectImpl *This = impl_from_IShellLinkDual(iface);
ITypeInfo *ti;
HRESULT hr;
TRACE("(%p,%d,%s,%d,%u,%p,%p,%p,%p)\n", iface, dispIdMember, shdebugstr_guid(riid), lcid,
wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
hr = get_typeinfo(IShellLinkDual2_tid, &ti);
if (SUCCEEDED(hr))
hr = ITypeInfo_Invoke(ti, This, dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return hr;
}
static HRESULT WINAPI ShellLinkObject_get_Path(IShellLinkDual2 *iface, BSTR *pbs)
{
FIXME("(%p, %p)\n", iface, pbs);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_put_Path(IShellLinkDual2 *iface, BSTR bs)
{
FIXME("(%p, %s)\n", iface, debugstr_w(bs));
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_get_Description(IShellLinkDual2 *iface, BSTR *pbs)
{
FIXME("(%p, %p)\n", iface, pbs);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_put_Description(IShellLinkDual2 *iface, BSTR bs)
{
FIXME("(%p, %s)\n", iface, debugstr_w(bs));
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_get_WorkingDirectory(IShellLinkDual2 *iface, BSTR *pbs)
{
FIXME("(%p, %p)\n", iface, pbs);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_put_WorkingDirectory(IShellLinkDual2 *iface, BSTR bs)
{
FIXME("(%p, %s)\n", iface, debugstr_w(bs));
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_get_Arguments(IShellLinkDual2 *iface, BSTR *pbs)
{
FIXME("(%p, %p)\n", iface, pbs);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_put_Arguments(IShellLinkDual2 *iface, BSTR bs)
{
FIXME("(%p, %s)\n", iface, debugstr_w(bs));
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_get_Hotkey(IShellLinkDual2 *iface, int *piHK)
{
FIXME("(%p, %p)\n", iface, piHK);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_put_Hotkey(IShellLinkDual2 *iface, int iHK)
{
FIXME("(%p, %d)\n", iface, iHK);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_get_ShowCommand(IShellLinkDual2 *iface, int *piShowCommand)
{
FIXME("(%p, %p)\n", iface, piShowCommand);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_put_ShowCommand(IShellLinkDual2 *iface, int iShowCommand)
{
FIXME("(%p, %d)\n", iface, iShowCommand);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_Resolve(IShellLinkDual2 *iface, int fFlags)
{
FIXME("(%p, %d)\n", iface, fFlags);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_GetIconLocation(IShellLinkDual2 *iface, BSTR *pbs,
int *piIcon)
{
FIXME("(%p, %p, %p)\n", iface, pbs, piIcon);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_SetIconLocation(IShellLinkDual2 *iface, BSTR bs,
int iIcon)
{
FIXME("(%p, %s, %d)\n", iface, debugstr_w(bs), iIcon);
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_Save(IShellLinkDual2 *iface, VARIANT vWhere)
{
FIXME("(%p, %s)\n", iface, debugstr_variant(&vWhere));
return E_NOTIMPL;
}
static HRESULT WINAPI ShellLinkObject_get_Target(IShellLinkDual2 *iface, FolderItem **ppfi)
{
FIXME("(%p, %p)\n", iface, ppfi);
return E_NOTIMPL;
}
static const IShellLinkDual2Vtbl ShellLinkObjectVtbl = {
ShellLinkObject_QueryInterface,
ShellLinkObject_AddRef,
ShellLinkObject_Release,
ShellLinkObject_GetTypeInfoCount,
ShellLinkObject_GetTypeInfo,
ShellLinkObject_GetIDsOfNames,
ShellLinkObject_Invoke,
ShellLinkObject_get_Path,
ShellLinkObject_put_Path,
ShellLinkObject_get_Description,
ShellLinkObject_put_Description,
ShellLinkObject_get_WorkingDirectory,
ShellLinkObject_put_WorkingDirectory,
ShellLinkObject_get_Arguments,
ShellLinkObject_put_Arguments,
ShellLinkObject_get_Hotkey,
ShellLinkObject_put_Hotkey,
ShellLinkObject_get_ShowCommand,
ShellLinkObject_put_ShowCommand,
ShellLinkObject_Resolve,
ShellLinkObject_GetIconLocation,
ShellLinkObject_SetIconLocation,
ShellLinkObject_Save,
ShellLinkObject_get_Target,
};
static HRESULT ShellLinkObject_Constructor(IShellLinkDual2 **link)
{
ShellLinkObjectImpl *This;
FIXME("(%p)\n", link);
*link = NULL;
This = heap_alloc(sizeof(*This));
if (!This) return E_OUTOFMEMORY;
This->IShellLinkDual2_iface.lpVtbl = &ShellLinkObjectVtbl;
This->ref = 1;
*link = (IShellLinkDual2 *)&This->IShellLinkDual2_iface;
return S_OK;
}
static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem2 *iface, static HRESULT WINAPI FolderItemImpl_QueryInterface(FolderItem2 *iface,
REFIID riid, LPVOID *ppv) REFIID riid, LPVOID *ppv)
{ {
...@@ -803,10 +1081,23 @@ static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem2 *iface, BSTR *path) ...@@ -803,10 +1081,23 @@ static HRESULT WINAPI FolderItemImpl_get_Path(FolderItem2 *iface, BSTR *path)
static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem2 *iface, static HRESULT WINAPI FolderItemImpl_get_GetLink(FolderItem2 *iface,
IDispatch **ppid) IDispatch **ppid)
{ {
FIXME("(%p,%p)\n", iface, ppid); IShellLinkDual2 *link;
HRESULT hr;
FolderItemImpl *This = impl_from_FolderItem(iface);
TRACE("(%p,%p)\n", iface, ppid);
*ppid = NULL; *ppid = NULL;
return E_NOTIMPL;
if (!(This->attributes & SFGAO_LINK))
return E_NOTIMPL;
hr = ShellLinkObject_Constructor(&link);
if (hr != S_OK)
return hr;
*ppid = (IDispatch*)link;
return S_OK;
} }
static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem2 *iface, static HRESULT WINAPI FolderItemImpl_get_GetFolder(FolderItem2 *iface,
......
...@@ -1408,6 +1408,154 @@ if (0) { /* crashes on winxp/win2k3 */ ...@@ -1408,6 +1408,154 @@ if (0) { /* crashes on winxp/win2k3 */
IShellDispatch_Release(sd); IShellDispatch_Release(sd);
} }
static void test_ShellLinkObject(void)
{
HRESULT hr;
IShellDispatch *sd;
WCHAR path[MAX_PATH],
empty_path[MAX_PATH],
link_path[MAX_PATH];
VARIANT v;
Folder2 *folder2;
Folder *folder;
FolderItem *item;
IDispatch *dispatch;
IShellLinkW *sl;
IShellLinkDual2* sld;
IPersistFile *pf;
BOOL ret;
BSTR str;
HANDLE file;
int hk;
hr = CoCreateInstance(&CLSID_Shell, NULL, CLSCTX_INPROC_SERVER,
&IID_IShellDispatch, (void**)&sd);
ok(hr == S_OK, "got 0x%08x\n", hr);
GetTempPathW(MAX_PATH, path);
V_VT(&v) = VT_BSTR;
V_BSTR(&v) = SysAllocString(path);
hr = IShellDispatch_NameSpace(sd, v, &folder);
ok(hr == S_OK, "got 0x%08x\n", hr);
VariantClear(&v);
hr = Folder_QueryInterface(folder, &IID_Folder2, (void**)&folder2);
ok(hr == S_OK, "got 0x%08x\n", hr);
Folder_Release(folder);
hr = Folder2_get_Self(folder2, &item);
ok(hr == S_OK, "got 0x%08x\n", hr);
dispatch = (IDispatch*)0xdeadbeef;
hr = FolderItem_get_GetLink(item, &dispatch);
ok(hr == E_NOTIMPL, "got 0x%08x\n", hr);
ok(dispatch == NULL, "got %p\n", dispatch);
FolderItem_Release(item);
PathCombineW(empty_path, path, L"winetest_empty_file.txt");
file = CreateFileW(empty_path, 0, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed: %08x\n", GetLastError());
CloseHandle(file);
hr = CoCreateInstance(&CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, &IID_IShellLinkW, (LPVOID*)&sl);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_SetPath(sl, empty_path);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_GetPath(sl, empty_path, MAX_PATH, NULL, 0);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_SetDescription(sl, L"description");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_SetWorkingDirectory(sl, L"working directory");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_SetArguments(sl, L"arguments");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_SetHotkey(sl, 1234);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_SetShowCmd(sl, 1);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IShellLinkW_QueryInterface(sl, &IID_IPersistFile, (LPVOID*)&pf);
ok(hr == S_OK, "got 0x%08x\n", hr);
PathCombineW(link_path, path, L"winetest_filled.lnk");
hr = IPersistFile_Save(pf, link_path, TRUE);
ok(hr == S_OK, "got 0x%08x\n", hr);
IPersistFile_Release(pf);
IShellLinkW_Release(sl);
str = SysAllocString(L"winetest_filled.lnk");
hr = Folder2_ParseName(folder2, str, &item);
ok(hr == S_OK, "got 0x%08x\n", hr);
SysFreeString(str);
dispatch = NULL;
hr = FolderItem_get_GetLink(item, &dispatch);
ok(hr == S_OK, "got 0x%08x\n", hr);
ok(dispatch != NULL, "got %p\n", dispatch);
if (dispatch) {
sld = (IShellLinkDual2*)dispatch;
str = NULL;
hr = IShellLinkDual2_get_Path(sld, &str);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) {
ok(!wcscmp(str, empty_path), "got %s (wanted %s)\n",
wine_dbgstr_w(str), wine_dbgstr_w(empty_path));
SysFreeString(str);
}
str = NULL;
hr = IShellLinkDual2_get_Description(sld, &str);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) {
ok(!wcscmp(str, L"description"), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
}
str = NULL;
hr = IShellLinkDual2_get_WorkingDirectory(sld, &str);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) {
ok(!wcscmp(str, L"working directory"), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
}
str = NULL;
hr = IShellLinkDual2_get_Arguments(sld, &str);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
if (hr == S_OK) {
ok(!wcscmp(str, L"arguments"), "got %s\n", wine_dbgstr_w(str));
SysFreeString(str);
}
hk = 0;
hr = IShellLinkDual2_get_Hotkey(sld, &hk);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine ok(hk == 1234, "got %i\n", hk);
hk = 0;
hr = IShellLinkDual2_get_ShowCommand(sld, &hk);
todo_wine ok(hr == S_OK, "got 0x%08x\n", hr);
todo_wine ok(hk == 1, "got %i\n", hk);
IShellLinkDual2_Release(sld);
}
FolderItem_Release(item);
ret = DeleteFileW(link_path);
ok(ret, "DeleteFile failed: %08x\n", GetLastError());
ret = DeleteFileW(empty_path);
ok(ret, "DeleteFile failed: %08x\n", GetLastError());
Folder2_Release(folder2);
IShellDispatch_Release(sd);
}
static void test_ShellExecute(void) static void test_ShellExecute(void)
{ {
HRESULT hr; HRESULT hr;
...@@ -1466,6 +1614,7 @@ START_TEST(shelldispatch) ...@@ -1466,6 +1614,7 @@ START_TEST(shelldispatch)
test_ShellWindows(); test_ShellWindows();
test_ParseName(); test_ParseName();
test_Verbs(); test_Verbs();
test_ShellLinkObject();
test_ShellExecute(); test_ShellExecute();
CoUninitialize(); CoUninitialize();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment