From: Lorenzo Ferrillo lorenzofersteam@live.it
--- dlls/shell32/shellord.c | 108 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 2 deletions(-)
diff --git a/dlls/shell32/shellord.c b/dlls/shell32/shellord.c index a007c0e5c60..7c262e6436f 100644 --- a/dlls/shell32/shellord.c +++ b/dlls/shell32/shellord.c @@ -534,6 +534,90 @@ HRESULT WINAPI SHRevokeDragDrop(HWND hWnd) return RevokeDragDrop(hWnd); }
+ +typedef struct InternalDropSource{ + IDropSource IDropSource_iface; + LONG Ref; +} InternalDropSource; + +static inline InternalDropSource *impl_from_IDropSource(IDropSource *iface) +{ + return CONTAINING_RECORD(iface, InternalDropSource, IDropSource_iface); +} + +static HRESULT WINAPI InternalDropSource_QueryInterface(IDropSource *iface, REFIID riid, void **ppvObj) +{ + InternalDropSource *This = impl_from_IDropSource(iface); + TRACE("(%p)->(%s, %p)\n", This, debugstr_guid(riid), ppvObj); + + *ppvObj = NULL; + + if(IsEqualIID(riid, &IID_IDropSource) || IsEqualIID(riid, &IID_IUnknown) ) + { + *ppvObj = &This->IDropSource_iface; + IUnknown_AddRef ((IUnknown *) (*ppvObj)); + TRACE("-- Interface: (%p)->(%p)\n",ppvObj,*ppvObj); + return S_OK; + } + + WARN("-- Interface: E_NOINTERFACE\n"); + return E_NOINTERFACE; +} + +static ULONG WINAPI InternalDropSource_AddRef(IDropSource *iface) +{ + InternalDropSource *This = impl_from_IDropSource(iface); + TRACE("(%p)->(%lu)\n", This, This->Ref); + return InterlockedIncrement(&This->Ref); +} + +static ULONG WINAPI InternalDropSource_Release(IDropSource *iface) +{ + ULONG refcount; + InternalDropSource *This = impl_from_IDropSource(iface); + TRACE("(%p)->(%lu)\n", This, This->Ref); + refcount = InterlockedDecrement(&This->Ref); + + if(refcount == 0) + free(This); + + return refcount; +} + +static HRESULT WINAPI InternalDropSource_QueryContinueDrag( + IDropSource *iface, + BOOL fEscapePressed, + DWORD grfKeyState) +{ + InternalDropSource *This = impl_from_IDropSource(iface); + TRACE("(%p)\n",This); + + if (fEscapePressed) + return DRAGDROP_S_CANCEL; + else if (!(grfKeyState & MK_LBUTTON) && !(grfKeyState & MK_RBUTTON)) + return DRAGDROP_S_DROP; + else + return S_OK; +} + +static HRESULT WINAPI InternalDropSource_GiveFeedback( + IDropSource *iface, + DWORD dwEffect) +{ + InternalDropSource *This = impl_from_IDropSource(iface); + TRACE("(%p)\n",This); + + return DRAGDROP_S_USEDEFAULTCURSORS; +} + +static const IDropSourceVtbl dropsourcevtbl = +{ + InternalDropSource_QueryInterface, + InternalDropSource_AddRef, + InternalDropSource_Release, + InternalDropSource_QueryContinueDrag, + InternalDropSource_GiveFeedback +}; /************************************************************************* * SHDoDragDrop [SHELL32.88] * @@ -554,9 +638,29 @@ HRESULT WINAPI SHDoDragDrop( DWORD dwOKEffect, LPDWORD pdwEffect) { + HRESULT hr; + LPDROPSOURCE dropSource = lpDropSource; FIXME("(%p %p %p 0x%08lx %p):stub.\n", - hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect); - return DoDragDrop(lpDataObject, lpDropSource, dwOKEffect, pdwEffect); + hWnd, lpDataObject, lpDropSource, dwOKEffect, pdwEffect); + if(lpDropSource == NULL) + { + /*This function should create a IDropSource object if the lpDropSource parameter was NULL. + * Delphi's drag and drop functions expect this to work when it detects Windows Vista or above */ + InternalDropSource* dummy = calloc(1, sizeof(InternalDropSource)); + if(!dummy) + return E_OUTOFMEMORY; + + dummy->IDropSource_iface.lpVtbl = &dropsourcevtbl; + dummy->Ref = 1; + dropSource = &dummy->IDropSource_iface; + } + hr = DoDragDrop(lpDataObject, dropSource, dwOKEffect, pdwEffect); + if(lpDropSource == NULL) + { + /*Source was created internally, free*/ + InternalDropSource_Release(dropSource); + } + return hr; }
/*************************************************************************