diff --git a/dlls/shell32/shellfolder.h b/dlls/shell32/shellfolder.h new file mode 100644 index 00000000000..c2db02cfc0c --- /dev/null +++ b/dlls/shell32/shellfolder.h @@ -0,0 +1,48 @@ +/* + * defines helperfunctions to manipulate the contents of a IShellFolder + * + */ + +#ifndef __WINE_SHELLFOLDER_HELP_H +#define __WINE_SHELLFOLDER_HELP_H + +#include "winbase.h" +#include "shell.h" + +#include "wine/obj_base.h" +#include "wine/obj_shellfolder.h" + + +/***************************************************************************** + * Predeclare the interfaces + */ +DEFINE_GUID(IID_ISFHelper, 0x1fe68efbL, 0x1874, 0x9812, 0x56, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); +typedef struct ISFHelper ISFHelper, *LPISFHELPER; + +/***************************************************************************** + * ISFHelper interface + */ + +#define ICOM_INTERFACE ISFHelper +#define ISFHelper_METHODS \ + ICOM_METHOD2 (HRESULT, GetUniqueName, LPSTR, lpName, UINT, uLen) \ + ICOM_METHOD3 (HRESULT, AddFolder, HWND, hwnd, LPCSTR, lpName, LPITEMIDLIST*, ppidlOut) \ + ICOM_METHOD2 (HRESULT, DeleteItems, UINT, cidl, LPCITEMIDLIST*, apidl) \ + ICOM_METHOD3 (HRESULT, CopyItems, IShellFolder*, pSFFrom, UINT, cidl, LPCITEMIDLIST*, apidl) +#define ISFHelper_IMETHODS \ + IUnknown_IMETHODS \ + ISFHelper_METHODS +ICOM_DEFINE(ISFHelper, IUnknown) +#undef ICOM_INTERFACE + +/*** IUnknown methods ***/ +#define ISFHelper_QueryInterface(p,a,b) ICOM_CALL2(QueryInterface,p,a,b) +#define ISFHelper_AddRef(p) ICOM_CALL (AddRef,p) +#define ISFHelper_Release(p) ICOM_CALL (Release,p) +/*** ISFHelper methods ***/ +#define ISFHelper_GetUniqueName(p,a,b) ICOM_CALL2(GetUniqueName,p,a,b) +#define ISFHelper_AddFolder(p,a,b,c) ICOM_CALL3(AddFolder,p,a,b,c) +#define ISFHelper_DeleteItems(p,a,b) ICOM_CALL2(DeleteItems,p,a,b) +#define ISFHelper_CopyItems(p,a,b,c) ICOM_CALL3(CopyItems,p,a,b,c) + +#endif /* __WINE_SHELLFOLDER_HELP_H */ diff --git a/dlls/shell32/shlfolder.c b/dlls/shell32/shlfolder.c index 884d015f1b7..4fee7c6a9b7 100644 --- a/dlls/shell32/shlfolder.c +++ b/dlls/shell32/shlfolder.c @@ -10,6 +10,7 @@ #include #include +#include #include "debugtools.h" #include "winerror.h" @@ -25,6 +26,11 @@ #include "shell32_main.h" #include "shresdef.h" +#define INITGUID +#include "initguid.h" +#include "shellfolder.h" + + DEFAULT_DEBUG_CHANNEL(shell) @@ -210,10 +216,11 @@ typedef struct { ICOM_VFIELD(IUnknown); DWORD ref; - ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder;; - ICOM_VTABLE(IPersistFolder)* lpvtblPersistFolder; + ICOM_VTABLE(IShellFolder2)* lpvtblShellFolder; + ICOM_VTABLE(IPersistFolder2)* lpvtblPersistFolder2; ICOM_VTABLE(IDropTarget)* lpvtblDropTarget; - + ICOM_VTABLE(ISFHelper)* lpvtblSFHelper; + IUnknown *pUnkOuter; /* used for aggregation */ CLSID* pclsid; @@ -227,29 +234,34 @@ typedef struct static struct ICOM_VTABLE(IUnknown) unkvt; static struct ICOM_VTABLE(IShellFolder2) sfvt; -static struct ICOM_VTABLE(IPersistFolder) psfvt; +static struct ICOM_VTABLE(IPersistFolder2) psfvt; static struct ICOM_VTABLE(IDropTarget) dtvt; +static struct ICOM_VTABLE(ISFHelper) shvt; static IShellFolder * ISF_MyComputer_Constructor(void); #define _IShellFolder2_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblShellFolder))) #define _ICOM_THIS_From_IShellFolder2(class, name) class* This = (class*)(((char*)name)-_IShellFolder2_Offset); -#define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder))) -#define _ICOM_THIS_From_IPersistFolder(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset); +#define _IPersistFolder_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblPersistFolder2))) +#define _ICOM_THIS_From_IPersistFolder2(class, name) class* This = (class*)(((char*)name)-_IPersistFolder_Offset); #define _IDropTarget_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblDropTarget))) #define _ICOM_THIS_From_IDropTarget(class, name) class* This = (class*)(((char*)name)-_IDropTarget_Offset); +#define _ISFHelper_Offset ((int)(&(((IGenericSFImpl*)0)->lpvtblSFHelper))) +#define _ICOM_THIS_From_ISFHelper(class, name) class* This = (class*)(((char*)name)-_ISFHelper_Offset); /* converts This to a interface pointer */ #define _IUnknown_(This) (IUnknown*)&(This->lpVtbl) #define _IShellFolder_(This) (IShellFolder*)&(This->lpvtblShellFolder) #define _IShellFolder2_(This) (IShellFolder2*)&(This->lpvtblShellFolder) -#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder) -#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder) +#define _IPersist_(This) (IPersist*)&(This->lpvtblPersistFolder2) +#define _IPersistFolder_(This) (IPersistFolder*)&(This->lpvtblPersistFolder2) +#define _IPersistFolder2_(This) (IPersistFolder2*)&(This->lpvtblPersistFolder2) #define _IDropTarget_(This) (IDropTarget*)&(This->lpvtblDropTarget) +#define _ISFHelper_(This) (ISFHelper*)&(This->lpvtblSFHelper) /************************************************************************** * registers clipboardformat once */ @@ -284,6 +296,8 @@ static HRESULT WINAPI IUnknown_fnQueryInterface( else if(IsEqualIID(riid, &IID_IShellFolder2)) *ppvObj = _IShellFolder_(This); else if(IsEqualIID(riid, &IID_IPersist)) *ppvObj = _IPersist_(This); else if(IsEqualIID(riid, &IID_IPersistFolder)) *ppvObj = _IPersistFolder_(This); + else if(IsEqualIID(riid, &IID_IPersistFolder2)) *ppvObj = _IPersistFolder2_(This); + else if(IsEqualIID(riid, &IID_ISFHelper)) *ppvObj = _ISFHelper_(This); else if(IsEqualIID(riid, &IID_IDropTarget)) { *ppvObj = _IDropTarget_(This); @@ -386,8 +400,10 @@ HRESULT IFSFolder_Constructor( sf->ref=1; ICOM_VTBL(sf)=&unkvt; sf->lpvtblShellFolder=&sfvt; - sf->lpvtblPersistFolder=&psfvt; + sf->lpvtblPersistFolder2=&psfvt; sf->lpvtblDropTarget=&dtvt; + sf->lpvtblSFHelper=&shvt; + sf->pclsid = (CLSID*)&CLSID_SFFile; sf->pUnkOuter = pUnkOuter ? pUnkOuter : _IUnknown_(sf); *ppv = _IUnknown_(sf); @@ -422,8 +438,10 @@ IShellFolder * IShellFolder_Constructor( ICOM_VTBL(sf)=&unkvt; sf->lpvtblShellFolder=&sfvt; - sf->lpvtblPersistFolder=&psfvt; + sf->lpvtblPersistFolder2=&psfvt; sf->lpvtblDropTarget=&dtvt; + sf->lpvtblSFHelper=&shvt; + sf->pclsid = (CLSID*)&CLSID_SFFile; sf->pUnkOuter = _IUnknown_(sf); @@ -939,7 +957,7 @@ static HRESULT WINAPI IShellFolder_fnGetUIObjectOf( IUnknown* pObj = NULL; HRESULT hr = E_INVALIDARG; - TRACE("(%p)->(%u,%u,apidl=%p,\n\tIID:%s,%p,%p)\n", + TRACE("(%p)->(0x%04x,%u,apidl=%p,\n\tIID:%s,%p,%p)\n", This,hwndOwner,cidl,apidl,debugstr_guid(riid),prgfInOut,ppvOut); if (ppvOut) @@ -948,7 +966,7 @@ static HRESULT WINAPI IShellFolder_fnGetUIObjectOf( if(IsEqualIID(riid, &IID_IContextMenu) && (cidl >= 1)) { - pObj = (LPUNKNOWN)IContextMenu_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl); + pObj = (LPUNKNOWN)ISvItemCm_Constructor((IShellFolder*)iface, This->absPidl, apidl, cidl); hr = S_OK; } else if (IsEqualIID(riid, &IID_IDataObject) &&(cidl >= 1)) @@ -1066,36 +1084,39 @@ static HRESULT WINAPI IShellFolder_fnSetNameOf( HWND hwndOwner, LPCITEMIDLIST pidl, /*simple pidl*/ LPCOLESTR lpName, - DWORD dw, + DWORD dwFlags, LPITEMIDLIST *pPidlOut) { _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) + char szSrc[MAX_PATH], szDest[MAX_PATH]; + int len; - FIXME("(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n", - This,hwndOwner,pidl,debugstr_w(lpName),dw,pPidlOut); + TRACE("(%p)->(%u,pidl=%p,%s,%lu,%p),stub!\n", + This,hwndOwner,pidl,debugstr_w(lpName),dwFlags,pPidlOut); - return E_NOTIMPL; -} - -/************************************************************************** -* IShellFolder_fnGetFolderPath -*/ -static HRESULT WINAPI IShellFolder_fnGetFolderPath(IShellFolder2 * iface, LPSTR lpszOut, DWORD dwOutSize) -{ - _ICOM_THIS_From_IShellFolder2(IGenericSFImpl, iface) + if (dwFlags & SHGDN_INFOLDER) + { + strcpy(szSrc, This->sMyPath); + PathAddBackslashA(szSrc); + len = strlen (szSrc); + _ILSimpleGetText(pidl, szSrc+len, MAX_PATH-len); + } + else + { + SHGetPathFromIDListA(pidl, szSrc); + } + strcpy(szDest, This->sMyPath); + PathAddBackslashA(szDest); + len = strlen (szDest); + lstrcpynWtoA(szDest+len, lpName, MAX_PATH-len); - TRACE("(%p)->(%p %lu)\n",This, lpszOut, dwOutSize); - - if (!lpszOut) return FALSE; - - *lpszOut=0; - - if (! This->sMyPath) return FALSE; - - lstrcpynA(lpszOut, This->sMyPath, dwOutSize); - - TRACE("-- (%p)->(return=%s)\n",This, lpszOut); - return TRUE; + TRACE("src=%s dest=%s\n", szSrc, szDest); + if (MoveFileA(szSrc, szDest)) + { + if (pPidlOut) *pPidlOut = SHSimpleIDListFromPathA(szDest); + return S_OK; + } + return E_FAIL; } static HRESULT WINAPI IShellFolder_fnGetDefaultSearchGUID( @@ -1240,6 +1261,250 @@ static ICOM_VTABLE(IShellFolder2) sfvt = IShellFolder_fnGetDetailsOf, IShellFolder_fnMapNameToSCID }; + +/**************************************************************************** + * ISFHelper for IShellFolder implementation + */ + +static HRESULT WINAPI ISFHelper_fnQueryInterface( + ISFHelper *iface, + REFIID riid, + LPVOID *ppvObj) +{ + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface); + + TRACE("(%p)\n", This); + + return IUnknown_QueryInterface(This->pUnkOuter, riid, ppvObj); +} + +static ULONG WINAPI ISFHelper_fnAddRef( + ISFHelper *iface) +{ + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface); + + TRACE("(%p)\n", This); + + return IUnknown_AddRef(This->pUnkOuter); +} + +static ULONG WINAPI ISFHelper_fnRelease( + ISFHelper *iface) +{ + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface); + + TRACE("(%p)\n", This); + + return IUnknown_Release(This->pUnkOuter); +} + + +/**************************************************************************** + * ISFHelper_fnAddFolder + * + * creates a unique folder name + */ + +static HRESULT WINAPI ISFHelper_fnGetUniqueName( + ISFHelper *iface, + LPSTR lpName, + UINT uLen) +{ + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface) + IEnumIDList * penum; + HRESULT hr; + char szText[MAX_PATH]; + char * szNewFolder = "New Folder"; + + TRACE("(%p)(%s %u)\n", This, lpName, uLen); + + if (uLen < strlen(szNewFolder) + 4) return E_POINTER; + + strcpy(lpName, szNewFolder); + + hr = IShellFolder_fnEnumObjects(_IShellFolder2_(This), 0, SHCONTF_FOLDERS | SHCONTF_NONFOLDERS | SHCONTF_INCLUDEHIDDEN, &penum); + if (penum) + { + LPITEMIDLIST pidl; + DWORD dwFetched; + int i=1; + +next: IEnumIDList_Reset(penum); + while(S_OK == IEnumIDList_Next(penum, 1, &pidl, &dwFetched) && dwFetched) + { + _ILSimpleGetText(pidl, szText, MAX_PATH); + if (0 == strcasecmp(szText, lpName)) + { + sprintf(lpName, "%s %d", szNewFolder, i++); + if (i > 99) + { + hr = E_FAIL; + break; + } + goto next; + } + } + + IEnumIDList_Release(penum); + } + return hr; +} + +/**************************************************************************** + * ISFHelper_fnAddFolder + * + * adds a new folder. + */ + +static HRESULT WINAPI ISFHelper_fnAddFolder( + ISFHelper *iface, + HWND hwnd, + LPCSTR lpName, + LPITEMIDLIST* ppidlOut) +{ + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface) + char lpstrNewDir[MAX_PATH]; + DWORD bRes; + HRESULT hres = E_FAIL; + + TRACE("(%p)(%s %p)\n", This, lpName, ppidlOut); + + strcpy(lpstrNewDir, This->sMyPath); + PathAddBackslashA(lpstrNewDir); + strcat(lpstrNewDir, lpName); + + bRes = CreateDirectoryA(lpstrNewDir, NULL); + + if (bRes) + { + LPITEMIDLIST pidl, pidlitem; + + pidlitem = SHSimpleIDListFromPathA(lpstrNewDir); + + pidl = ILCombine(This->absPidl, pidlitem); + SHChangeNotifyA(SHCNE_MKDIR, SHCNF_IDLIST, pidl, NULL); + SHFree(pidl); + + if (ppidlOut) *ppidlOut = pidlitem; + hres = S_OK; + } + else + { + char lpstrText[128+MAX_PATH]; + char lpstrTempText[128]; + char lpstrCaption[256]; + + /* Cannot Create folder because of permissions */ + LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_DENIED, lpstrTempText, sizeof(lpstrTempText)); + LoadStringA(shell32_hInstance, IDS_CREATEFOLDER_CAPTION, lpstrCaption, sizeof(lpstrCaption)); + sprintf(lpstrText,lpstrTempText, lpstrNewDir); + MessageBoxA(hwnd,lpstrText, lpstrCaption, MB_OK | MB_ICONEXCLAMATION); + } + + return hres; +} + +/**************************************************************************** + * ISFHelper_fnDeleteItems + * + * deletes items in folder + */ +static HRESULT WINAPI ISFHelper_fnDeleteItems( + ISFHelper *iface, + UINT cidl, + LPCITEMIDLIST* apidl) +{ + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface) + int i; + char szPath[MAX_PATH]; + + TRACE("(%p)(%u %p)\n", This, cidl, apidl); + + for(i=0; i< cidl; i++) + { + strcpy(szPath, This->sMyPath); + PathAddBackslashA(szPath); + _ILSimpleGetText(apidl[i], szPath+strlen(szPath), MAX_PATH); + + if (_ILIsFolder(apidl[i])) + { + LPITEMIDLIST pidl; + +/* if (! RemoveDirectoryA(szPath)) return E_FAIL; */ + MESSAGE("would delete %s\n", szPath); + pidl = ILCombine(This->absPidl, apidl[i]); + SHChangeNotifyA(SHCNE_RMDIR, SHCNF_IDLIST, pidl, NULL); + SHFree(pidl); + } + else if (_ILIsValue(apidl[i])) + { + LPITEMIDLIST pidl; + +/* if (! DeleteFileA(szPath)) return E_FAIL; */ + MESSAGE("would delete %s\n", szPath); + pidl = ILCombine(This->absPidl, apidl[i]); + SHChangeNotifyA(SHCNE_DELETE, SHCNF_IDLIST, pidl, NULL); + SHFree(pidl); + } + + } + return S_OK; +} + +/**************************************************************************** + * ISFHelper_fnCopyItems + * + * copys items to this folder + */ +static HRESULT WINAPI ISFHelper_fnCopyItems( + ISFHelper *iface, + IShellFolder* pSFFrom, + UINT cidl, + LPCITEMIDLIST *apidl) +{ + int i; + IPersistFolder2 * ppf2=NULL; + char szSrcPath[MAX_PATH], szDstPath[MAX_PATH]; + _ICOM_THIS_From_ISFHelper(IGenericSFImpl,iface); + + TRACE("(%p)->(%p,%u,%p)\n", This, pSFFrom, cidl, apidl); + + IShellFolder_QueryInterface(pSFFrom, &IID_IPersistFolder2, (LPVOID*)&ppf2); + if (ppf2) + { + LPITEMIDLIST pidl; + if (SUCCEEDED(IPersistFolder2_GetCurFolder(ppf2, &pidl))) + { + for (i=0; isMyPath); + PathAddBackslashA(szDstPath); + _ILSimpleGetText(apidl[i], szDstPath+strlen(szDstPath), MAX_PATH); + MESSAGE("would copy %s to %s\n", szSrcPath, szDstPath); + } + SHFree(pidl); + } + IPersistFolder2_Release(ppf2); + } + return S_OK; +} + +static ICOM_VTABLE(ISFHelper) shvt = +{ + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + ISFHelper_fnQueryInterface, + ISFHelper_fnAddRef, + ISFHelper_fnRelease, + ISFHelper_fnGetUniqueName, + ISFHelper_fnAddFolder, + ISFHelper_fnDeleteItems, + ISFHelper_fnCopyItems, +}; + /*********************************************************************** * [Desktopfolder] IShellFolder implementation */ @@ -1766,7 +2031,7 @@ static IShellFolder * ISF_MyComputer_Constructor(void) ICOM_VTBL(sf)=&unkvt; sf->lpvtblShellFolder=&sfmcvt; - sf->lpvtblPersistFolder = &psfvt; + sf->lpvtblPersistFolder2 = &psfvt; sf->pclsid = (CLSID*)&CLSID_SFMyComp; sf->absPidl=_ILCreateMyComputer(); /* my qualified pidl */ sf->pUnkOuter = (IUnknown *) &sf->lpVtbl; @@ -2220,12 +2485,12 @@ static ICOM_VTABLE(IShellFolder2) sfmcvt = * ISFPersistFolder_QueryInterface (IUnknown) * */ -static HRESULT WINAPI ISFPersistFolder_QueryInterface( - IPersistFolder * iface, +static HRESULT WINAPI ISFPersistFolder2_QueryInterface( + IPersistFolder2 * iface, REFIID iid, LPVOID* ppvObj) { - _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); + _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); @@ -2236,10 +2501,10 @@ static HRESULT WINAPI ISFPersistFolder_QueryInterface( * ISFPersistFolder_AddRef (IUnknown) * */ -static ULONG WINAPI ISFPersistFolder_AddRef( - IPersistFolder * iface) +static ULONG WINAPI ISFPersistFolder2_AddRef( + IPersistFolder2 * iface) { - _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); + _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); @@ -2250,10 +2515,10 @@ static ULONG WINAPI ISFPersistFolder_AddRef( * ISFPersistFolder_Release (IUnknown) * */ -static ULONG WINAPI ISFPersistFolder_Release( - IPersistFolder * iface) +static ULONG WINAPI ISFPersistFolder2_Release( + IPersistFolder2 * iface) { - _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); + _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); @@ -2263,11 +2528,11 @@ static ULONG WINAPI ISFPersistFolder_Release( /************************************************************************ * ISFPersistFolder_GetClassID (IPersist) */ -static HRESULT WINAPI ISFPersistFolder_GetClassID( - IPersistFolder * iface, +static HRESULT WINAPI ISFPersistFolder2_GetClassID( + IPersistFolder2 * iface, CLSID * lpClassId) { - _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); + _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)\n", This); @@ -2283,12 +2548,12 @@ static HRESULT WINAPI ISFPersistFolder_GetClassID( * NOTES * sMyPath is not set. Don't know how to handle in a non rooted environment. */ -static HRESULT WINAPI ISFPersistFolder_Initialize( - IPersistFolder * iface, +static HRESULT WINAPI ISFPersistFolder2_Initialize( + IPersistFolder2 * iface, LPCITEMIDLIST pidl) { char sTemp[MAX_PATH]; - _ICOM_THIS_From_IPersistFolder(IGenericSFImpl, iface); + _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); TRACE("(%p)->(%p)\n", This, pidl); @@ -2319,14 +2584,33 @@ static HRESULT WINAPI ISFPersistFolder_Initialize( return S_OK; } -static ICOM_VTABLE(IPersistFolder) psfvt = +/************************************************************************** +* IPersistFolder2_fnGetCurFolder +*/ +static HRESULT WINAPI ISFPersistFolder2_fnGetCurFolder( + IPersistFolder2 * iface, + LPITEMIDLIST * pidl) +{ + _ICOM_THIS_From_IPersistFolder2(IGenericSFImpl, iface); + + TRACE("(%p)->(%p)\n",This, pidl); + + if (!pidl) return E_POINTER; + + *pidl = ILClone(This->absPidl); + + return S_OK; +} + +static ICOM_VTABLE(IPersistFolder2) psfvt = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE - ISFPersistFolder_QueryInterface, - ISFPersistFolder_AddRef, - ISFPersistFolder_Release, - ISFPersistFolder_GetClassID, - ISFPersistFolder_Initialize + ISFPersistFolder2_QueryInterface, + ISFPersistFolder2_AddRef, + ISFPersistFolder2_Release, + ISFPersistFolder2_GetClassID, + ISFPersistFolder2_Initialize, + ISFPersistFolder2_fnGetCurFolder }; /**************************************************************************** @@ -2462,4 +2746,3 @@ static struct ICOM_VTABLE(IDropTarget) dtvt = ISFDropTarget_DragLeave, ISFDropTarget_Drop }; -