|
|
#include "shellprv.h"
#pragma hdrstop
// warning: this will fail given a UNICODE hDrop on an ANSI build and
// the DRAGINFO is esentially a TCHAR struct with no A/W versions exported
//
// in:
// hDrop drop handle
//
// out:
// a bunch of info about the hdrop
// (mostly the pointer to the double NULL file name list in TCHAR format)
//
// returns:
// TRUE the DRAGINFO struct was filled in
// FALSE the hDrop was bad
//
STDAPI_(BOOL) DragQueryInfo(HDROP hDrop, DRAGINFO *pdi) { if (hDrop && (pdi->uSize == sizeof(DRAGINFO))) { LPDROPFILES lpdfx = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop); pdi->lpFileList = NULL; if (lpdfx) { LPTSTR lpOldFileList; if (LOWORD(lpdfx->pFiles) == sizeof(DROPFILES16)) { //
// This is Win31-stye HDROP
//
LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfx; pdi->pt.x = pdf16->pt.x; pdi->pt.y = pdf16->pt.y; pdi->fNC = pdf16->fNC; pdi->grfKeyState = 0; lpOldFileList = (LPTSTR)((LPBYTE)pdf16 + pdf16->pFiles); } else { //
// This is a new (NT-compatible) HDROP.
//
pdi->pt.x = lpdfx->pt.x; pdi->pt.y = lpdfx->pt.y; pdi->fNC = lpdfx->fNC; pdi->grfKeyState = 0; lpOldFileList = (LPTSTR)((LPBYTE)lpdfx + lpdfx->pFiles); // there could be other data in there, but all
// the HDROPs we build should be this size
ASSERT(lpdfx->pFiles == sizeof(DROPFILES)); } { BOOL fListMatchesBuild; if ((LOWORD(lpdfx->pFiles) == sizeof(DROPFILES16)) || lpdfx->fWide == FALSE) { fListMatchesBuild = FALSE; } else { fListMatchesBuild = TRUE; } if (fListMatchesBuild) { LPTSTR pTStr = (LPTSTR) lpOldFileList; LPTSTR pNewFileList; UINT cChar; // Look for the end of the file list
while (*pTStr || *(pTStr + 1)) { pTStr++; } pTStr++; // Advance to last NUL of double terminator
cChar = (UINT)(pTStr - lpOldFileList); pNewFileList = (LPTSTR) SHAlloc((cChar + 1) * sizeof(TCHAR)); if (NULL == pNewFileList) { GlobalUnlock((HGLOBAL)hDrop); return FALSE; } // Copy strings to new buffer and set LPDROPINFO filelist
// pointer to point to this new buffer
CopyMemory(pNewFileList, lpOldFileList, ((cChar + 1) * sizeof(TCHAR))); pdi->lpFileList = pNewFileList; } else { LPXSTR pXStr = (LPXSTR) lpOldFileList; LPTSTR pNewFileList; LPTSTR pSaveFileList; UINT cChar; UINT cchConverted; // Look for the end of the file list
while (*pXStr || (*(pXStr + 1))) { pXStr++; } pXStr++; // Advance to the last NUL of the double terminator
cChar = (UINT)(pXStr - ((LPXSTR) lpOldFileList)); pNewFileList = (LPTSTR) SHAlloc((cChar + 1) * sizeof(TCHAR)); if (NULL == pNewFileList) { GlobalUnlock((HGLOBAL)hDrop); return FALSE; } pSaveFileList = pNewFileList; pXStr = (LPXSTR) lpOldFileList; do { cchConverted = MultiByteToWideChar(CP_ACP, 0, pXStr, -1, pNewFileList, ((cChar + 1) * sizeof(TCHAR))); // Not really, but... "trust me"
if (0 == cchConverted) { ASSERT(0 && "Unable to convert HDROP filename ANSI -> UNICODE"); GlobalUnlock((HGLOBAL)hDrop); SHFree(pSaveFileList); return FALSE; } pNewFileList += cchConverted; pXStr += lstrlenX(pXStr) + 1; } while (*pXStr); // Add the double-null-terminator to the output list
*pNewFileList = 0; pdi->lpFileList = pSaveFileList; } } GlobalUnlock((HGLOBAL)hDrop); return TRUE; } } return FALSE; }
// 3.1 API
STDAPI_(BOOL) DragQueryPoint(HDROP hDrop, POINT *ppt) { BOOL fRet = FALSE; LPDROPFILES lpdfs = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop); if (lpdfs) { if (LOWORD(lpdfs->pFiles) == sizeof(DROPFILES16)) { //
// This is Win31-stye HDROP
//
LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfs; ppt->x = pdf16->pt.x; ppt->y = pdf16->pt.y; fRet = !pdf16->fNC; } else { //
// This is a new (NT-compatible) HDROP
//
ppt->x = (UINT)lpdfs->pt.x; ppt->y = (UINT)lpdfs->pt.y; fRet = !lpdfs->fNC;
// there could be other data in there, but all
// the HDROPs we build should be this size
ASSERT(lpdfs->pFiles == sizeof(DROPFILES)); } GlobalUnlock((HGLOBAL)hDrop); }
return fRet; }
//
// Unfortunately we need it split out this way because WOW needs to
// able to call a function named DragQueryFileAorW (so it can shorten them)
//
STDAPI_(UINT) DragQueryFileAorW(HDROP hDrop, UINT iFile, void *lpFile, UINT cb, BOOL fNeedAnsi, BOOL fShorten) { UINT i; LPDROPFILESTRUCT lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop); if (lpdfs) { // see if it is the new format
BOOL fWide = LOWORD(lpdfs->pFiles) == sizeof(DROPFILES) && lpdfs->fWide; if (fWide) { LPWSTR lpList; WCHAR szPath[MAX_PATH];
//
// UNICODE HDROP
//
lpList = (LPWSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
// find either the number of files or the start of the file
// we're looking for
//
for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++) { while (*lpList++) ; }
if (iFile == (UINT)-1) goto Exit;
iFile = i = lstrlenW(lpList); if (fShorten && iFile < MAX_PATH) { wcscpy(szPath, lpList); SheShortenPathW(szPath, TRUE); lpList = szPath; iFile = i = lstrlenW(lpList); }
if (fNeedAnsi) { // Do not assume that a count of characters == a count of bytes
i = WideCharToMultiByte(CP_ACP, 0, lpList, -1, NULL, 0, NULL, NULL); iFile = i ? --i : i; }
if (!i || !cb || !lpFile) goto Exit;
if (fNeedAnsi) { SHUnicodeToAnsi(lpList, (LPSTR)lpFile, cb); } else { cb--; if (cb < i) i = cb; lstrcpynW((LPWSTR)lpFile, lpList, i + 1); } } else { LPSTR lpList; CHAR szPath[MAX_PATH];
//
// This is Win31-style HDROP or an ANSI NT Style HDROP
//
lpList = (LPSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
// find either the number of files or the start of the file
// we're looking for
//
for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++) { while (*lpList++) ; }
if (iFile == (UINT)-1) goto Exit;
iFile = i = lstrlenA(lpList); if (fShorten && iFile < MAX_PATH) { strcpy(szPath, lpList); SheShortenPathA(szPath, TRUE); lpList = szPath; iFile = i = lstrlenA(lpList); }
if (!fNeedAnsi) { i = MultiByteToWideChar(CP_ACP, 0, lpList, -1, NULL, 0); iFile = i ? --i : i; }
if (!i || !cb || !lpFile) goto Exit;
if (fNeedAnsi) { cb--; if (cb < i) i = cb; lstrcpynA((LPSTR)lpFile, lpList, i + 1); } else { SHAnsiToUnicode(lpList, (LPWSTR)lpFile, cb); } } }
i = iFile;
Exit: GlobalUnlock(hDrop);
return i; }
STDAPI_(UINT) DragQueryFileW(HDROP hDrop, UINT wFile, LPWSTR lpFile, UINT cb) { return DragQueryFileAorW(hDrop, wFile, lpFile, cb, FALSE, FALSE); }
STDAPI_(UINT) DragQueryFileA(HDROP hDrop, UINT wFile, LPSTR lpFile, UINT cb) { return DragQueryFileAorW(hDrop, wFile, lpFile, cb, TRUE, FALSE); }
STDAPI_(void) DragFinish(HDROP hDrop) { GlobalFree((HGLOBAL)hDrop); }
STDAPI_(void) DragAcceptFiles(HWND hwnd, BOOL fAccept) { long exstyle = GetWindowLong(hwnd, GWL_EXSTYLE); if (fAccept) exstyle |= WS_EX_ACCEPTFILES; else exstyle &= (~WS_EX_ACCEPTFILES); SetWindowLong(hwnd, GWL_EXSTYLE, exstyle); }
|