itbdrop.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 13k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. //
  2. //  ITBDROP.CPP
  3. //  routines for implementing OLE drop target capability
  4. //  within the internet toolbar control
  5. //
  6. //  History:
  7. //      07/13/96 t-mkim     Created
  8. //      10/13/96 chrisg     massive cleanup
  9. //
  10. #include "priv.h"
  11. #include "itbdrop.h"
  12. #include "sccls.h"
  13. #include "resource.h"
  14. #include "mluisupp.h"
  15. #ifdef UNIX
  16. #ifdef SIZEOF
  17. #undef SIZEOF
  18. #endif
  19. #define SIZEOF(x)   sizeof(x)       // has been checked for UNICODE correctness
  20. #endif
  21. #define MAX_NAME_QUICKLINK 40
  22. // Data type of the incoming data object.
  23. #define CITBDTYPE_NONE      0
  24. #define CITBDTYPE_HDROP     1
  25. #define CITBDTYPE_URL       2
  26. #define CITBDTYPE_TEXT      3
  27. //  get an IDropTarget for shell special folders
  28. //
  29. HRESULT _GetSpecialDropTarget(UINT csidl, IDropTarget **ppdtgt)
  30. {
  31.     IShellFolder *psfDesktop;
  32.     *ppdtgt = NULL;
  33.     HRESULT hres = SHGetDesktopFolder(&psfDesktop);
  34.     if (SUCCEEDED(hres))
  35.     {
  36.         LPITEMIDLIST pidl;
  37.         hres = SHGetSpecialFolderLocation(NULL, csidl, &pidl);
  38.         if (SUCCEEDED(hres))
  39.         {
  40.             IShellFolder *psf;
  41.             hres = psfDesktop->BindToObject(pidl, NULL, IID_IShellFolder, (void **)&psf);
  42.             if (SUCCEEDED(hres))
  43.             {
  44.                 hres = psf->CreateViewObject(NULL, IID_IDropTarget, (void **)ppdtgt);
  45.                 psf->Release();
  46.             }
  47.             ILFree(pidl);
  48.         }
  49.         psfDesktop->Release();
  50.     }
  51.     return hres;
  52. }
  53. //  Takes a variety of inputs and returns a string for drop targets.
  54. //  szUrl:    the URL
  55. //  szName:   the name (for quicklinks and the confo dialog boxes)
  56. //  returns:  NOERROR if succeeded
  57. //
  58. HRESULT _GetURLData(IDataObject *pdtobj, int iDropType, TCHAR *pszUrl, DWORD cchUrl,  TCHAR *pszName)
  59. {
  60.     HRESULT hRes = NOERROR;
  61.     STGMEDIUM stgmedium;
  62.     UINT cfFormat;
  63.     *pszName = 0;
  64.     *pszUrl = 0;
  65.     switch (iDropType)
  66.     {
  67.     case CITBDTYPE_HDROP:
  68.         cfFormat = CF_HDROP;
  69.         break;
  70.     case CITBDTYPE_URL:
  71.         InitClipboardFormats();
  72.         cfFormat = g_cfURL;
  73.         break;
  74.     case CITBDTYPE_TEXT:
  75.         cfFormat = CF_TEXT;
  76.         break;
  77.     default:
  78.         return E_UNEXPECTED;
  79.     }
  80.     // Get the parse string
  81.     LPCSTR pszURL = (LPCSTR)DataObj_GetDataOfType(pdtobj, cfFormat, &stgmedium);
  82.     if (pszURL)
  83.     {
  84.         if (iDropType == CITBDTYPE_HDROP)
  85.         {
  86.             TCHAR szPath[MAX_PATH];
  87.             SHFILEINFO sfi;
  88.             DWORD_PTR bGotInfo;
  89.             ASSERT(stgmedium.tymed == TYMED_HGLOBAL);
  90.             DragQueryFile((HDROP)stgmedium.hGlobal, 0, szPath, SIZEOF(szPath));
  91.             // defaults...
  92.             lstrcpyn(pszUrl, szPath, MAX_URL_STRING);
  93.             lstrcpyn(pszName, szPath, MAX_NAME_QUICKLINK);
  94.             bGotInfo = SHGetFileInfo(szPath, 0, &sfi, sizeof(sfi), SHGFI_DISPLAYNAME | SHGFI_ATTRIBUTES);
  95.             if (bGotInfo)
  96.                 lstrcpyn(pszName, sfi.szDisplayName, MAX_NAME_QUICKLINK);
  97.             if (bGotInfo && (sfi.dwAttributes & SFGAO_LINK))
  98.             {
  99.                 LPITEMIDLIST pidl;
  100.                 if (SUCCEEDED(GetLinkTargetIDList(szPath, pszUrl, cchUrl, &pidl)))
  101.                 {
  102.                     // we only care about the name... thanks anyway.
  103.                     ILFree(pidl);
  104.                 }
  105.             }
  106.         }
  107.         else
  108.         {
  109. #ifdef UNICODE
  110.             WCHAR wszURL[MAX_URL_STRING];
  111.             SHAnsiToUnicode(pszURL, wszURL, ARRAYSIZE(wszURL));
  112.             LPTSTR pszURLData = wszURL;
  113. #else
  114.             LPTSTR pszURLData = pszURL;
  115. #endif
  116.             if (iDropType == CITBDTYPE_URL)
  117.             {
  118.                 // defaults
  119.                 lstrcpyn(pszUrl,  pszURLData, MAX_URL_STRING);
  120.                 lstrcpyn(pszName, pszURLData, MAX_NAME_QUICKLINK);
  121.                 WCHAR szPath[MAX_PATH];
  122.                 if (SUCCEEDED(DataObj_GetNameFromFileDescriptor(pdtobj, szPath, ARRAYSIZE(szPath))))
  123.                     PathToDisplayNameW(szPath, pszName, MAX_NAME_QUICKLINK);
  124.                     
  125.             }
  126.             else // if (iDropType == CITBDTYPE_TEXT)
  127.             {
  128.                 ASSERT(iDropType == CITBDTYPE_TEXT);
  129.                 lstrcpyn(pszUrl, pszURLData, MAX_URL_STRING);
  130.                 lstrcpyn(pszName, pszURLData, MAX_NAME_QUICKLINK);
  131.             }
  132.         }
  133.     
  134.         ReleaseStgMediumHGLOBAL(&stgmedium);
  135.     }
  136.     else
  137.     {
  138.         hRes = E_FAIL;
  139.     }
  140.     return hRes;
  141. }
  142. //  Displays a dialog asking for confirmation of drop-set operations.
  143. //  Returns: User's response to the dialog box: YES = TRUE, NO = FALSE
  144. //
  145. BOOL _ConfirmChangeQuickLink(HWND hwndParent, TCHAR *pszName, int iTarget)
  146. {
  147.     MSGBOXPARAMS mbp;
  148.     TCHAR szHeader[64];
  149.     TCHAR szBuffer [MAX_NAME_QUICKLINK + 64];
  150.     TCHAR szCaption [MAX_NAME_QUICKLINK + 64];
  151.     UINT titleID, textID, iconID;
  152.     switch (iTarget)
  153.     {
  154.     case TBIDM_HOME:
  155.         titleID = IDS_SETHOME_TITLE;
  156.         textID = IDS_SETHOME_TEXT;
  157.         iconID = IDI_HOMEPAGE;
  158.         break;
  159. #if 0
  160.     case TBIDM_SEARCH:
  161.         titleID = IDS_SETSEARCH_TITLE;
  162.         textID = IDS_SETSEARCH_TEXT;
  163.         iconID = IDI_FRAME; // Warning if you unif0 this: IDI_FRAME is not in this dll
  164.         break;
  165. #endif
  166.     default:
  167.         return FALSE;           // We should never get here!
  168.     }
  169.     mbp.cbSize = sizeof (MSGBOXPARAMS);
  170.     mbp.hwndOwner = hwndParent;
  171.     mbp.hInstance = HinstShdocvw();
  172.     mbp.dwStyle = MB_YESNO | MB_USERICON;
  173.     MLLoadString(titleID, szCaption, ARRAYSIZE (szCaption));
  174.     mbp.lpszCaption = szCaption;
  175.     mbp.lpszIcon = MAKEINTRESOURCE (iconID);
  176.     mbp.dwContextHelpId = 0;
  177.     mbp.lpfnMsgBoxCallback = NULL;
  178.     mbp.dwLanguageId = LANGIDFROMLCID (g_lcidLocale);
  179.     MLLoadString(textID, szHeader, ARRAYSIZE (szHeader));
  180.     wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szHeader, pszName);
  181.     mbp.lpszText = szBuffer;
  182.     return MessageBoxIndirect(&mbp) == IDYES;
  183. }
  184. //  Creates an instance of CITBarDropTarget. ptr is a pointer to the parent
  185. //  CInternetToolbar.
  186. //
  187. CITBarDropTarget::CITBarDropTarget(HWND hwnd, int iTarget) : 
  188.     _cRef(1), _iDropType(CITBDTYPE_NONE), _hwndParent(hwnd), _iTarget(iTarget)
  189. {
  190. }
  191. STDMETHODIMP CITBarDropTarget::QueryInterface(REFIID iid, void **ppvObj)
  192. {
  193.     if (IsEqualIID (iid, IID_IUnknown) || IsEqualIID (iid, IID_IDropTarget))
  194.     { 
  195.         *ppvObj = SAFECAST(this, IDropTarget*);
  196.         AddRef(); 
  197.         return NOERROR; 
  198.     } 
  199.     *ppvObj = NULL; 
  200.     return E_NOINTERFACE; 
  201. }
  202. STDMETHODIMP_(ULONG) CITBarDropTarget::AddRef()
  203. {
  204.     _cRef++;
  205.     return _cRef;
  206. }
  207. STDMETHODIMP_(ULONG) CITBarDropTarget::Release()
  208. {
  209.     _cRef--;
  210.     if (_cRef > 0)
  211.         return _cRef;
  212.     delete this;
  213.     return 0;
  214. }
  215. typedef struct
  216. {
  217.     int iTarget;
  218.     int iDropType;
  219.     HWND hwnd;
  220.     TCHAR szUrl [MAX_URL_STRING];
  221.     TCHAR szName [MAX_NAME_QUICKLINK];
  222. } DROPDATA;
  223. DWORD CALLBACK ITBarDropThreadProc(void *pv)
  224. {
  225.     DROPDATA *pdd = (DROPDATA *)pv;
  226.     switch (pdd->iTarget)
  227.     {
  228.     case TBIDM_HOME:
  229.         if (pdd->iDropType != CITBDTYPE_TEXT)
  230.         {
  231.             if (_ConfirmChangeQuickLink(pdd->hwnd, pdd->szName, pdd->iTarget)) {
  232.                 ASSERT(pdd->iTarget == TBIDM_HOME);
  233.                 // currently don't support pdd->itarget == TBIDM_SEARCH
  234.                 //(pdd->iTarget == TBIDM_HOME) ? DVIDM_GOHOME : DVIDM_GOSEARCH);
  235.                 _SetStdLocation(pdd->szUrl, DVIDM_GOHOME);
  236.             }
  237.         }
  238.         break;
  239.     case TBIDM_SEARCH:
  240.         ASSERT(0);
  241.         break;
  242.     }
  243.     LocalFree(pdd);
  244.     return 0;
  245. }
  246. STDMETHODIMP CITBarDropTarget::DragEnter(IDataObject *pdtobj, DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  247. {
  248.     ASSERT(pdtobj);
  249.     _DragEnter(_hwndParent, ptl, pdtobj);
  250.     if (_iTarget == TBIDM_FAVORITES)
  251.     {
  252.         if (SUCCEEDED(_GetSpecialDropTarget(CSIDL_FAVORITES, &_pdrop)))
  253.             _pdrop->DragEnter(pdtobj, grfKeyState, ptl, pdwEffect);
  254.         else
  255.             *pdwEffect = DROPEFFECT_NONE;
  256.         return NOERROR;
  257.     }
  258.     else if (_iTarget == TBIDM_HOME)
  259.     {
  260.         HKEY                hkeyRest = 0;
  261.         DWORD               dwValue = 0;
  262.         DWORD               dwLen = sizeof(DWORD);
  263.         // Check if setting home page is restricted
  264.     
  265.         if (RegOpenKeyEx(HKEY_CURRENT_USER, REGSTR_SET_HOMEPAGE_RESTRICTION, 0,
  266.                          KEY_READ, &hkeyRest) == ERROR_SUCCESS)
  267.         {
  268.             if (RegQueryValueEx(hkeyRest, REGVAL_HOMEPAGE_RESTRICTION, NULL, NULL,
  269.                                 (LPBYTE)&dwValue, &dwLen) == ERROR_SUCCESS
  270.                 && dwValue)
  271.             {
  272.                 return E_ACCESSDENIED;
  273.             }
  274.     
  275.             RegCloseKey(hkeyRest);
  276.         }
  277.     }
  278.     
  279.     InitClipboardFormats();
  280.     // Find the drop object's data format.
  281.     FORMATETC fe = {g_cfURL, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
  282.     if (NOERROR == pdtobj->QueryGetData (&fe))
  283.     {
  284.         _iDropType = CITBDTYPE_URL;
  285.     }
  286.     else if (fe.cfFormat = CF_HDROP, NOERROR == pdtobj->QueryGetData (&fe))
  287.     {
  288.         _iDropType = CITBDTYPE_HDROP;
  289.     }
  290.     else if (fe.cfFormat = CF_TEXT, NOERROR == pdtobj->QueryGetData (&fe))
  291.     {
  292.         _iDropType = CITBDTYPE_TEXT;
  293.         // We want to eventually pick through the text for an
  294.         // URL, but right now we just leave it unmolested.
  295.     }
  296.     DragOver (grfKeyState, ptl, pdwEffect);
  297.     return NOERROR;
  298. }
  299. STDMETHODIMP CITBarDropTarget::DragOver(DWORD grfKeyState, POINTL ptl, DWORD *pdwEffect)
  300. {
  301.     DWORD dwEffectAvail;
  302.     _DragMove(_hwndParent, ptl);
  303.     if (_iTarget == TBIDM_FAVORITES)
  304.     {
  305.         if (_pdrop)
  306.             return _pdrop->DragOver(grfKeyState, ptl, pdwEffect);
  307.         *pdwEffect = DROPEFFECT_NONE;
  308.         return NOERROR;
  309.     }
  310.     ASSERT(!_pdrop);
  311.     if (_iDropType == CITBDTYPE_NONE)
  312.     {
  313.         *pdwEffect = DROPEFFECT_NONE;
  314.         return NOERROR;
  315.     }
  316.     dwEffectAvail = DROPEFFECT_NONE;
  317.     switch (_iTarget)
  318.     {
  319.         case TBIDM_HOME:
  320.         case TBIDM_SEARCH:
  321.             if (_iDropType == CITBDTYPE_TEXT)
  322.             {
  323.                 // CF_TEXT doesn't do link.
  324.             }
  325.             else
  326.                 dwEffectAvail = DROPEFFECT_LINK;
  327.             break;
  328.     }
  329.     *pdwEffect &= dwEffectAvail;
  330.     return NOERROR;
  331. }
  332. STDMETHODIMP CITBarDropTarget::Drop(IDataObject *pdtobj, DWORD grfKeyState, POINTL pt, DWORD *pdwEffect)
  333. {
  334.     BOOL fSafe = TRUE;
  335.     LPITEMIDLIST pidl;
  336.     if (_pdrop)
  337.     {
  338.         ASSERT(_iTarget == TBIDM_FAVORITES);
  339.         //
  340.         // Force a linking since we are passing straight through to the folder.
  341.         // This avoids confusion when dragging to the toolbar button.
  342.         //
  343.         // BUGBUG: this should really go through the "Add to Favorites" UI
  344.         //
  345.         // When forcing a link, make sure that you can move it. If you cannot move it,
  346.         // then we rely on the prefered effect of the data object. Why? Well, the history
  347.         // folder only allows a copy. If you just whack this to LINK, the shell folder hoses
  348.         // the drag images (Does a DAD_SetDragImage(NULL), blowing away the information about
  349.         // the last locked window, without unlocking it.). So, if you can move the item, 
  350.         // you can link to it (I guess), but if you cannot move it, do whatever. 
  351.         //     - (lamadio) 1.3.99
  352.         if (*pdwEffect & DROPEFFECT_MOVE)
  353.             *pdwEffect = DROPEFFECT_LINK;
  354.         if (TBIDM_FAVORITES == _iTarget &&
  355.             SUCCEEDED(SHPidlFromDataObject(pdtobj, &pidl, NULL, 0)))
  356.         {
  357.             fSafe = IEIsLinkSafe(_hwndParent, pidl, ILS_ADDTOFAV);
  358.             ILFree(pidl);
  359.         }
  360.         if (fSafe)
  361.         {
  362.             _pdrop->Drop(pdtobj, grfKeyState, pt, pdwEffect);
  363.         }
  364.         else
  365.         {
  366.             pdtobj->Release();  // Match Release called in _pdrop->Drop.
  367.         }
  368.        
  369.         DAD_DragLeave();
  370.         _pdrop->Release();
  371.         _pdrop = NULL;
  372.     }
  373.     else
  374.     {
  375.         if (TBIDM_HOME == _iTarget &&
  376.             SUCCEEDED(SHPidlFromDataObject(pdtobj, &pidl, NULL, 0)))
  377.         {
  378.             fSafe = IEIsLinkSafe(_hwndParent, pidl, ILS_HOME);
  379.             ILFree(pidl);
  380.         }
  381.         if (fSafe)
  382.         {
  383.             DROPDATA *pdd = (DROPDATA *)LocalAlloc (LPTR, sizeof(DROPDATA));
  384.             if (pdd)
  385.             {
  386.                 pdd->iTarget = _iTarget;
  387.                 pdd->iDropType = _iDropType;
  388.                 pdd->hwnd = _hwndParent;
  389.                 // do this async so we don't block the source of the drag durring our UI
  390.                 if (FAILED(_GetURLData(pdtobj, _iDropType, pdd->szUrl, ARRAYSIZE(pdd->szUrl), pdd->szName)) ||
  391.                     !SHCreateThread(ITBarDropThreadProc, pdd, 0, NULL))
  392.                     LocalFree(pdd);
  393.             }
  394.         }
  395.         DragLeave();
  396.     }
  397.     return NOERROR;
  398. }
  399. STDMETHODIMP CITBarDropTarget::DragLeave(void)
  400. {
  401.     DAD_DragLeave();
  402.     // Check if we should to pass to the favorites dt.
  403.     if (_pdrop)
  404.     {
  405.         ASSERT(_iTarget == TBIDM_FAVORITES);
  406.         _pdrop->DragLeave();
  407.         _pdrop->Release();
  408.         _pdrop = NULL;
  409.     }
  410.     _iDropType = CITBDTYPE_NONE;
  411.     return NOERROR;
  412. }