Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

348 lines
10 KiB

  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 in TCHAR format)
  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. pdi->lpFileList = NULL;
  23. if (lpdfx)
  24. {
  25. LPTSTR lpOldFileList;
  26. if (LOWORD(lpdfx->pFiles) == sizeof(DROPFILES16))
  27. {
  28. //
  29. // This is Win31-stye HDROP
  30. //
  31. LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfx;
  32. pdi->pt.x = pdf16->pt.x;
  33. pdi->pt.y = pdf16->pt.y;
  34. pdi->fNC = pdf16->fNC;
  35. pdi->grfKeyState = 0;
  36. lpOldFileList = (LPTSTR)((LPBYTE)pdf16 + pdf16->pFiles);
  37. }
  38. else
  39. {
  40. //
  41. // This is a new (NT-compatible) HDROP.
  42. //
  43. pdi->pt.x = lpdfx->pt.x;
  44. pdi->pt.y = lpdfx->pt.y;
  45. pdi->fNC = lpdfx->fNC;
  46. pdi->grfKeyState = 0;
  47. lpOldFileList = (LPTSTR)((LPBYTE)lpdfx + lpdfx->pFiles);
  48. // there could be other data in there, but all
  49. // the HDROPs we build should be this size
  50. ASSERT(lpdfx->pFiles == sizeof(DROPFILES));
  51. }
  52. {
  53. BOOL fListMatchesBuild;
  54. if ((LOWORD(lpdfx->pFiles) == sizeof(DROPFILES16)) || lpdfx->fWide == FALSE)
  55. {
  56. fListMatchesBuild = FALSE;
  57. }
  58. else
  59. {
  60. fListMatchesBuild = TRUE;
  61. }
  62. if (fListMatchesBuild)
  63. {
  64. LPTSTR pTStr = (LPTSTR) lpOldFileList;
  65. LPTSTR pNewFileList;
  66. UINT cChar;
  67. // Look for the end of the file list
  68. while (*pTStr || *(pTStr + 1))
  69. {
  70. pTStr++;
  71. }
  72. pTStr++; // Advance to last NUL of double terminator
  73. cChar = (UINT)(pTStr - lpOldFileList);
  74. pNewFileList = (LPTSTR) SHAlloc((cChar + 1) * sizeof(TCHAR));
  75. if (NULL == pNewFileList)
  76. {
  77. GlobalUnlock((HGLOBAL)hDrop);
  78. return FALSE;
  79. }
  80. // Copy strings to new buffer and set LPDROPINFO filelist
  81. // pointer to point to this new buffer
  82. CopyMemory(pNewFileList, lpOldFileList, ((cChar + 1) * sizeof(TCHAR)));
  83. pdi->lpFileList = pNewFileList;
  84. }
  85. else
  86. {
  87. LPXSTR pXStr = (LPXSTR) lpOldFileList;
  88. LPTSTR pNewFileList;
  89. LPTSTR pSaveFileList;
  90. UINT cChar;
  91. UINT cchConverted;
  92. // Look for the end of the file list
  93. while (*pXStr || (*(pXStr + 1)))
  94. {
  95. pXStr++;
  96. }
  97. pXStr++; // Advance to the last NUL of the double terminator
  98. cChar = (UINT)(pXStr - ((LPXSTR) lpOldFileList));
  99. pNewFileList = (LPTSTR) SHAlloc((cChar + 1) * sizeof(TCHAR));
  100. if (NULL == pNewFileList)
  101. {
  102. GlobalUnlock((HGLOBAL)hDrop);
  103. return FALSE;
  104. }
  105. pSaveFileList = pNewFileList;
  106. pXStr = (LPXSTR) lpOldFileList;
  107. do
  108. {
  109. cchConverted = MultiByteToWideChar(CP_ACP, 0, pXStr, -1,
  110. pNewFileList, ((cChar + 1) * sizeof(TCHAR))); // Not really, but... "trust me"
  111. if (0 == cchConverted)
  112. {
  113. ASSERT(0 && "Unable to convert HDROP filename ANSI -> UNICODE");
  114. GlobalUnlock((HGLOBAL)hDrop);
  115. SHFree(pSaveFileList);
  116. return FALSE;
  117. }
  118. pNewFileList += cchConverted;
  119. pXStr += lstrlenX(pXStr) + 1;
  120. } while (*pXStr);
  121. // Add the double-null-terminator to the output list
  122. *pNewFileList = 0;
  123. pdi->lpFileList = pSaveFileList;
  124. }
  125. }
  126. GlobalUnlock((HGLOBAL)hDrop);
  127. return TRUE;
  128. }
  129. }
  130. return FALSE;
  131. }
  132. // 3.1 API
  133. STDAPI_(BOOL) DragQueryPoint(HDROP hDrop, POINT *ppt)
  134. {
  135. BOOL fRet = FALSE;
  136. LPDROPFILES lpdfs = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop);
  137. if (lpdfs)
  138. {
  139. if (LOWORD(lpdfs->pFiles) == sizeof(DROPFILES16))
  140. {
  141. //
  142. // This is Win31-stye HDROP
  143. //
  144. LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfs;
  145. ppt->x = pdf16->pt.x;
  146. ppt->y = pdf16->pt.y;
  147. fRet = !pdf16->fNC;
  148. }
  149. else
  150. {
  151. //
  152. // This is a new (NT-compatible) HDROP
  153. //
  154. ppt->x = (UINT)lpdfs->pt.x;
  155. ppt->y = (UINT)lpdfs->pt.y;
  156. fRet = !lpdfs->fNC;
  157. // there could be other data in there, but all
  158. // the HDROPs we build should be this size
  159. ASSERT(lpdfs->pFiles == sizeof(DROPFILES));
  160. }
  161. GlobalUnlock((HGLOBAL)hDrop);
  162. }
  163. return fRet;
  164. }
  165. //
  166. // Unfortunately we need it split out this way because WOW needs to
  167. // able to call a function named DragQueryFileAorW (so it can shorten them)
  168. //
  169. STDAPI_(UINT) DragQueryFileAorW(HDROP hDrop, UINT iFile, void *lpFile, UINT cb, BOOL fNeedAnsi, BOOL fShorten)
  170. {
  171. UINT i;
  172. LPDROPFILESTRUCT lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop);
  173. if (lpdfs)
  174. {
  175. // see if it is the new format
  176. BOOL fWide = LOWORD(lpdfs->pFiles) == sizeof(DROPFILES) && lpdfs->fWide;
  177. if (fWide)
  178. {
  179. LPWSTR lpList;
  180. WCHAR szPath[MAX_PATH];
  181. //
  182. // UNICODE HDROP
  183. //
  184. lpList = (LPWSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  185. // find either the number of files or the start of the file
  186. // we're looking for
  187. //
  188. for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++)
  189. {
  190. while (*lpList++)
  191. ;
  192. }
  193. if (iFile == (UINT)-1)
  194. goto Exit;
  195. iFile = i = lstrlenW(lpList);
  196. if (fShorten && iFile < MAX_PATH)
  197. {
  198. wcscpy(szPath, lpList);
  199. SheShortenPathW(szPath, TRUE);
  200. lpList = szPath;
  201. iFile = i = lstrlenW(lpList);
  202. }
  203. if (fNeedAnsi)
  204. {
  205. // Do not assume that a count of characters == a count of bytes
  206. i = WideCharToMultiByte(CP_ACP, 0, lpList, -1, NULL, 0, NULL, NULL);
  207. iFile = i ? --i : i;
  208. }
  209. if (!i || !cb || !lpFile)
  210. goto Exit;
  211. if (fNeedAnsi)
  212. {
  213. SHUnicodeToAnsi(lpList, (LPSTR)lpFile, cb);
  214. }
  215. else
  216. {
  217. cb--;
  218. if (cb < i)
  219. i = cb;
  220. lstrcpynW((LPWSTR)lpFile, lpList, i + 1);
  221. }
  222. }
  223. else
  224. {
  225. LPSTR lpList;
  226. CHAR szPath[MAX_PATH];
  227. //
  228. // This is Win31-style HDROP or an ANSI NT Style HDROP
  229. //
  230. lpList = (LPSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  231. // find either the number of files or the start of the file
  232. // we're looking for
  233. //
  234. for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++)
  235. {
  236. while (*lpList++)
  237. ;
  238. }
  239. if (iFile == (UINT)-1)
  240. goto Exit;
  241. iFile = i = lstrlenA(lpList);
  242. if (fShorten && iFile < MAX_PATH)
  243. {
  244. strcpy(szPath, lpList);
  245. SheShortenPathA(szPath, TRUE);
  246. lpList = szPath;
  247. iFile = i = lstrlenA(lpList);
  248. }
  249. if (!fNeedAnsi)
  250. {
  251. i = MultiByteToWideChar(CP_ACP, 0, lpList, -1, NULL, 0);
  252. iFile = i ? --i : i;
  253. }
  254. if (!i || !cb || !lpFile)
  255. goto Exit;
  256. if (fNeedAnsi)
  257. {
  258. cb--;
  259. if (cb < i)
  260. i = cb;
  261. lstrcpynA((LPSTR)lpFile, lpList, i + 1);
  262. }
  263. else
  264. {
  265. SHAnsiToUnicode(lpList, (LPWSTR)lpFile, cb);
  266. }
  267. }
  268. }
  269. i = iFile;
  270. Exit:
  271. GlobalUnlock(hDrop);
  272. return i;
  273. }
  274. STDAPI_(UINT) DragQueryFileW(HDROP hDrop, UINT wFile, LPWSTR lpFile, UINT cb)
  275. {
  276. return DragQueryFileAorW(hDrop, wFile, lpFile, cb, FALSE, FALSE);
  277. }
  278. STDAPI_(UINT) DragQueryFileA(HDROP hDrop, UINT wFile, LPSTR lpFile, UINT cb)
  279. {
  280. return DragQueryFileAorW(hDrop, wFile, lpFile, cb, TRUE, FALSE);
  281. }
  282. STDAPI_(void) DragFinish(HDROP hDrop)
  283. {
  284. GlobalFree((HGLOBAL)hDrop);
  285. }
  286. STDAPI_(void) DragAcceptFiles(HWND hwnd, BOOL fAccept)
  287. {
  288. long exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  289. if (fAccept)
  290. exstyle |= WS_EX_ACCEPTFILES;
  291. else
  292. exstyle &= (~WS_EX_ACCEPTFILES);
  293. SetWindowLong(hwnd, GWL_EXSTYLE, exstyle);
  294. }