1524 lines
46 KiB
C
1524 lines
46 KiB
C
/*
|
|
* Unit test of the IShellView
|
|
*
|
|
* Copyright 2010 Nikolay Sivov 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>
|
|
#include <stdio.h>
|
|
|
|
#define COBJMACROS
|
|
#define CONST_VTABLE
|
|
|
|
#include "windef.h"
|
|
#include "winbase.h"
|
|
#include "wtypes.h"
|
|
#include "shellapi.h"
|
|
|
|
#include "shlguid.h"
|
|
#include "shlobj.h"
|
|
#include "shobjidl.h"
|
|
#include "shlwapi.h"
|
|
#include "ocidl.h"
|
|
#include "oleauto.h"
|
|
|
|
#include "initguid.h"
|
|
|
|
#include "wine/heap.h"
|
|
#include "wine/test.h"
|
|
|
|
#include "msg.h"
|
|
|
|
#define LISTVIEW_SEQ_INDEX 0
|
|
#define NUM_MSG_SEQUENCES 1
|
|
|
|
DEFINE_GUID(IID_IPersistHistory, 0x91a565c1, 0xe38f, 0x11d0, 0x94, 0xbf, 0x00, 0xa0, 0xc9, 0x05, 0x5c, 0xbf);
|
|
|
|
static struct msg_sequence *sequences[NUM_MSG_SEQUENCES];
|
|
|
|
static LRESULT WINAPI listview_subclass_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
WNDPROC oldproc = (WNDPROC)GetWindowLongPtrA(hwnd, GWLP_USERDATA);
|
|
static LONG defwndproc_counter = 0;
|
|
struct message msg = { 0 };
|
|
LRESULT ret;
|
|
|
|
msg.message = message;
|
|
msg.flags = sent|wparam|lparam;
|
|
if (defwndproc_counter) msg.flags |= defwinproc;
|
|
msg.wParam = wParam;
|
|
msg.lParam = lParam;
|
|
add_message(sequences, LISTVIEW_SEQ_INDEX, &msg);
|
|
|
|
defwndproc_counter++;
|
|
ret = CallWindowProcA(oldproc, hwnd, message, wParam, lParam);
|
|
defwndproc_counter--;
|
|
return ret;
|
|
}
|
|
|
|
static HWND subclass_listview(HWND hwnd)
|
|
{
|
|
WNDPROC oldproc;
|
|
HWND listview;
|
|
|
|
/* listview is a first child */
|
|
listview = FindWindowExA(hwnd, NULL, WC_LISTVIEWA, NULL);
|
|
if(!listview)
|
|
{
|
|
/* .. except for some versions of Windows XP, where things
|
|
are slightly more complicated. */
|
|
HWND hwnd_tmp;
|
|
hwnd_tmp = FindWindowExA(hwnd, NULL, "DUIViewWndClassName", NULL);
|
|
hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "DirectUIHWND", NULL);
|
|
hwnd_tmp = FindWindowExA(hwnd_tmp, NULL, "CtrlNotifySink", NULL);
|
|
listview = FindWindowExA(hwnd_tmp, NULL, WC_LISTVIEWA, NULL);
|
|
}
|
|
|
|
oldproc = (WNDPROC)SetWindowLongPtrA(listview, GWLP_WNDPROC,
|
|
(LONG_PTR)listview_subclass_proc);
|
|
SetWindowLongPtrA(listview, GWLP_USERDATA, (LONG_PTR)oldproc);
|
|
|
|
return listview;
|
|
}
|
|
|
|
static UINT get_msg_count(struct msg_sequence **seq, int sequence_index, UINT message)
|
|
{
|
|
struct msg_sequence *msg_seq = seq[sequence_index];
|
|
UINT i, count = 0;
|
|
|
|
for(i = 0; i < msg_seq->count ; i++)
|
|
if(msg_seq->sequence[i].message == message)
|
|
count++;
|
|
|
|
return count;
|
|
}
|
|
|
|
/* Checks that every message in the sequence seq is also present in
|
|
* the UINT array msgs */
|
|
static void verify_msgs_in_(struct msg_sequence *seq, const UINT *msgs,
|
|
const char *file, int line)
|
|
{
|
|
UINT i, j, msg, failcount = 0;
|
|
for(i = 0; i < seq->count; i++)
|
|
{
|
|
BOOL found = FALSE;
|
|
msg = seq->sequence[i].message;
|
|
for(j = 0; msgs[j] != 0; j++)
|
|
if(msgs[j] == msg) found = TRUE;
|
|
|
|
if(!found)
|
|
{
|
|
failcount++;
|
|
trace("Unexpected message %d\n", msg);
|
|
}
|
|
}
|
|
ok_(file, line) (!failcount, "%d failures.\n", failcount);
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
}
|
|
|
|
#define verify_msgs_in(seq, msgs) \
|
|
verify_msgs_in_(seq, msgs, __FILE__, __LINE__)
|
|
|
|
/* dummy IDataObject implementation */
|
|
typedef struct {
|
|
IDataObject IDataObject_iface;
|
|
LONG ref;
|
|
} IDataObjectImpl;
|
|
|
|
static const IDataObjectVtbl IDataObjectImpl_Vtbl;
|
|
|
|
static inline IDataObjectImpl *impl_from_IDataObject(IDataObject *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, IDataObjectImpl, IDataObject_iface);
|
|
}
|
|
|
|
static IDataObject* IDataObjectImpl_Construct(void)
|
|
{
|
|
IDataObjectImpl *obj;
|
|
|
|
obj = heap_alloc(sizeof(*obj));
|
|
obj->IDataObject_iface.lpVtbl = &IDataObjectImpl_Vtbl;
|
|
obj->ref = 1;
|
|
|
|
return &obj->IDataObject_iface;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_QueryInterface(IDataObject *iface, REFIID riid, void **ppvObj)
|
|
{
|
|
IDataObjectImpl *This = impl_from_IDataObject(iface);
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown) ||
|
|
IsEqualIID(riid, &IID_IDataObject))
|
|
{
|
|
*ppvObj = &This->IDataObject_iface;
|
|
}
|
|
|
|
if(*ppvObj)
|
|
{
|
|
IDataObject_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI IDataObjectImpl_AddRef(IDataObject * iface)
|
|
{
|
|
IDataObjectImpl *This = impl_from_IDataObject(iface);
|
|
return InterlockedIncrement(&This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI IDataObjectImpl_Release(IDataObject * iface)
|
|
{
|
|
IDataObjectImpl *This = impl_from_IDataObject(iface);
|
|
ULONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
if (!ref)
|
|
heap_free(This);
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_GetData(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_GetDataHere(IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_QueryGetData(IDataObject *iface, FORMATETC *pformat)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_GetCanonicalFormatEtc(
|
|
IDataObject *iface, FORMATETC *pformatIn, FORMATETC *pformatOut)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_SetData(
|
|
IDataObject *iface, FORMATETC *pformat, STGMEDIUM *pmedium, BOOL release)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_EnumFormatEtc(
|
|
IDataObject *iface, DWORD direction, IEnumFORMATETC **ppenumFormatEtc)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_DAdvise(
|
|
IDataObject *iface, FORMATETC *pformatetc, DWORD advf, IAdviseSink *pSink, DWORD *pConnection)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_DUnadvise(IDataObject *iface, DWORD connection)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IDataObjectImpl_EnumDAdvise(IDataObject *iface, IEnumSTATDATA **ppenumAdvise)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IDataObjectVtbl IDataObjectImpl_Vtbl =
|
|
{
|
|
IDataObjectImpl_QueryInterface,
|
|
IDataObjectImpl_AddRef,
|
|
IDataObjectImpl_Release,
|
|
IDataObjectImpl_GetData,
|
|
IDataObjectImpl_GetDataHere,
|
|
IDataObjectImpl_QueryGetData,
|
|
IDataObjectImpl_GetCanonicalFormatEtc,
|
|
IDataObjectImpl_SetData,
|
|
IDataObjectImpl_EnumFormatEtc,
|
|
IDataObjectImpl_DAdvise,
|
|
IDataObjectImpl_DUnadvise,
|
|
IDataObjectImpl_EnumDAdvise
|
|
};
|
|
|
|
/* dummy IShellBrowser implementation */
|
|
typedef struct {
|
|
IShellBrowser IShellBrowser_iface;
|
|
LONG ref;
|
|
} IShellBrowserImpl;
|
|
|
|
static const IShellBrowserVtbl IShellBrowserImpl_Vtbl;
|
|
|
|
static inline IShellBrowserImpl *impl_from_IShellBrowser(IShellBrowser *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, IShellBrowserImpl, IShellBrowser_iface);
|
|
}
|
|
|
|
static IShellBrowser* IShellBrowserImpl_Construct(void)
|
|
{
|
|
IShellBrowserImpl *browser;
|
|
|
|
browser = heap_alloc(sizeof(*browser));
|
|
browser->IShellBrowser_iface.lpVtbl = &IShellBrowserImpl_Vtbl;
|
|
browser->ref = 1;
|
|
|
|
return &browser->IShellBrowser_iface;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_QueryInterface(IShellBrowser *iface,
|
|
REFIID riid,
|
|
LPVOID *ppvObj)
|
|
{
|
|
IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
|
|
|
|
*ppvObj = NULL;
|
|
|
|
if(IsEqualIID(riid, &IID_IUnknown) ||
|
|
IsEqualIID(riid, &IID_IOleWindow) ||
|
|
IsEqualIID(riid, &IID_IShellBrowser))
|
|
{
|
|
*ppvObj = &This->IShellBrowser_iface;
|
|
}
|
|
|
|
if(*ppvObj)
|
|
{
|
|
IShellBrowser_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI IShellBrowserImpl_AddRef(IShellBrowser * iface)
|
|
{
|
|
IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
|
|
return InterlockedIncrement(&This->ref);
|
|
}
|
|
|
|
static ULONG WINAPI IShellBrowserImpl_Release(IShellBrowser * iface)
|
|
{
|
|
IShellBrowserImpl *This = impl_from_IShellBrowser(iface);
|
|
ULONG ref = InterlockedDecrement(&This->ref);
|
|
|
|
if (!ref)
|
|
heap_free(This);
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_GetWindow(IShellBrowser *iface,
|
|
HWND *phwnd)
|
|
{
|
|
if (phwnd) *phwnd = GetDesktopWindow();
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_ContextSensitiveHelp(IShellBrowser *iface,
|
|
BOOL fEnterMode)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_BrowseObject(IShellBrowser *iface,
|
|
LPCITEMIDLIST pidl,
|
|
UINT wFlags)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_EnableModelessSB(IShellBrowser *iface,
|
|
BOOL fEnable)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_GetControlWindow(IShellBrowser *iface,
|
|
UINT id,
|
|
HWND *lphwnd)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_GetViewStateStream(IShellBrowser *iface,
|
|
DWORD mode,
|
|
LPSTREAM *pStrm)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_InsertMenusSB(IShellBrowser *iface,
|
|
HMENU hmenuShared,
|
|
LPOLEMENUGROUPWIDTHS lpMenuWidths)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_OnViewWindowActive(IShellBrowser *iface,
|
|
IShellView *ppshv)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_QueryActiveShellView(IShellBrowser *iface,
|
|
IShellView **ppshv)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_RemoveMenusSB(IShellBrowser *iface,
|
|
HMENU hmenuShared)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_SendControlMsg(IShellBrowser *iface,
|
|
UINT id,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam,
|
|
LRESULT *pret)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_SetMenuSB(IShellBrowser *iface,
|
|
HMENU hmenuShared,
|
|
HOLEMENU holemenuReserved,
|
|
HWND hwndActiveObject)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_SetStatusTextSB(IShellBrowser *iface,
|
|
LPCOLESTR lpszStatusText)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_SetToolbarItems(IShellBrowser *iface,
|
|
LPTBBUTTON lpButtons,
|
|
UINT nButtons,
|
|
UINT uFlags)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI IShellBrowserImpl_TranslateAcceleratorSB(IShellBrowser *iface,
|
|
LPMSG lpmsg,
|
|
WORD wID)
|
|
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IShellBrowserVtbl IShellBrowserImpl_Vtbl =
|
|
{
|
|
IShellBrowserImpl_QueryInterface,
|
|
IShellBrowserImpl_AddRef,
|
|
IShellBrowserImpl_Release,
|
|
IShellBrowserImpl_GetWindow,
|
|
IShellBrowserImpl_ContextSensitiveHelp,
|
|
IShellBrowserImpl_InsertMenusSB,
|
|
IShellBrowserImpl_SetMenuSB,
|
|
IShellBrowserImpl_RemoveMenusSB,
|
|
IShellBrowserImpl_SetStatusTextSB,
|
|
IShellBrowserImpl_EnableModelessSB,
|
|
IShellBrowserImpl_TranslateAcceleratorSB,
|
|
IShellBrowserImpl_BrowseObject,
|
|
IShellBrowserImpl_GetViewStateStream,
|
|
IShellBrowserImpl_GetControlWindow,
|
|
IShellBrowserImpl_SendControlMsg,
|
|
IShellBrowserImpl_QueryActiveShellView,
|
|
IShellBrowserImpl_OnViewWindowActive,
|
|
IShellBrowserImpl_SetToolbarItems
|
|
};
|
|
|
|
static const struct message empty_seq[] = {
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message folderview_getspacing_seq[] = {
|
|
{ LVM_GETITEMSPACING, wparam|sent, FALSE },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message folderview_getselectionmarked_seq[] = {
|
|
{ LVM_GETSELECTIONMARK, sent },
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message folderview_getfocused_seq[] = {
|
|
{ LVM_GETNEXTITEM, sent|wparam|lparam|optional, -1, LVNI_FOCUSED },
|
|
{ 0 }
|
|
};
|
|
|
|
static HRESULT WINAPI shellbrowser_QueryInterface(IShellBrowser *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
if (IsEqualGUID(&IID_IShellBrowser, riid) ||
|
|
IsEqualGUID(&IID_IOleWindow, riid) ||
|
|
IsEqualGUID(&IID_IUnknown, riid))
|
|
{
|
|
*ppv = iface;
|
|
}
|
|
|
|
if (*ppv)
|
|
{
|
|
IUnknown_AddRef((IUnknown*)*ppv);
|
|
return S_OK;
|
|
}
|
|
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
static ULONG WINAPI shellbrowser_AddRef(IShellBrowser *iface)
|
|
{
|
|
return 2;
|
|
}
|
|
|
|
static ULONG WINAPI shellbrowser_Release(IShellBrowser *iface)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_GetWindow(IShellBrowser *iface, HWND *phwnd)
|
|
{
|
|
*phwnd = GetDesktopWindow();
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_ContextSensitiveHelp(IShellBrowser *iface, BOOL mode)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_InsertMenusSB(IShellBrowser *iface, HMENU hmenuShared,
|
|
OLEMENUGROUPWIDTHS *menuwidths)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_SetMenuSB(IShellBrowser *iface, HMENU hmenuShared,
|
|
HOLEMENU holemenuReserved, HWND hwndActiveObject)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_RemoveMenusSB(IShellBrowser *iface, HMENU hmenuShared)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_SetStatusTextSB(IShellBrowser *iface, LPCOLESTR text)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_EnableModelessSB(IShellBrowser *iface, BOOL enable)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_TranslateAcceleratorSB(IShellBrowser *iface, MSG *pmsg, WORD wID)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_BrowseObject(IShellBrowser *iface, LPCITEMIDLIST pidl, UINT flags)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_GetViewStateStream(IShellBrowser *iface, DWORD mode, IStream **stream)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_GetControlWindow(IShellBrowser *iface, UINT id, HWND *phwnd)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_SendControlMsg(IShellBrowser *iface, UINT id, UINT uMsg,
|
|
WPARAM wParam, LPARAM lParam, LRESULT *pret)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_QueryActiveShellView(IShellBrowser *iface, IShellView **view)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_OnViewWindowActive(IShellBrowser *iface, IShellView *view)
|
|
{
|
|
ok(0, "unexpected\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI shellbrowser_SetToolbarItems(IShellBrowser *iface, LPTBBUTTONSB buttons,
|
|
UINT count, UINT flags)
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IShellBrowserVtbl shellbrowservtbl = {
|
|
shellbrowser_QueryInterface,
|
|
shellbrowser_AddRef,
|
|
shellbrowser_Release,
|
|
shellbrowser_GetWindow,
|
|
shellbrowser_ContextSensitiveHelp,
|
|
shellbrowser_InsertMenusSB,
|
|
shellbrowser_SetMenuSB,
|
|
shellbrowser_RemoveMenusSB,
|
|
shellbrowser_SetStatusTextSB,
|
|
shellbrowser_EnableModelessSB,
|
|
shellbrowser_TranslateAcceleratorSB,
|
|
shellbrowser_BrowseObject,
|
|
shellbrowser_GetViewStateStream,
|
|
shellbrowser_GetControlWindow,
|
|
shellbrowser_SendControlMsg,
|
|
shellbrowser_QueryActiveShellView,
|
|
shellbrowser_OnViewWindowActive,
|
|
shellbrowser_SetToolbarItems
|
|
};
|
|
|
|
static IShellBrowser test_shellbrowser = { &shellbrowservtbl };
|
|
|
|
static void test_CreateViewWindow(void)
|
|
{
|
|
IShellFolder *desktop;
|
|
HWND hwnd_view, hwnd2;
|
|
FOLDERSETTINGS settings;
|
|
IShellView *view;
|
|
IDropTarget *dt;
|
|
HRESULT hr;
|
|
RECT r = {0};
|
|
ULONG ref1, ref2;
|
|
IUnknown *unk;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellView_QueryInterface(view, &IID_CDefView, (void **)&unk);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(unk == (IUnknown *)view, "got %p\n", unk);
|
|
IUnknown_Release(unk);
|
|
|
|
if (0)
|
|
{
|
|
/* crashes on native */
|
|
IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, NULL);
|
|
}
|
|
|
|
settings.ViewMode = FVM_ICON;
|
|
settings.fFlags = 0;
|
|
hwnd_view = (HWND)0xdeadbeef;
|
|
hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, NULL, &hwnd_view);
|
|
ok(hr == E_UNEXPECTED, "got (0x%08lx)\n", hr);
|
|
ok(hwnd_view == 0, "got %p\n", hwnd_view);
|
|
|
|
hwnd_view = (HWND)0xdeadbeef;
|
|
hr = IShellView_CreateViewWindow(view, NULL, &settings, NULL, &r, &hwnd_view);
|
|
ok(hr == E_UNEXPECTED, "got (0x%08lx)\n", hr);
|
|
ok(hwnd_view == 0, "got %p\n", hwnd_view);
|
|
|
|
hwnd_view = NULL;
|
|
hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd_view);
|
|
ok(hr == S_OK || broken(hr == S_FALSE), "got (0x%08lx)\n", hr);
|
|
ok(hwnd_view != 0, "got %p\n", hwnd_view);
|
|
|
|
hwnd2 = (HWND)0xdeadbeef;
|
|
hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd2);
|
|
ok(hr == E_UNEXPECTED, "got (0x%08lx)\n", hr);
|
|
ok(hwnd2 == NULL, "got %p\n", hwnd2);
|
|
|
|
/* ::DragLeave without drag operation */
|
|
hr = IShellView_QueryInterface(view, &IID_IDropTarget, (void**)&dt);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
hr = IDropTarget_DragLeave(dt);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
IDropTarget_Release(dt);
|
|
|
|
IShellView_AddRef(view);
|
|
ref1 = IShellView_Release(view);
|
|
hr = IShellView_DestroyViewWindow(view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(!IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
|
|
ref2 = IShellView_Release(view);
|
|
ok(ref1 > ref2, "expected %lu > %lu\n", ref1, ref2);
|
|
ref1 = ref2;
|
|
|
|
/* Show that releasing the shell view does not destroy the window */
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
hwnd_view = NULL;
|
|
hr = IShellView_CreateViewWindow(view, NULL, &settings, &test_shellbrowser, &r, &hwnd_view);
|
|
ok(hr == S_OK || broken(hr == S_FALSE), "got (0x%08lx)\n", hr);
|
|
ok(hwnd_view != NULL, "got %p\n", hwnd_view);
|
|
ok(IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
|
|
ref2 = IShellView_Release(view);
|
|
ok(ref2 != 0, "ref2 = %lu\n", ref2);
|
|
ok(ref2 > ref1, "expected %lu > %lu\n", ref2, ref1);
|
|
ok(IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
|
|
DestroyWindow(hwnd_view);
|
|
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_IFolderView(void)
|
|
{
|
|
IShellFolder *desktop, *folder;
|
|
FOLDERSETTINGS settings;
|
|
IShellView *view;
|
|
IShellBrowser *browser;
|
|
IFolderView2 *fv2;
|
|
IFolderView *fv;
|
|
IUnknown *unk;
|
|
HWND hwnd_view, hwnd_list;
|
|
PITEMID_CHILD pidl;
|
|
HRESULT hr;
|
|
INT ret, count;
|
|
POINT pt;
|
|
RECT r;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellView_QueryInterface(view, &IID_IFolderView, (void**)&fv);
|
|
if (hr != S_OK)
|
|
{
|
|
win_skip("IFolderView not supported by desktop folder\n");
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
return;
|
|
}
|
|
|
|
/* call methods before window creation */
|
|
hr = IFolderView_GetSpacing(fv, NULL);
|
|
ok(hr == S_FALSE || broken(hr == S_OK) /* win7 */, "got (0x%08lx)\n", hr);
|
|
|
|
pidl = (void*)0xdeadbeef;
|
|
hr = IFolderView_Item(fv, 0, &pidl);
|
|
ok(hr == E_INVALIDARG || broken(hr == E_FAIL) /* < Vista */, "got (0x%08lx)\n", hr);
|
|
ok(pidl == 0 || broken(pidl == (void*)0xdeadbeef) /* < Vista */, "got %p\n", pidl);
|
|
|
|
if (0)
|
|
{
|
|
/* crashes on Vista and Win2k8 - List not created yet case */
|
|
IFolderView_GetSpacing(fv, &pt);
|
|
|
|
/* crashes on XP */
|
|
IFolderView_GetSelectionMarkedItem(fv, NULL);
|
|
IFolderView_GetFocusedItem(fv, NULL);
|
|
|
|
/* crashes on Vista+ */
|
|
IFolderView_Item(fv, 0, NULL);
|
|
}
|
|
|
|
browser = IShellBrowserImpl_Construct();
|
|
|
|
settings.ViewMode = FVM_ICON;
|
|
settings.fFlags = 0;
|
|
hwnd_view = (HWND)0xdeadbeef;
|
|
SetRect(&r, 0, 0, 100, 100);
|
|
hr = IShellView_CreateViewWindow(view, NULL, &settings, browser, &r, &hwnd_view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(IsWindow(hwnd_view), "got %p\n", hwnd_view);
|
|
|
|
hwnd_list = subclass_listview(hwnd_view);
|
|
if (!hwnd_list)
|
|
{
|
|
win_skip("Failed to subclass ListView control\n");
|
|
IShellBrowser_Release(browser);
|
|
IFolderView_Release(fv);
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
return;
|
|
}
|
|
|
|
/* IFolderView::GetSpacing */
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
hr = IFolderView_GetSpacing(fv, NULL);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq, "IFolderView::GetSpacing, empty", FALSE);
|
|
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
hr = IFolderView_GetSpacing(fv, &pt);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
/* fails with empty sequence on win7 for unknown reason */
|
|
if (sequences[LISTVIEW_SEQ_INDEX]->count)
|
|
{
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getspacing_seq, "IFolderView::GetSpacing", FALSE);
|
|
ok(pt.x > 0, "got %ld\n", pt.x);
|
|
ok(pt.y > 0, "got %ld\n", pt.y);
|
|
ret = SendMessageA(hwnd_list, LVM_GETITEMSPACING, 0, 0);
|
|
ok(pt.x == LOWORD(ret) && pt.y == HIWORD(ret), "got (%d, %d)\n", LOWORD(ret), HIWORD(ret));
|
|
}
|
|
|
|
/* IFolderView::ItemCount */
|
|
if (0)
|
|
{
|
|
/* crashes on XP */
|
|
IFolderView_ItemCount(fv, SVGIO_ALLVIEW, NULL);
|
|
}
|
|
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
IFolderView_ItemCount(fv, SVGIO_ALLVIEW, &count);
|
|
|
|
/* IFolderView::GetSelectionMarkedItem */
|
|
if (0)
|
|
{
|
|
/* crashes on XP */
|
|
IFolderView_GetSelectionMarkedItem(fv, NULL);
|
|
}
|
|
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
hr = IFolderView_GetSelectionMarkedItem(fv, &ret);
|
|
if (count)
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
else
|
|
ok(hr == S_FALSE, "got (0x%08lx)\n", hr);
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getselectionmarked_seq,
|
|
"IFolderView::GetSelectionMarkedItem", FALSE);
|
|
|
|
/* IFolderView::GetFocusedItem */
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
hr = IFolderView_GetFocusedItem(fv, &ret);
|
|
if (count)
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
else
|
|
ok(hr == S_FALSE, "got (0x%08lx)\n", hr);
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_getfocused_seq,
|
|
"IFolderView::GetFocusedItem", FALSE);
|
|
|
|
/* IFolderView::GetFolder, just return pointer */
|
|
if (0)
|
|
{
|
|
/* crashes on XP */
|
|
IFolderView_GetFolder(fv, NULL, (void**)&folder);
|
|
IFolderView_GetFolder(fv, NULL, NULL);
|
|
}
|
|
|
|
hr = IFolderView_GetFolder(fv, &IID_IShellFolder, NULL);
|
|
ok(hr == E_POINTER, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IFolderView_GetFolder(fv, &IID_IShellFolder, (void**)&folder);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(desktop == folder, "\n");
|
|
if (folder) IShellFolder_Release(folder);
|
|
|
|
hr = IFolderView_GetFolder(fv, &IID_IUnknown, (void**)&unk);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
if (unk) IUnknown_Release(unk);
|
|
|
|
hr = IFolderView_QueryInterface(fv, &IID_IFolderView2, (void**)&fv2);
|
|
if (hr != S_OK)
|
|
win_skip("IFolderView2 is not supported.\n");
|
|
if (fv2) IFolderView2_Release(fv2);
|
|
|
|
hr = IShellView_DestroyViewWindow(view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(!IsWindow(hwnd_view), "hwnd %p still valid\n", hwnd_view);
|
|
|
|
IShellBrowser_Release(browser);
|
|
IFolderView_Release(fv);
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_GetItemObject(void)
|
|
{
|
|
IShellFolder *desktop;
|
|
IShellView *view;
|
|
IUnknown *unk;
|
|
HRESULT hr;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
/* from documentation three interfaces are supported for SVGIO_BACKGROUND:
|
|
IContextMenu, IDispatch, IPersistHistory */
|
|
hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IContextMenu, (void**)&unk);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
IUnknown_Release(unk);
|
|
|
|
unk = NULL;
|
|
hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IDispatch, (void**)&unk);
|
|
ok(hr == S_OK || broken(hr == E_NOTIMPL) /* NT4 */, "got (0x%08lx)\n", hr);
|
|
if (unk) IUnknown_Release(unk);
|
|
|
|
unk = NULL;
|
|
hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersistHistory, (void**)&unk);
|
|
todo_wine ok(hr == S_OK || broken(hr == E_NOTIMPL) /* W9x, NT4 */, "got (0x%08lx)\n", hr);
|
|
if (unk) IUnknown_Release(unk);
|
|
|
|
/* example of unsupported interface, base for IPersistHistory */
|
|
hr = IShellView_GetItemObject(view, SVGIO_BACKGROUND, &IID_IPersist, (void**)&unk);
|
|
ok(hr == E_NOINTERFACE || broken(hr == E_NOTIMPL) /* W2K */, "got (0x%08lx)\n", hr);
|
|
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_IShellFolderView(void)
|
|
{
|
|
IShellFolderView *folderview;
|
|
IShellFolder *desktop;
|
|
IShellView *view;
|
|
IDataObject *obj;
|
|
UINT i;
|
|
HRESULT hr;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellView_QueryInterface(view, &IID_IShellFolderView, (void**)&folderview);
|
|
if (hr != S_OK)
|
|
{
|
|
win_skip("IShellView doesn't provide IShellFolderView on this platform\n");
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
return;
|
|
}
|
|
|
|
/* ::MoveIcons */
|
|
obj = IDataObjectImpl_Construct();
|
|
hr = IShellFolderView_MoveIcons(folderview, obj);
|
|
ok(hr == E_NOTIMPL || broken(hr == S_OK) /* W98 */, "got (0x%08lx)\n", hr);
|
|
IDataObject_Release(obj);
|
|
|
|
/* ::SetRedraw without list created */
|
|
hr = IShellFolderView_SetRedraw(folderview, TRUE);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
/* ::QuerySupport */
|
|
hr = IShellFolderView_QuerySupport(folderview, NULL);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
i = 0xdeadbeef;
|
|
hr = IShellFolderView_QuerySupport(folderview, &i);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(i == 0xdeadbeef, "got %d\n", i);
|
|
|
|
/* ::RemoveObject */
|
|
i = 0xdeadbeef;
|
|
hr = IShellFolderView_RemoveObject(folderview, NULL, &i);
|
|
ok(hr == S_OK || hr == E_FAIL, "got (0x%08lx)\n", hr);
|
|
if (hr == S_OK) ok(i == 0 || broken(i == 0xdeadbeef) /* Vista, 2k8 */,
|
|
"got %d\n", i);
|
|
|
|
IShellFolderView_Release(folderview);
|
|
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_IOleWindow(void)
|
|
{
|
|
IShellFolder *desktop;
|
|
IShellView *view;
|
|
IOleWindow *wnd;
|
|
HRESULT hr;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&view);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellView_QueryInterface(view, &IID_IOleWindow, (void**)&wnd);
|
|
ok(hr == E_NOINTERFACE, "got (0x%08lx)\n", hr);
|
|
|
|
/* IShellView::ContextSensitiveHelp */
|
|
hr = IShellView_ContextSensitiveHelp(view, TRUE);
|
|
ok(hr == E_NOTIMPL, "got (0x%08lx)\n", hr);
|
|
hr = IShellView_ContextSensitiveHelp(view, FALSE);
|
|
ok(hr == E_NOTIMPL, "got (0x%08lx)\n", hr);
|
|
|
|
IShellView_Release(view);
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static const struct message folderview_setcurrentviewmode1_2_prevista[] = {
|
|
{ LVM_SETVIEW, sent|wparam, LV_VIEW_ICON},
|
|
{ LVM_SETIMAGELIST, sent|wparam, 0},
|
|
{ LVM_SETIMAGELIST, sent|wparam, 1},
|
|
{ 0x105a, sent},
|
|
{ LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
|
|
{ LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
|
|
{ LVM_ARRANGE, sent },
|
|
{ LVM_ARRANGE, sent|optional }, /* WinXP */
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message folderview_setcurrentviewmode3_prevista[] = {
|
|
{ LVM_SETVIEW, sent|wparam, LV_VIEW_LIST},
|
|
{ LVM_SETIMAGELIST, sent|wparam, 0},
|
|
{ LVM_SETIMAGELIST, sent|wparam, 1},
|
|
{ 0x105a, sent},
|
|
{ LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
|
|
{ LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
|
|
{ 0 }
|
|
};
|
|
|
|
static const struct message folderview_setcurrentviewmode4_prevista[] = {
|
|
{ LVM_GETHEADER, sent},
|
|
{ LVM_GETITEMCOUNT, sent|optional },
|
|
{ LVM_SETSELECTEDCOLUMN, sent},
|
|
{ WM_NOTIFY, sent },
|
|
{ WM_NOTIFY, sent },
|
|
{ WM_NOTIFY, sent },
|
|
{ WM_NOTIFY, sent },
|
|
{ LVM_SETVIEW, sent|wparam, LV_VIEW_DETAILS},
|
|
{ LVM_SETIMAGELIST, sent|wparam, 0},
|
|
{ LVM_SETIMAGELIST, sent|wparam, 1},
|
|
{ 0x105a, sent},
|
|
{ LVM_SETBKIMAGEW, sent|optional}, /* w2k3 */
|
|
{ LVM_GETBKCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_GETTEXTBKCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_GETTEXTCOLOR, sent|optional}, /* w2k3 */
|
|
{ LVM_SETEXTENDEDLISTVIEWSTYLE, sent|optional|wparam, 0xc8}, /* w2k3 */
|
|
{ 0 }
|
|
};
|
|
|
|
/* XP, SetCurrentViewMode(5)
|
|
108e - LVM_SETVIEW (LV_VIEW_ICON);
|
|
1036 - LVM_SETEXTEDEDLISTVIEWSTYLE (0x8000, 0)
|
|
100c/104c repeated X times
|
|
1003 - LVM_SETIMAGELIST
|
|
1035 - LVM_SETICONSPACING
|
|
1004 - LVM_GETITEMCOUNT
|
|
105a - ?
|
|
1016 - LVM_ARRANGE
|
|
1016 - LVM_ARRANGE
|
|
*/
|
|
|
|
/* XP, SetCurrentViewMode(6)
|
|
1036 - LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0)
|
|
1035 - LVM_SETICONSPACING
|
|
1003 - LVM_SETIMAGELIST
|
|
1003 - LVM_SETIMAGELIST
|
|
100c/104c repeated X times
|
|
10a2 - LVM_SETTILEVIEWINFO
|
|
108e - LVM_SETVIEW (LV_VIEW_TILE)
|
|
1003 - LVM_SETIMAGELIST
|
|
105a - ?
|
|
1016 - LVM_ARRANGE
|
|
1016 - LVM_ARRANGE
|
|
*/
|
|
|
|
/* XP, SetCurrentViewMode (7)
|
|
10a2 - LVM_SETTILEVIEWINFO
|
|
108e - LVM_SETVIEW (LV_VIEW_ICON)
|
|
1004/10a4 (LVM_GETITEMCOUNT/LVM_SETTILEINFO) X times
|
|
1016 - LVM_ARRANGE
|
|
1016 - LVM_ARRANGE
|
|
...
|
|
LVM_SETEXTENDEDLISTVIEWSTYLE (0x40000, 0x40000)
|
|
...
|
|
LVM_SETEXTENDEDLISTVIEWSTYLE (0x8000, 0x8000)
|
|
*/
|
|
|
|
static void test_GetSetCurrentViewMode(void)
|
|
{
|
|
IShellFolder *desktop;
|
|
IShellView *sview;
|
|
IFolderView *fview;
|
|
IShellBrowser *browser;
|
|
FOLDERSETTINGS fs;
|
|
UINT viewmode;
|
|
HWND hwnd;
|
|
RECT rc = {0, 0, 10, 10};
|
|
HRESULT hr;
|
|
UINT i;
|
|
static const int winxp_res[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
|
|
static const int win2k3_res[11] = {0, 1, 2, 3, 4, 5, 6, 5, 8, 0, 0};
|
|
static const int vista_res[11] = {0, 1, 5, 3, 4, 5, 6, 7, 7, 0, 0};
|
|
static const int win7_res[11] = {1, 1, 1, 3, 4, 1, 6, 1, 8, 8, 8};
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(desktop, NULL, &IID_IShellView, (void**)&sview);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
fs.ViewMode = 1;
|
|
fs.fFlags = 0;
|
|
browser = IShellBrowserImpl_Construct();
|
|
hr = IShellView_CreateViewWindow(sview, NULL, &fs, browser, &rc, &hwnd);
|
|
ok(hr == S_OK || broken(hr == S_FALSE /*Win2k*/ ), "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellView_QueryInterface(sview, &IID_IFolderView, (void**)&fview);
|
|
ok(hr == S_OK || broken(hr == E_NOINTERFACE), "got (0x%08lx)\n", hr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
HWND hwnd_lv;
|
|
UINT count;
|
|
|
|
if (0)
|
|
{
|
|
/* Crashes under Win7/WinXP */
|
|
IFolderView_GetCurrentViewMode(fview, NULL);
|
|
}
|
|
|
|
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(viewmode == 1, "ViewMode was %d\n", viewmode);
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, FVM_AUTO);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 0);
|
|
ok(hr == E_INVALIDARG || broken(hr == S_OK),
|
|
"got (0x%08lx)\n", hr);
|
|
|
|
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
for(i = 1; i < 9; i++)
|
|
{
|
|
hr = IFolderView_SetCurrentViewMode(fview, i);
|
|
ok(hr == S_OK || (i == 8 && hr == E_INVALIDARG /*Vista*/),
|
|
"(%d) got (0x%08lx)\n", i, hr);
|
|
|
|
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
|
|
ok(hr == S_OK, "(%d) got (0x%08lx)\n", i, hr);
|
|
|
|
/* Wine currently behaves like winxp here. */
|
|
ok((viewmode == win7_res[i]) || (viewmode == vista_res[i]) ||
|
|
(viewmode == win2k3_res[i]) || (viewmode == winxp_res[i]),
|
|
"(%d) got %d\n",i , viewmode);
|
|
}
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 9);
|
|
ok(hr == E_INVALIDARG || broken(hr == S_OK),
|
|
"got (0x%08lx)\n", hr);
|
|
|
|
/* Test messages */
|
|
hwnd_lv = subclass_listview(hwnd);
|
|
ok(hwnd_lv != NULL, "Failed to subclass listview\n");
|
|
if(hwnd_lv)
|
|
{
|
|
/* Vista seems to set the viewmode by other means than
|
|
sending messages. At least no related messages are
|
|
captured by subclassing.
|
|
*/
|
|
BOOL vista_plus = FALSE;
|
|
static const UINT vista_plus_msgs[] = {
|
|
WM_SETREDRAW, WM_NOTIFY, WM_NOTIFYFORMAT, WM_QUERYUISTATE,
|
|
WM_MENUCHAR, WM_WINDOWPOSCHANGING, WM_NCCALCSIZE, WM_WINDOWPOSCHANGED,
|
|
WM_PARENTNOTIFY, LVM_GETHEADER, 0 };
|
|
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
hr = IFolderView_SetCurrentViewMode(fview, 1);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
|
|
/* WM_SETREDRAW is not sent in versions before Vista. */
|
|
vista_plus = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, WM_SETREDRAW);
|
|
if(vista_plus)
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
else
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista,
|
|
"IFolderView::SetCurrentViewMode(1)", TRUE);
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 2);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
if(vista_plus)
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
else
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode1_2_prevista,
|
|
"IFolderView::SetCurrentViewMode(2)", TRUE);
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 3);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
if(vista_plus)
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
else
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode3_prevista,
|
|
"IFolderView::SetCurrentViewMode(3)", TRUE);
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 4);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
if(vista_plus)
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
else
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, folderview_setcurrentviewmode4_prevista,
|
|
"IFolderView::SetCurrentViewMode(4)", TRUE);
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 5);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
todo_wine
|
|
{
|
|
if(vista_plus)
|
|
{
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
}
|
|
else
|
|
{
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
|
|
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
|
|
ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
}
|
|
}
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 6);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
todo_wine
|
|
{
|
|
if(vista_plus)
|
|
{
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
}
|
|
else
|
|
{
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
|
|
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
|
|
ok(count == 1 || count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
}
|
|
}
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 7);
|
|
ok(hr == S_OK, "got 0x%08lx\n", hr);
|
|
todo_wine
|
|
{
|
|
if(vista_plus)
|
|
{
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
}
|
|
else
|
|
{
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
|
|
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
|
|
ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
}
|
|
}
|
|
|
|
hr = IFolderView_SetCurrentViewMode(fview, 8);
|
|
ok(hr == S_OK || broken(hr == E_INVALIDARG /* Vista */), "got 0x%08lx\n", hr);
|
|
todo_wine
|
|
{
|
|
if(vista_plus)
|
|
{
|
|
verify_msgs_in(sequences[LISTVIEW_SEQ_INDEX], vista_plus_msgs);
|
|
}
|
|
else
|
|
{
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETVIEW);
|
|
ok(count == 1, "LVM_SETVIEW sent %d times.\n", count);
|
|
count = get_msg_count(sequences, LISTVIEW_SEQ_INDEX, LVM_SETEXTENDEDLISTVIEWSTYLE);
|
|
ok(count == 2, "LVM_SETEXTENDEDLISTVIEWSTYLE sent %d times.\n", count);
|
|
flush_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
}
|
|
}
|
|
|
|
hr = IFolderView_GetCurrentViewMode(fview, &viewmode);
|
|
ok(hr == S_OK, "Failed to get current viewmode.\n");
|
|
ok_sequence(sequences, LISTVIEW_SEQ_INDEX, empty_seq,
|
|
"IFolderView::GetCurrentViewMode", FALSE);
|
|
}
|
|
|
|
IFolderView_Release(fview);
|
|
}
|
|
else
|
|
{
|
|
skip("No IFolderView for the desktop folder.\n");
|
|
}
|
|
|
|
IShellBrowser_Release(browser);
|
|
IShellView_DestroyViewWindow(sview);
|
|
IShellView_Release(sview);
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_IOleCommandTarget(void)
|
|
{
|
|
IShellFolder *psf_desktop;
|
|
IShellView *psv;
|
|
IOleCommandTarget *poct;
|
|
HRESULT hr;
|
|
|
|
hr = SHGetDesktopFolder(&psf_desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
hr = IShellFolder_CreateViewObject(psf_desktop, NULL, &IID_IShellView, (void**)&psv);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = IShellView_QueryInterface(psv, &IID_IOleCommandTarget, (void**)&poct);
|
|
ok(hr == S_OK || broken(hr == E_NOINTERFACE) /* Win95/NT4 */, "Got 0x%08lx\n", hr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
OLECMD oc;
|
|
|
|
hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, NULL, NULL);
|
|
ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
|
|
|
|
oc.cmdID = 1;
|
|
hr = IOleCommandTarget_QueryStatus(poct, NULL, 0, &oc, NULL);
|
|
ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08lx\n", hr);
|
|
|
|
oc.cmdID = 1;
|
|
hr = IOleCommandTarget_QueryStatus(poct, NULL, 1, &oc, NULL);
|
|
ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08lx\n", hr);
|
|
|
|
hr = IOleCommandTarget_Exec(poct, NULL, 0, 0, NULL, NULL);
|
|
ok(hr == OLECMDERR_E_UNKNOWNGROUP, "Got 0x%08lx\n", hr);
|
|
|
|
IOleCommandTarget_Release(poct);
|
|
}
|
|
|
|
IShellView_Release(psv);
|
|
}
|
|
|
|
IShellFolder_Release(psf_desktop);
|
|
}
|
|
|
|
static void test_SHCreateShellFolderView(void)
|
|
{
|
|
IShellFolder *desktop;
|
|
IShellView *psv;
|
|
SFV_CREATE sfvc;
|
|
ULONG refCount;
|
|
IUnknown *unk;
|
|
HRESULT hr;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
if (0)
|
|
{
|
|
/* crash on win7 */
|
|
SHCreateShellFolderView(NULL, NULL);
|
|
}
|
|
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderView(NULL, &psv);
|
|
ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
|
|
memset(&sfvc, 0, sizeof(sfvc));
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderView(&sfvc, &psv);
|
|
ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
|
|
memset(&sfvc, 0, sizeof(sfvc));
|
|
sfvc.cbSize = sizeof(sfvc) - 1;
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderView(&sfvc, &psv);
|
|
ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
|
|
memset(&sfvc, 0, sizeof(sfvc));
|
|
sfvc.cbSize = sizeof(sfvc) + 1;
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderView(&sfvc, &psv);
|
|
ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
|
|
if (0)
|
|
{
|
|
/* Crashes on NULL 'pshf' on XP/2k3 */
|
|
memset(&sfvc, 0, sizeof(sfvc));
|
|
sfvc.cbSize = sizeof(sfvc);
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderView(&sfvc, &psv);
|
|
ok(hr == E_UNEXPECTED, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
}
|
|
memset(&sfvc, 0, sizeof(sfvc));
|
|
sfvc.cbSize = sizeof(sfvc) - 1;
|
|
sfvc.pshf = desktop;
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderView(&sfvc, &psv);
|
|
ok(hr == E_INVALIDARG, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
|
|
memset(&sfvc, 0, sizeof(sfvc));
|
|
sfvc.cbSize = sizeof(sfvc);
|
|
sfvc.pshf = desktop;
|
|
psv = NULL;
|
|
hr = SHCreateShellFolderView(&sfvc, &psv);
|
|
ok(hr == S_OK, "Got 0x%08lx\n", hr);
|
|
ok(psv != NULL, "psv = %p\n", psv);
|
|
|
|
hr = IShellView_QueryInterface(psv, &IID_CDefView, (void **)&unk);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(unk == (IUnknown *)psv, "got %p\n", unk);
|
|
IUnknown_Release(unk);
|
|
|
|
refCount = IShellView_Release(psv);
|
|
ok(refCount == 0, "refCount = %lu\n", refCount);
|
|
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_SHCreateShellFolderViewEx(void)
|
|
{
|
|
IShellFolder *desktop;
|
|
IShellView *psv;
|
|
ULONG refCount;
|
|
IUnknown *unk;
|
|
HRESULT hr;
|
|
CSFV csfv;
|
|
|
|
hr = SHGetDesktopFolder(&desktop);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
|
|
if (0)
|
|
{
|
|
/* crash on win7 */
|
|
SHCreateShellFolderViewEx(NULL, NULL);
|
|
SHCreateShellFolderViewEx(NULL, &psv);
|
|
SHCreateShellFolderViewEx(&csfv, NULL);
|
|
}
|
|
|
|
memset(&csfv, 0, sizeof(csfv));
|
|
csfv.pshf = desktop;
|
|
psv = NULL;
|
|
hr = SHCreateShellFolderViewEx(&csfv, &psv);
|
|
ok(hr == S_OK, "Got 0x%08lx\n", hr);
|
|
ok(psv != NULL, "psv = %p\n", psv);
|
|
|
|
hr = IShellView_QueryInterface(psv, &IID_CDefView, (void **)&unk);
|
|
ok(hr == S_OK, "got (0x%08lx)\n", hr);
|
|
ok(unk == (IUnknown *)psv, "got %p\n", unk);
|
|
IUnknown_Release(unk);
|
|
|
|
refCount = IShellView_Release(psv);
|
|
ok(refCount == 0, "refCount = %lu\n", refCount);
|
|
|
|
if (0)
|
|
{
|
|
/* Crashes on null shellfolder, on XP/2k3 */
|
|
memset(&csfv, 0, sizeof(csfv));
|
|
csfv.pshf = NULL;
|
|
psv = (void *)0xdeadbeef;
|
|
hr = SHCreateShellFolderViewEx(&csfv, &psv);
|
|
ok(hr == E_UNEXPECTED, "Got 0x%08lx\n", hr);
|
|
ok(psv == NULL, "psv = %p\n", psv);
|
|
}
|
|
memset(&csfv, 0, sizeof(csfv));
|
|
csfv.cbSize = sizeof(csfv);
|
|
csfv.pshf = desktop;
|
|
psv = NULL;
|
|
hr = SHCreateShellFolderViewEx(&csfv, &psv);
|
|
ok(hr == S_OK, "Got 0x%08lx\n", hr);
|
|
ok(psv != NULL, "psv = %p\n", psv);
|
|
if (psv)
|
|
{
|
|
refCount = IShellView_Release(psv);
|
|
ok(refCount == 0, "refCount = %lu\n", refCount);
|
|
}
|
|
|
|
IShellFolder_Release(desktop);
|
|
}
|
|
|
|
static void test_newmenu(void)
|
|
{
|
|
IUnknown *unk, *unk2;
|
|
HRESULT hr;
|
|
|
|
hr = CoCreateInstance(&CLSID_NewMenu, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk);
|
|
todo_wine
|
|
ok(hr == S_OK, "Failed to create NewMenu object, hr %#lx.\n", hr);
|
|
if (hr != S_OK)
|
|
{
|
|
skip("NewMenu is not supported.\n");
|
|
return;
|
|
}
|
|
|
|
hr = IUnknown_QueryInterface(unk, &IID_IShellExtInit, (void **)&unk2);
|
|
ok(hr == S_OK, "Failed to get IShellExtInit, hr %#lx.\n", hr);
|
|
IUnknown_Release(unk2);
|
|
|
|
hr = IUnknown_QueryInterface(unk, &IID_IContextMenu3, (void **)&unk2);
|
|
ok(hr == S_OK, "Failed to get IContextMenu3, hr %#lx.\n", hr);
|
|
IUnknown_Release(unk2);
|
|
|
|
hr = IUnknown_QueryInterface(unk, &IID_IObjectWithSite, (void **)&unk2);
|
|
ok(hr == S_OK, "Failed to get IObjectWithSite, hr %#lx.\n", hr);
|
|
IUnknown_Release(unk2);
|
|
|
|
IUnknown_Release(unk);
|
|
}
|
|
|
|
START_TEST(shlview)
|
|
{
|
|
OleInitialize(NULL);
|
|
|
|
init_msg_sequences(sequences, NUM_MSG_SEQUENCES);
|
|
|
|
test_CreateViewWindow();
|
|
test_IFolderView();
|
|
test_GetItemObject();
|
|
test_IShellFolderView();
|
|
test_IOleWindow();
|
|
test_GetSetCurrentViewMode();
|
|
test_IOleCommandTarget();
|
|
test_SHCreateShellFolderView();
|
|
test_SHCreateShellFolderViewEx();
|
|
test_newmenu();
|
|
|
|
OleUninitialize();
|
|
}
|