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

Windows Kernel

Development Platform:

Visual C++

  1. #include "shellprv.h"
  2. #pragma  hdrstop
  3. // warning: this will fail given a UNICODE hDrop on an ANSI build and
  4. // the DRAGINFO is esentially a TCHAR struct with no A/W versions exported
  5. //
  6. // in:
  7. //      hDrop   drop handle
  8. //
  9. // out:
  10. //      a bunch of info about the hdrop
  11. //      (mostly the pointer to the double NULL file name list)
  12. //
  13. // returns:
  14. //      TRUE    the DRAGINFO struct was filled in
  15. //      FALSE   the hDrop was bad
  16. //
  17. STDAPI_(BOOL) DragQueryInfo(HDROP hDrop, DRAGINFO *pdi)
  18. {
  19.     if (hDrop && (pdi->uSize == SIZEOF(DRAGINFO))) 
  20.     {
  21.         LPDROPFILES lpdfx = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop);
  22.         
  23.         pdi->lpFileList = NULL;
  24.         
  25.         if (lpdfx)
  26.         {
  27.             LPTSTR lpOldFileList;
  28.             if (LOWORD(lpdfx->pFiles) == SIZEOF(DROPFILES16))
  29.             {
  30.                 //
  31.                 // This is Win31-stye HDROP
  32.                 //
  33.                 LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfx;
  34.                 pdi->pt.x  = pdf16->pt.x;
  35.                 pdi->pt.y  = pdf16->pt.y;
  36.                 pdi->fNC   = pdf16->fNC;
  37.                 pdi->grfKeyState = 0;
  38.                 lpOldFileList = (LPTSTR)((LPBYTE)pdf16 + pdf16->pFiles);
  39.             }
  40.             else
  41.             {
  42.                 //
  43.                 // This is a new (NT-compatible) HDROP.
  44.                 //
  45.                 pdi->pt.x  = lpdfx->pt.x;
  46.                 pdi->pt.y  = lpdfx->pt.y;
  47.                 pdi->fNC   = lpdfx->fNC;
  48.                 pdi->grfKeyState = 0;
  49.                 lpOldFileList = (LPTSTR)((LPBYTE)lpdfx + lpdfx->pFiles);
  50.                 
  51.                 // there could be other data in there, but all
  52.                 // the HDROPs we build should be this size
  53.                 ASSERT(lpdfx->pFiles == SIZEOF(DROPFILES));
  54.             }
  55.             
  56.             {
  57.                 BOOL fListMatchesBuild;
  58.                 
  59. #ifdef UNICODE
  60.                 if ((LOWORD(lpdfx->pFiles) == SIZEOF(DROPFILES16)) || lpdfx->fWide == FALSE)
  61.                 {
  62.                     fListMatchesBuild = FALSE;
  63.                 }
  64.                 else
  65.                 {
  66.                     fListMatchesBuild = TRUE;
  67.                 }
  68. #else
  69.                 if ((LOWORD(lpdfx->pFiles) != SIZEOF(DROPFILES16)) && lpdfx->fWide == TRUE)
  70.                 {
  71.                     ASSERT(0 && "Unicode drop to Ansi explorer not supported");
  72.                     GlobalUnlock((HGLOBAL)hDrop);
  73.                     return FALSE;
  74.                 }
  75.                 else
  76.                 {
  77.                     fListMatchesBuild = TRUE;
  78.                 }
  79. #endif
  80.                 if (fListMatchesBuild)
  81.                 {
  82.                     LPTSTR pTStr = (LPTSTR) lpOldFileList;
  83.                     LPTSTR pNewFileList;
  84.                     UINT   cChar;
  85.                     
  86.                     // Look for the end of the file list
  87.                     
  88.                     while (*pTStr || *(pTStr + 1))
  89.                     {
  90.                         pTStr++;
  91.                     }
  92.                     pTStr++;    // Advance to last NUL of double terminator
  93.                     
  94.                     cChar = (UINT)(pTStr - lpOldFileList);
  95.                     
  96.                     pNewFileList = (LPTSTR) SHAlloc((cChar + 1) * SIZEOF(TCHAR));
  97.                     if (NULL == pNewFileList)
  98.                     {
  99.                         GlobalUnlock((HGLOBAL)hDrop);
  100.                         return FALSE;
  101.                     }
  102.                     
  103.                     // Copy strings to new buffer and set LPDROPINFO filelist
  104.                     // pointer to point to this new buffer
  105.                     
  106.                     CopyMemory(pNewFileList, lpOldFileList, ((cChar + 1) * SIZEOF(TCHAR)));
  107.                     pdi->lpFileList = pNewFileList;
  108.                 }
  109.                 else
  110.                 {
  111.                     LPXSTR pXStr = (LPXSTR) lpOldFileList;
  112.                     LPTSTR pNewFileList;
  113.                     LPTSTR pSaveFileList;
  114.                     UINT   cChar;
  115.                     UINT   cchConverted;
  116.                     
  117.                     // Look for the end of the file list
  118.                     
  119.                     while (*pXStr || (*(pXStr + 1)))
  120.                     {
  121.                         pXStr++;
  122.                     }
  123.                     pXStr++;   // Advance to the last NUL of the double terminator
  124.                     
  125.                     cChar = (UINT)(pXStr - ((LPXSTR) lpOldFileList));
  126.                     
  127.                     pNewFileList = (LPTSTR) SHAlloc((cChar + 1) * SIZEOF(TCHAR));
  128.                     if (NULL == pNewFileList)
  129.                     {
  130.                         GlobalUnlock((HGLOBAL)hDrop);
  131.                         return FALSE;
  132.                     }
  133.                     pSaveFileList = pNewFileList;
  134.                     
  135.                     pXStr = (LPXSTR) lpOldFileList;
  136.                     
  137.                     do
  138.                     {
  139. #ifdef UNICODE
  140.                         cchConverted = MultiByteToWideChar(CP_ACP, 0, pXStr, -1, 
  141.                             pNewFileList, ((cChar + 1) * SIZEOF(TCHAR)));        // Not really, but... "trust me"
  142.                         
  143. #else
  144.                         ASSERT(0 && "Unicode drop to Ansi explorer not supported");
  145.                         cchConverted = 0;
  146. #endif
  147.                         
  148.                         if (0 == cchConverted)
  149.                         {
  150.                             ASSERT(0 && "Unable to convert HDROP filename ANSI -> UNICODE");
  151.                             GlobalUnlock((HGLOBAL)hDrop);
  152.                             SHFree(pSaveFileList);
  153.                             return FALSE;
  154.                         }
  155.                         
  156.                         pNewFileList += cchConverted;
  157.                         pXStr += lstrlenX(pXStr) + 1;
  158.                     } while (*pXStr);
  159.                     
  160.                     // Add the double-null-terminator to the output list
  161.                     
  162.                     *pNewFileList = 0;
  163.                     pdi->lpFileList = pSaveFileList;
  164.                 }
  165.             }
  166.             
  167.             GlobalUnlock((HGLOBAL)hDrop);
  168.             
  169.             return TRUE;
  170.         }
  171.     }
  172.     return FALSE;
  173. }
  174. // 3.1 API
  175. STDAPI_(BOOL) DragQueryPoint(HDROP hDrop, POINT *ppt)
  176. {
  177.     BOOL fRet = FALSE;
  178.     LPDROPFILES lpdfs = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop);
  179.     if (lpdfs)
  180.     {
  181.         if (LOWORD(lpdfs->pFiles) == SIZEOF(DROPFILES16))
  182.         {
  183.             //
  184.             // This is Win31-stye HDROP
  185.             //
  186.             LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfs;
  187.             ppt->x = pdf16->pt.x;
  188.             ppt->y = pdf16->pt.y;
  189.             fRet = !pdf16->fNC;
  190.         }
  191.         else
  192.         {
  193.             //
  194.             // This is a new (NT-compatible) HDROP
  195.             //
  196.             ppt->x = (UINT)lpdfs->pt.x;
  197.             ppt->y = (UINT)lpdfs->pt.y;
  198.             fRet = !lpdfs->fNC;
  199.             // there could be other data in there, but all
  200.             // the HDROPs we build should be this size
  201.             ASSERT(lpdfs->pFiles == SIZEOF(DROPFILES));
  202.         }
  203.         GlobalUnlock((HGLOBAL)hDrop);
  204.     }
  205.     return fRet;
  206. }
  207. #ifdef WINNT
  208. //
  209. // Unfortunately we need it split out this way because WOW needs to
  210. // able to call a function named DragQueryFileAorW (so it can shorten them)
  211. // BUGBUG - BobDay - If there is time, try to change WOW and the SHELL at
  212. // the same time so that they don't need this function
  213. //
  214. STDAPI_(UINT) DragQueryFileAorW(HDROP hDrop, UINT iFile, void *lpFile, UINT cb, BOOL fNeedAnsi, BOOL fShorten)
  215. {
  216.     UINT i;
  217.     LPDROPFILESTRUCT lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop);
  218.     if (lpdfs)
  219.     {
  220.         // see if it is the new format
  221.         BOOL fWide = LOWORD(lpdfs->pFiles) == SIZEOF(DROPFILES) && lpdfs->fWide;
  222.         if (fWide)
  223.         {
  224.             LPWSTR lpList;
  225.             WCHAR szPath[MAX_PATH];
  226.             //
  227.             // UNICODE HDROP
  228.             //
  229.             lpList = (LPWSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  230.             // find either the number of files or the start of the file
  231.             // we're looking for
  232.             //
  233.             for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++)
  234.             {
  235.                 while (*lpList++)
  236.                     ;
  237.             }
  238.             if (iFile == (UINT)-1)
  239.                 goto Exit;
  240.             iFile = i = lstrlenW(lpList);
  241.             if (fShorten && iFile < MAX_PATH)
  242.             {
  243.                 wcscpy(szPath, lpList);
  244.                 SheShortenPathW(szPath, TRUE);
  245.                 lpList = szPath;
  246.                 iFile = i = lstrlenW(lpList);
  247.             }
  248.             if (fNeedAnsi)
  249.             {
  250.                 // Do not assume that a count of characters == a count of bytes
  251.                 i = WideCharToMultiByte(CP_ACP, 0, lpList, -1, NULL, 0, NULL, NULL);
  252.                 iFile = i ? --i : i;
  253.             }
  254.             if (!i || !cb || !lpFile)
  255.                 goto Exit;
  256.             if (fNeedAnsi) 
  257.             {
  258.                 SHUnicodeToAnsi(lpList, (LPSTR)lpFile, cb);
  259.             } 
  260.             else 
  261.             {
  262.                 cb--;
  263.                 if (cb < i)
  264.                     i = cb;
  265.                 lstrcpynW((LPWSTR)lpFile, lpList, i + 1);
  266.             }
  267.         }
  268.         else
  269.         {
  270.             LPSTR lpList;
  271.             CHAR szPath[MAX_PATH];
  272.             //
  273.             // This is Win31-style HDROP or an ANSI NT Style HDROP
  274.             //
  275.             lpList = (LPSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  276.             // find either the number of files or the start of the file
  277.             // we're looking for
  278.             //
  279.             for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++)
  280.             {
  281.                 while (*lpList++)
  282.                     ;
  283.             }
  284.             if (iFile == (UINT)-1)
  285.                 goto Exit;
  286.             iFile = i = lstrlenA(lpList);
  287.             if (fShorten && iFile < MAX_PATH)
  288.             {
  289.                 strcpy(szPath, lpList);
  290.                 SheShortenPathA(szPath, TRUE);
  291.                 lpList = szPath;
  292.                 iFile = i = lstrlenA(lpList);
  293.             }
  294.             if (!fNeedAnsi)
  295.             {
  296.                 i = MultiByteToWideChar(CP_ACP, 0, lpList, -1, NULL, 0);
  297.                 iFile = i ? --i : i;
  298.             }
  299.             if (!i || !cb || !lpFile)
  300.                 goto Exit;
  301.             if (fNeedAnsi) 
  302.             {
  303.                 cb--;
  304.                 if (cb < i)
  305.                     i = cb;
  306.     
  307.                 lstrcpynA((LPSTR)lpFile, lpList, i + 1);
  308.             } 
  309.             else 
  310.             {
  311.                 SHAnsiToUnicode(lpList, (LPWSTR)lpFile, cb);
  312.             }
  313.         }
  314.     }
  315.     i = iFile;
  316. Exit:
  317.     GlobalUnlock(hDrop);
  318.     return i;
  319. }
  320. STDAPI_(UINT) DragQueryFileW(HDROP hDrop, UINT wFile, LPWSTR lpFile, UINT cb)
  321. {
  322.    return DragQueryFileAorW(hDrop, wFile, lpFile, cb, FALSE, FALSE);
  323. }
  324. STDAPI_(UINT) DragQueryFileA(HDROP hDrop, UINT wFile, LPSTR lpFile, UINT cb)
  325. {
  326.    return DragQueryFileAorW(hDrop, wFile, lpFile, cb, TRUE, FALSE);
  327. }
  328. #else // WINNT
  329. STDAPI_(UINT) DragQueryFile(HDROP hDrop, UINT iFile, LPTSTR lpFile, UINT cb)
  330. {
  331.     LPTSTR lpList;
  332.     int i;
  333.     LPDROPFILES lpdfs = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop);
  334.     if (LOWORD(lpdfs->pFiles) == SIZEOF(DROPFILES16))
  335.     {
  336.         //
  337.         // This is Win31-stye HDROP
  338.         //
  339.         LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfs;
  340.         lpList = (LPTSTR)((LPBYTE)pdf16 + pdf16->pFiles);
  341.     }
  342.     else
  343.     {
  344.         //
  345.         // This is a new (NT-compatible) HDROP
  346.         //
  347.         lpList = (LPTSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  348.         // there could be other data in there, but all
  349.         // the HDROPs we build should be this size
  350.         ASSERT(lpdfs->pFiles == SIZEOF(DROPFILES));
  351.     }
  352.     /* find either the number of files or the start of the file
  353.      * we're looking for
  354.      */
  355.     for (i = 0; ((int)iFile == -1 || i != (int)iFile) && *lpList; i++)
  356.     {
  357.         while (*lpList++)
  358.             ;
  359.     }
  360.     if (iFile == -1)
  361.         goto Exit;
  362.     iFile = i = lstrlen(lpList);
  363.     if (!i || !cb || !lpFile)
  364.         goto Exit;
  365.     cb--;
  366.     if (cb < (UINT)i)
  367.         i = cb;
  368.     lstrcpyn(lpFile, lpList, cb+1);
  369.     // Note that we are returning the length of the string NOT INCLUDING the
  370.     // NULL.  The DOCs are in error.
  371.     i = iFile;
  372. Exit:
  373.     GlobalUnlock((HGLOBAL)hDrop);
  374.     return i;
  375. }
  376. #endif // !WINNT
  377. STDAPI_(void) DragFinish(HDROP hDrop)
  378. {
  379.     GlobalFree((HGLOBAL)hDrop);
  380. }
  381. STDAPI_(void) DragAcceptFiles(HWND hwnd, BOOL fAccept)
  382. {
  383.     long exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  384.     if (fAccept)
  385.         exstyle |= WS_EX_ACCEPTFILES;
  386.     else
  387.         exstyle &= (~WS_EX_ACCEPTFILES);
  388.     SetWindowLong(hwnd, GWL_EXSTYLE, exstyle);
  389. }