/* * Copyright 2010 Piotr 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 */ #define COBJMACROS #define CONST_VTABLE #define NONAMELESSUNION #include #include #include "winbase.h" #include "shlobj.h" #include "shellapi.h" #include "initguid.h" DEFINE_GUID(FMTID_Test,0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x12); DEFINE_GUID(FMTID_NotExisting, 0x12345678,0x1234,0x1234,0x12,0x12,0x12,0x12,0x12,0x12,0x12,0x13); DEFINE_GUID(CLSID_ClassMoniker, 0x0000031a,0x0000,0x0000,0xc0,0x00,0x00,0x00,0x00,0x00,0x00,0x46); #define DEFINE_EXPECT(func) \ static BOOL expect_ ## func = FALSE, called_ ## func = FALSE #define SET_EXPECT(func) \ expect_ ## func = TRUE #define CHECK_EXPECT2(func) \ do { \ ok(expect_ ##func, "unexpected call " #func "\n"); \ called_ ## func = TRUE; \ }while(0) #define CHECK_EXPECT(func) \ do { \ CHECK_EXPECT2(func); \ expect_ ## func = FALSE; \ }while(0) #define CHECK_CALLED(func) \ do { \ ok(called_ ## func, "expected " #func "\n"); \ expect_ ## func = called_ ## func = FALSE; \ }while(0) DEFINE_EXPECT(Create); DEFINE_EXPECT(Delete); DEFINE_EXPECT(Open); DEFINE_EXPECT(ReadMultiple); DEFINE_EXPECT(ReadMultipleCodePage); DEFINE_EXPECT(Release); DEFINE_EXPECT(Stat); DEFINE_EXPECT(WriteMultiple); DEFINE_EXPECT(autoplay_BindToObject); DEFINE_EXPECT(autoplay_GetClassObject); static HRESULT (WINAPI *pSHPropStgCreate)(IPropertySetStorage*, REFFMTID, const CLSID*, DWORD, DWORD, DWORD, IPropertyStorage**, UINT*); static HRESULT (WINAPI *pSHPropStgReadMultiple)(IPropertyStorage*, UINT, ULONG, const PROPSPEC*, PROPVARIANT*); static HRESULT (WINAPI *pSHPropStgWriteMultiple)(IPropertyStorage*, UINT*, ULONG, const PROPSPEC*, PROPVARIANT*, PROPID); static HRESULT (WINAPI *pSHCreateQueryCancelAutoPlayMoniker)(IMoniker**); static HRESULT (WINAPI *pSHCreateSessionKey)(REGSAM, HKEY*); static void init(void) { HMODULE hmod = GetModuleHandleA("shell32.dll"); pSHPropStgCreate = (void*)GetProcAddress(hmod, "SHPropStgCreate"); pSHPropStgReadMultiple = (void*)GetProcAddress(hmod, "SHPropStgReadMultiple"); pSHPropStgWriteMultiple = (void*)GetProcAddress(hmod, "SHPropStgWriteMultiple"); pSHCreateQueryCancelAutoPlayMoniker = (void*)GetProcAddress(hmod, "SHCreateQueryCancelAutoPlayMoniker"); pSHCreateSessionKey = (void*)GetProcAddress(hmod, (char*)723); } static HRESULT WINAPI PropertyStorage_QueryInterface(IPropertyStorage *This, REFIID riid, void **ppvObject) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static ULONG WINAPI PropertyStorage_AddRef(IPropertyStorage *This) { ok(0, "unexpected call\n"); return 2; } static ULONG WINAPI PropertyStorage_Release(IPropertyStorage *This) { CHECK_EXPECT(Release); return 1; } static HRESULT WINAPI PropertyStorage_ReadMultiple(IPropertyStorage *This, ULONG cpspec, const PROPSPEC *rgpspec, PROPVARIANT *rgpropvar) { if(cpspec == 1) { CHECK_EXPECT(ReadMultipleCodePage); ok(rgpspec != NULL, "rgpspec = NULL\n"); ok(rgpropvar != NULL, "rgpropvar = NULL\n"); ok(rgpspec[0].ulKind == PRSPEC_PROPID, "rgpspec[0].ulKind = %d\n", rgpspec[0].ulKind); ok(rgpspec[0].u.propid == PID_CODEPAGE, "rgpspec[0].propid = %d\n", rgpspec[0].u.propid); rgpropvar[0].vt = VT_I2; rgpropvar[0].iVal = 1234; } else { CHECK_EXPECT(ReadMultiple); ok(cpspec == 10, "cpspec = %u\n", cpspec); ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec); ok(rgpropvar != NULL, "rgpropvar = NULL\n"); ok(rgpropvar[0].vt==0 || broken(rgpropvar[0].vt==VT_BSTR), "rgpropvar[0].vt = %d\n", rgpropvar[0].vt); rgpropvar[0].vt = VT_BSTR; rgpropvar[0].bstrVal = (void*)0xdeadbeef; rgpropvar[1].vt = VT_LPSTR; rgpropvar[1].pszVal = (void*)0xdeadbeef; rgpropvar[2].vt = VT_BYREF|VT_I1; rgpropvar[2].pcVal = (void*)0xdeadbeef; rgpropvar[3].vt = VT_BYREF|VT_VARIANT; rgpropvar[3].pvarVal = (void*)0xdeadbeef; } return S_OK; } static HRESULT WINAPI PropertyStorage_WriteMultiple(IPropertyStorage *This, ULONG cpspec, const PROPSPEC *rgpspec, const PROPVARIANT *rgpropvar, PROPID propidNameFirst) { CHECK_EXPECT(WriteMultiple); ok(cpspec == 20, "cpspec = %d\n", cpspec); ok(rgpspec == (void*)0xdeadbeef, "rgpspec = %p\n", rgpspec); ok(rgpropvar == (void*)0xdeadbeef, "rgpropvar = %p\n", rgpspec); ok(propidNameFirst == PID_FIRST_USABLE, "propidNameFirst = %d\n", propidNameFirst); return S_OK; } static HRESULT WINAPI PropertyStorage_DeleteMultiple(IPropertyStorage *This, ULONG cpspec, const PROPSPEC *rgpspec) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_ReadPropertyNames(IPropertyStorage *This, ULONG cpropid, const PROPID *rgpropid, LPOLESTR *rglpwstrName) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_WritePropertyNames(IPropertyStorage *This, ULONG cpropid, const PROPID *rgpropid, const LPOLESTR *rglpwstrName) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_DeletePropertyNames(IPropertyStorage *This, ULONG cpropid, const PROPID *rgpropid) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_Commit(IPropertyStorage *This, DWORD grfCommitFlags) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_Revert(IPropertyStorage *This) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_Enum(IPropertyStorage *This, IEnumSTATPROPSTG **ppenum) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_SetTimes(IPropertyStorage *This, const FILETIME *pctime, const FILETIME *patime, const FILETIME *pmtime) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_SetClass(IPropertyStorage *This, REFCLSID clsid) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI PropertyStorage_Stat(IPropertyStorage *This, STATPROPSETSTG *statpsstg) { CHECK_EXPECT(Stat); memset(statpsstg, 0, sizeof(STATPROPSETSTG)); memcpy(&statpsstg->fmtid, &FMTID_Test, sizeof(FMTID)); statpsstg->grfFlags = PROPSETFLAG_ANSI; return S_OK; } static IPropertyStorageVtbl PropertyStorageVtbl = { PropertyStorage_QueryInterface, PropertyStorage_AddRef, PropertyStorage_Release, PropertyStorage_ReadMultiple, PropertyStorage_WriteMultiple, PropertyStorage_DeleteMultiple, PropertyStorage_ReadPropertyNames, PropertyStorage_WritePropertyNames, PropertyStorage_DeletePropertyNames, PropertyStorage_Commit, PropertyStorage_Revert, PropertyStorage_Enum, PropertyStorage_SetTimes, PropertyStorage_SetClass, PropertyStorage_Stat }; static IPropertyStorage PropertyStorage = { &PropertyStorageVtbl }; static HRESULT WINAPI PropertySetStorage_QueryInterface(IPropertySetStorage *This, REFIID riid, void **ppvObject) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static ULONG WINAPI PropertySetStorage_AddRef(IPropertySetStorage *This) { ok(0, "unexpected call\n"); return 2; } static ULONG WINAPI PropertySetStorage_Release(IPropertySetStorage *This) { ok(0, "unexpected call\n"); return 1; } static HRESULT WINAPI PropertySetStorage_Create(IPropertySetStorage *This, REFFMTID rfmtid, const CLSID *pclsid, DWORD grfFlags, DWORD grfMode, IPropertyStorage **ppprstg) { CHECK_EXPECT(Create); ok(IsEqualGUID(rfmtid, &FMTID_Test) || IsEqualGUID(rfmtid, &FMTID_NotExisting), "Incorrect rfmtid value\n"); ok(pclsid == NULL, "pclsid != NULL\n"); ok(grfFlags == PROPSETFLAG_ANSI, "grfFlags = %x\n", grfFlags); ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode); *ppprstg = &PropertyStorage; return S_OK; } static HRESULT WINAPI PropertySetStorage_Open(IPropertySetStorage *This, REFFMTID rfmtid, DWORD grfMode, IPropertyStorage **ppprstg) { CHECK_EXPECT(Open); if(IsEqualGUID(rfmtid, &FMTID_Test)) { ok(grfMode == STGM_READ, "grfMode = %x\n", grfMode); *ppprstg = &PropertyStorage; return S_OK; } return STG_E_FILENOTFOUND; } static HRESULT WINAPI PropertySetStorage_Delete(IPropertySetStorage *This, REFFMTID rfmtid) { CHECK_EXPECT(Delete); ok(IsEqualGUID(rfmtid, &FMTID_Test), "wrong rfmtid value\n"); return S_OK; } static HRESULT WINAPI PropertySetStorage_Enum(IPropertySetStorage *This, IEnumSTATPROPSETSTG **ppenum) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static IPropertySetStorageVtbl PropertySetStorageVtbl = { PropertySetStorage_QueryInterface, PropertySetStorage_AddRef, PropertySetStorage_Release, PropertySetStorage_Create, PropertySetStorage_Open, PropertySetStorage_Delete, PropertySetStorage_Enum }; static IPropertySetStorage PropertySetStorage = { &PropertySetStorageVtbl }; static void test_SHPropStg_functions(void) { IPropertyStorage *property_storage; UINT codepage; PROPVARIANT read[10]; HRESULT hres; if(!pSHPropStgCreate || !pSHPropStgReadMultiple || !pSHPropStgWriteMultiple) { win_skip("SHPropStg* functions are missing\n"); return; } if(0) { /* Crashes on Windows */ pSHPropStgCreate(NULL, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage); pSHPropStgCreate(&PropertySetStorage, NULL, NULL, PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage); pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, NULL, &codepage); } SET_EXPECT(Open); SET_EXPECT(ReadMultipleCodePage); hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage); ok(codepage == 1234, "codepage = %d\n", codepage); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(Open); CHECK_CALLED(ReadMultipleCodePage); SET_EXPECT(Open); hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL, PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, &codepage); ok(hres == STG_E_FILENOTFOUND, "hres = %x\n", hres); CHECK_CALLED(Open); SET_EXPECT(Open); SET_EXPECT(Release); SET_EXPECT(Delete); SET_EXPECT(Create); SET_EXPECT(ReadMultipleCodePage); hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, NULL, PROPSETFLAG_ANSI, STGM_READ, CREATE_ALWAYS, &property_storage, &codepage); ok(codepage == 1234, "codepage = %d\n", codepage); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(Open); CHECK_CALLED(Release); CHECK_CALLED(Delete); CHECK_CALLED(Create); CHECK_CALLED(ReadMultipleCodePage); SET_EXPECT(Open); SET_EXPECT(Create); SET_EXPECT(ReadMultipleCodePage); hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_NotExisting, NULL, PROPSETFLAG_ANSI, STGM_READ, CREATE_ALWAYS, &property_storage, &codepage); ok(codepage == 1234, "codepage = %d\n", codepage); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(Open); CHECK_CALLED(Create); CHECK_CALLED(ReadMultipleCodePage); SET_EXPECT(Open); hres = pSHPropStgCreate(&PropertySetStorage, &FMTID_Test, &FMTID_NotExisting, PROPSETFLAG_DEFAULT, STGM_READ, OPEN_EXISTING, &property_storage, NULL); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(Open); SET_EXPECT(Stat); SET_EXPECT(ReadMultipleCodePage); SET_EXPECT(WriteMultiple); codepage = 0; hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE); ok(hres == S_OK, "hres = %x\n", hres); ok(codepage == 1234, "codepage = %d\n", codepage); CHECK_CALLED(Stat); CHECK_CALLED(ReadMultipleCodePage); CHECK_CALLED(WriteMultiple); SET_EXPECT(Stat); SET_EXPECT(ReadMultipleCodePage); SET_EXPECT(WriteMultiple); hres = pSHPropStgWriteMultiple(property_storage, NULL, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(Stat); CHECK_CALLED(ReadMultipleCodePage); CHECK_CALLED(WriteMultiple); SET_EXPECT(Stat); SET_EXPECT(WriteMultiple); codepage = 1000; hres = pSHPropStgWriteMultiple(property_storage, &codepage, 20, (void*)0xdeadbeef, (void*)0xdeadbeef, PID_FIRST_USABLE); ok(hres == S_OK, "hres = %x\n", hres); ok(codepage == 1000, "codepage = %d\n", codepage); CHECK_CALLED(Stat); CHECK_CALLED(WriteMultiple); read[0].vt = VT_BSTR; read[0].bstrVal = (void*)0xdeadbeef; SET_EXPECT(ReadMultiple); SET_EXPECT(ReadMultipleCodePage); SET_EXPECT(Stat); hres = pSHPropStgReadMultiple(property_storage, 0, 10, (void*)0xdeadbeef, read); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(ReadMultiple); CHECK_CALLED(ReadMultipleCodePage); CHECK_CALLED(Stat); SET_EXPECT(ReadMultiple); SET_EXPECT(Stat); hres = pSHPropStgReadMultiple(property_storage, 1251, 10, (void*)0xdeadbeef, read); ok(hres == S_OK, "hres = %x\n", hres); CHECK_CALLED(ReadMultiple); CHECK_CALLED(Stat); } static HRESULT WINAPI test_activator_QI(IClassActivator *iface, REFIID riid, void **ppv) { *ppv = NULL; if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IClassActivator)) { *ppv = iface; } if (!*ppv) return E_NOINTERFACE; IClassActivator_AddRef(iface); return S_OK; } static ULONG WINAPI test_activator_AddRef(IClassActivator *iface) { return 2; } static ULONG WINAPI test_activator_Release(IClassActivator *iface) { return 1; } static HRESULT WINAPI test_activator_GetClassObject(IClassActivator *iface, REFCLSID clsid, DWORD context, LCID locale, REFIID riid, void **ppv) { CHECK_EXPECT(autoplay_GetClassObject); ok(IsEqualGUID(clsid, &CLSID_QueryCancelAutoPlay), "clsid %s\n", wine_dbgstr_guid(clsid)); ok(IsEqualIID(riid, &IID_IQueryCancelAutoPlay), "riid %s\n", wine_dbgstr_guid(riid)); return E_NOTIMPL; } static const IClassActivatorVtbl test_activator_vtbl = { test_activator_QI, test_activator_AddRef, test_activator_Release, test_activator_GetClassObject }; static IClassActivator test_activator = { &test_activator_vtbl }; static HRESULT WINAPI test_moniker_QueryInterface(IMoniker* iface, REFIID riid, void **ppvObject) { *ppvObject = 0; if (IsEqualIID(&IID_IUnknown, riid) || IsEqualIID(&IID_IPersist, riid) || IsEqualIID(&IID_IPersistStream, riid) || IsEqualIID(&IID_IMoniker, riid)) { *ppvObject = iface; } if (!*ppvObject) return E_NOINTERFACE; return S_OK; } static ULONG WINAPI test_moniker_AddRef(IMoniker* iface) { return 2; } static ULONG WINAPI test_moniker_Release(IMoniker* iface) { return 1; } static HRESULT WINAPI test_moniker_GetClassID(IMoniker* iface, CLSID *pClassID) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_IsDirty(IMoniker* iface) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_Load(IMoniker* iface, IStream* pStm) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_Save(IMoniker* iface, IStream* pStm, BOOL fClearDirty) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_GetSizeMax(IMoniker* iface, ULARGE_INTEGER* pcbSize) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_BindToObject(IMoniker* iface, IBindCtx* pbc, IMoniker* moniker_to_left, REFIID riid, void** ppv) { CHECK_EXPECT(autoplay_BindToObject); ok(pbc != NULL, "got %p\n", pbc); ok(moniker_to_left == NULL, "got %p\n", moniker_to_left); ok(IsEqualIID(riid, &IID_IClassActivator), "got riid %s\n", wine_dbgstr_guid(riid)); if (IsEqualIID(riid, &IID_IClassActivator)) { *ppv = &test_activator; return S_OK; } return E_NOTIMPL; } static HRESULT WINAPI test_moniker_BindToStorage(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, REFIID riid, VOID** ppvResult) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_Reduce(IMoniker* iface, IBindCtx* pbc, DWORD dwReduceHowFar, IMoniker** ppmkToLeft, IMoniker** ppmkReduced) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_ComposeWith(IMoniker* iface, IMoniker* pmkRight, BOOL fOnlyIfNotGeneric, IMoniker** ppmkComposite) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_Enum(IMoniker* iface,BOOL fForward, IEnumMoniker** ppenumMoniker) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_IsEqual(IMoniker* iface, IMoniker* pmkOtherMoniker) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_Hash(IMoniker* iface, DWORD* pdwHash) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_IsRunning(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, IMoniker* pmkNewlyRunning) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_GetTimeOfLastChange(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, FILETIME* pItemTime) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_Inverse(IMoniker* iface, IMoniker** ppmk) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_CommonPrefixWith(IMoniker* iface,IMoniker* pmkOther,IMoniker** ppmkPrefix) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_RelativePathTo(IMoniker* iface,IMoniker* pmOther, IMoniker** ppmkRelPath) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_GetDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR *ppszDisplayName) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_ParseDisplayName(IMoniker* iface, IBindCtx* pbc, IMoniker* pmkToLeft, LPOLESTR pszDisplayName, ULONG* pchEaten, IMoniker** ppmkOut) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static HRESULT WINAPI test_moniker_IsSystemMoniker(IMoniker* iface,DWORD* pwdMksys) { ok(0, "unexpected call\n"); return E_NOTIMPL; } static const IMonikerVtbl test_moniker_vtbl = { test_moniker_QueryInterface, test_moniker_AddRef, test_moniker_Release, test_moniker_GetClassID, test_moniker_IsDirty, test_moniker_Load, test_moniker_Save, test_moniker_GetSizeMax, test_moniker_BindToObject, test_moniker_BindToStorage, test_moniker_Reduce, test_moniker_ComposeWith, test_moniker_Enum, test_moniker_IsEqual, test_moniker_Hash, test_moniker_IsRunning, test_moniker_GetTimeOfLastChange, test_moniker_Inverse, test_moniker_CommonPrefixWith, test_moniker_RelativePathTo, test_moniker_GetDisplayName, test_moniker_ParseDisplayName, test_moniker_IsSystemMoniker }; static IMoniker test_moniker = { &test_moniker_vtbl }; static void test_SHCreateQueryCancelAutoPlayMoniker(void) { IBindCtx *ctxt; IMoniker *mon; IUnknown *unk; CLSID clsid; HRESULT hr; DWORD sys; if (!pSHCreateQueryCancelAutoPlayMoniker) { win_skip("SHCreateQueryCancelAutoPlayMoniker is not available, skipping tests.\n"); return; } hr = pSHCreateQueryCancelAutoPlayMoniker(NULL); ok(hr == E_INVALIDARG, "got 0x%08x\n", hr); hr = pSHCreateQueryCancelAutoPlayMoniker(&mon); ok(hr == S_OK, "got 0x%08x\n", hr); sys = -1; hr = IMoniker_IsSystemMoniker(mon, &sys); ok(hr == S_OK, "got 0x%08x\n", hr); ok(sys == MKSYS_CLASSMONIKER, "got %d\n", sys); memset(&clsid, 0, sizeof(clsid)); hr = IMoniker_GetClassID(mon, &clsid); ok(hr == S_OK, "got 0x%08x\n", hr); ok(IsEqualGUID(&clsid, &CLSID_ClassMoniker), "got %s\n", wine_dbgstr_guid(&clsid)); /* extract used CLSID that implements this hook */ SET_EXPECT(autoplay_BindToObject); SET_EXPECT(autoplay_GetClassObject); CreateBindCtx(0, &ctxt); hr = IMoniker_BindToObject(mon, ctxt, &test_moniker, &IID_IQueryCancelAutoPlay, (void**)&unk); ok(hr == E_NOTIMPL, "got 0x%08x\n", hr); IBindCtx_Release(ctxt); CHECK_CALLED(autoplay_BindToObject); CHECK_CALLED(autoplay_GetClassObject); IMoniker_Release(mon); } #define WM_EXPECTED_VALUE WM_APP #define DROPTEST_FILENAME "c:\\wintest.bin" struct DragParam { HWND hwnd; HANDLE ready; }; static LRESULT WINAPI drop_window_proc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { static BOOL expected; switch (msg) { case WM_EXPECTED_VALUE: { expected = lparam; break; } case WM_DROPFILES: { HDROP hDrop = (HDROP)wparam; char filename[MAX_PATH] = "dummy"; POINT pt; BOOL r; UINT num; num = DragQueryFileA(hDrop, 0xffffffff, NULL, 0); ok(num == 1, "expected 1, got %u\n", num); num = DragQueryFileA(hDrop, 0xffffffff, (char*)0xdeadbeef, 0xffffffff); ok(num == 1, "expected 1, got %u\n", num); num = DragQueryFileA(hDrop, 0, filename, sizeof(filename)); ok(num == strlen(DROPTEST_FILENAME), "got %u\n", num); ok(!strcmp(filename, DROPTEST_FILENAME), "got %s\n", filename); r = DragQueryPoint(hDrop, &pt); ok(r == expected, "expected %d, got %d\n", expected, r); ok(pt.x == 10, "expected 10, got %d\n", pt.x); ok(pt.y == 20, "expected 20, got %d\n", pt.y); DragFinish(hDrop); return 0; } } return DefWindowProcA(hwnd, msg, wparam, lparam); } static DWORD WINAPI drop_window_therad(void *arg) { struct DragParam *param = arg; WNDCLASSA cls; WINDOWINFO info; BOOL r; MSG msg; memset(&cls, 0, sizeof(cls)); cls.lpfnWndProc = drop_window_proc; cls.hInstance = GetModuleHandleA(NULL); cls.lpszClassName = "drop test"; RegisterClassA(&cls); param->hwnd = CreateWindowA("drop test", NULL, 0, 0, 0, 0, 0, NULL, 0, NULL, 0); ok(param->hwnd != NULL, "CreateWindow failed: %d\n", GetLastError()); memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); r = GetWindowInfo(param->hwnd, &info); ok(r, "got %d\n", r); ok(!(info.dwExStyle & WS_EX_ACCEPTFILES), "got %08x\n", info.dwExStyle); DragAcceptFiles(param->hwnd, TRUE); memset(&info, 0, sizeof(info)); info.cbSize = sizeof(info); r = GetWindowInfo(param->hwnd, &info); ok(r, "got %d\n", r); ok((info.dwExStyle & WS_EX_ACCEPTFILES), "got %08x\n", info.dwExStyle); SetEvent(param->ready); while ((r = GetMessageA(&msg, NULL, 0, 0)) != 0) { if (r == (BOOL)-1) { ok(0, "unexpected return value, got %d\n", r); break; } DispatchMessageA(&msg); } DestroyWindow(param->hwnd); UnregisterClassA("drop test", GetModuleHandleA(NULL)); return 0; } static void test_DragQueryFile(BOOL non_client_flag) { struct DragParam param; HANDLE hThread; DWORD rc; HGLOBAL hDrop; DROPFILES *pDrop; int ret; BOOL r; param.ready = CreateEventA(NULL, FALSE, FALSE, NULL); ok(param.ready != NULL, "can't create event\n"); hThread = CreateThread(NULL, 0, drop_window_therad, ¶m, 0, NULL); rc = WaitForSingleObject(param.ready, 5000); ok(rc == WAIT_OBJECT_0, "got %u\n", rc); hDrop = GlobalAlloc(GHND, sizeof(DROPFILES) + (strlen(DROPTEST_FILENAME) + 2) * sizeof(WCHAR)); pDrop = GlobalLock(hDrop); pDrop->pt.x = 10; pDrop->pt.y = 20; pDrop->fNC = non_client_flag; pDrop->pFiles = sizeof(DROPFILES); ret = MultiByteToWideChar(CP_ACP, 0, DROPTEST_FILENAME, -1, (LPWSTR)(pDrop + 1), strlen(DROPTEST_FILENAME) + 1); ok(ret > 0, "got %d\n", ret); pDrop->fWide = TRUE; GlobalUnlock(hDrop); r = PostMessageA(param.hwnd, WM_EXPECTED_VALUE, 0, !non_client_flag); ok(r, "got %d\n", r); r = PostMessageA(param.hwnd, WM_DROPFILES, (WPARAM)hDrop, 0); ok(r, "got %d\n", r); r = PostMessageA(param.hwnd, WM_QUIT, 0, 0); ok(r, "got %d\n", r); rc = WaitForSingleObject(hThread, 5000); ok(rc == WAIT_OBJECT_0, "got %d\n", rc); CloseHandle(param.ready); CloseHandle(hThread); } #undef WM_EXPECTED_VALUE #undef DROPTEST_FILENAME static void test_SHCreateSessionKey(void) { static const WCHAR session_format[] = { 'S','o','f','t','w','a','r','e','\\','M','i','c','r','o','s','o','f','t','\\', 'W','i','n','d','o','w','s','\\','C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\', 'E','x','p','l','o','r','e','r','\\','S','e','s','s','i','o','n','I','n','f','o','\\','%','u',0}; HKEY hkey, hkey2; HRESULT hr; DWORD session; WCHAR sessionW[ARRAY_SIZE(session_format) + 16]; LONG ret; if (!pSHCreateSessionKey) { win_skip("SHCreateSessionKey is not implemented\n"); return; } if (0) /* crashes on native */ hr = pSHCreateSessionKey(KEY_READ, NULL); hkey = (HKEY)0xdeadbeef; hr = pSHCreateSessionKey(0, &hkey); ok(hr == E_ACCESSDENIED, "got 0x%08x\n", hr); ok(hkey == NULL, "got %p\n", hkey); hr = pSHCreateSessionKey(KEY_READ, &hkey); ok(hr == S_OK, "got 0x%08x\n", hr); hr = pSHCreateSessionKey(KEY_READ, &hkey2); ok(hr == S_OK, "got 0x%08x\n", hr); ok(hkey != hkey2, "got %p, %p\n", hkey, hkey2); RegCloseKey(hkey); RegCloseKey(hkey2); /* check the registry */ ProcessIdToSessionId( GetCurrentProcessId(), &session); if (session) { wsprintfW(sessionW, session_format, session); ret = RegOpenKeyW(HKEY_CURRENT_USER, sessionW, &hkey); ok(!ret, "key not found\n"); RegCloseKey(hkey); } } static void test_dragdrophelper(void) { IDragSourceHelper *dragsource; IDropTargetHelper *target; HRESULT hr; hr = CoCreateInstance(&CLSID_DragDropHelper, NULL, CLSCTX_INPROC_SERVER, &IID_IDropTargetHelper, (void **)&target); ok(hr == S_OK, "Failed to create IDropTargetHelper, %#x\n", hr); hr = IDropTargetHelper_QueryInterface(target, &IID_IDragSourceHelper, (void **)&dragsource); ok(hr == S_OK, "QI failed, %#x\n", hr); IDragSourceHelper_Release(dragsource); IDropTargetHelper_Release(target); } START_TEST(shellole) { HRESULT hr; init(); hr = CoInitialize(NULL); ok(hr == S_OK, "CoInitialize failed (0x%08x)\n", hr); if (hr != S_OK) return; test_SHPropStg_functions(); test_SHCreateQueryCancelAutoPlayMoniker(); test_DragQueryFile(TRUE); test_DragQueryFile(FALSE); test_SHCreateSessionKey(); test_dragdrophelper(); CoUninitialize(); }