Leaked source code of windows server 2003
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.

321 lines
9.5 KiB

  1. #include "shellprv.h"
  2. #pragma hdrstop
  3. UINT _StringListLenW(PCWSTR pszList)
  4. {
  5. // this is a double NULL terminated list
  6. // we want to make sure that we get the size
  7. // including the NULL term
  8. PCWSTR pszLast = pszList;
  9. while (*pszLast || (*(pszLast + 1)))
  10. {
  11. pszLast++;
  12. }
  13. ASSERT(!pszLast[0] && !pszLast[1]);
  14. // add 2 for the double term
  15. return (UINT)(pszLast - pszList) + 2;
  16. }
  17. UINT _StringListLenA(PCSTR pszList)
  18. {
  19. // this is a double NULL terminated list
  20. // we want to make sure that we get the size
  21. // including the NULL term
  22. PCSTR pszLast = pszList;
  23. while (*pszLast || (*(pszLast + 1)))
  24. {
  25. pszLast++;
  26. }
  27. ASSERT(!pszLast[0] && !pszLast[1]);
  28. // add 2 for the double term
  29. return (UINT)(pszLast - pszList) + 2;
  30. }
  31. // warning: this will fail given a UNICODE hDrop on an ANSI build and
  32. // the DRAGINFO is esentially a TCHAR struct with no A/W versions exported
  33. //
  34. // in:
  35. // hDrop drop handle
  36. //
  37. // out:
  38. // a bunch of info about the hdrop
  39. // (mostly the pointer to the double NULL file name list in TCHAR format)
  40. //
  41. // returns:
  42. // TRUE the DRAGINFO struct was filled in
  43. // FALSE the hDrop was bad
  44. //
  45. STDAPI_(BOOL) DragQueryInfo(HDROP hDrop, DRAGINFO *pdi)
  46. {
  47. if (hDrop && (pdi->uSize == sizeof(DRAGINFO)))
  48. {
  49. LPDROPFILES lpdfx = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop);
  50. pdi->lpFileList = NULL;
  51. if (lpdfx)
  52. {
  53. LPTSTR lpOldFileList;
  54. if (LOWORD(lpdfx->pFiles) == sizeof(DROPFILES16))
  55. {
  56. //
  57. // This is Win31-stye HDROP
  58. //
  59. LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfx;
  60. pdi->pt.x = pdf16->pt.x;
  61. pdi->pt.y = pdf16->pt.y;
  62. pdi->fNC = pdf16->fNC;
  63. pdi->grfKeyState = 0;
  64. lpOldFileList = (LPTSTR)((LPBYTE)pdf16 + pdf16->pFiles);
  65. }
  66. else
  67. {
  68. //
  69. // This is a new (NT-compatible) HDROP.
  70. //
  71. pdi->pt.x = lpdfx->pt.x;
  72. pdi->pt.y = lpdfx->pt.y;
  73. pdi->fNC = lpdfx->fNC;
  74. pdi->grfKeyState = 0;
  75. lpOldFileList = (LPTSTR)((LPBYTE)lpdfx + lpdfx->pFiles);
  76. // there could be other data in there, but all
  77. // the HDROPs we build should be this size
  78. ASSERT(lpdfx->pFiles == sizeof(DROPFILES));
  79. }
  80. {
  81. BOOL fIsAnsi = ((LOWORD(lpdfx->pFiles) == sizeof(DROPFILES16)) || lpdfx->fWide == FALSE);
  82. if (!fIsAnsi)
  83. {
  84. UINT cchListW = _StringListLenW(lpOldFileList);
  85. LPTSTR pszListW = (LPTSTR) SHAlloc(CbFromCchW(cchListW));
  86. if (pszListW)
  87. {
  88. // Copy strings to new buffer and set LPDROPINFO filelist
  89. // pointer to point to this new buffer
  90. CopyMemory(pszListW, lpOldFileList, CbFromCchW(cchListW));
  91. pdi->lpFileList = pszListW;
  92. }
  93. }
  94. else
  95. {
  96. PCSTR pszListA = (LPSTR)lpOldFileList;
  97. UINT cchListA = _StringListLenA(pszListA);
  98. UINT cchListW = MultiByteToWideChar(CP_ACP, 0, pszListA, cchListA, NULL, 0);
  99. if (cchListW)
  100. {
  101. PWSTR pszListW = (LPWSTR) SHAlloc(CbFromCchW(cchListW));
  102. if (pszListW)
  103. {
  104. // reuse cchListA for debug purposes
  105. cchListA = MultiByteToWideChar(CP_ACP, 0, pszListA, cchListA, pszListW, cchListW);
  106. ASSERT(cchListA == cchListW);
  107. pdi->lpFileList = pszListW;
  108. }
  109. }
  110. }
  111. }
  112. GlobalUnlock((HGLOBAL)hDrop);
  113. return pdi->lpFileList != NULL;
  114. }
  115. }
  116. return FALSE;
  117. }
  118. // 3.1 API
  119. STDAPI_(BOOL) DragQueryPoint(HDROP hDrop, POINT *ppt)
  120. {
  121. BOOL fRet = FALSE;
  122. LPDROPFILES lpdfs = (LPDROPFILES)GlobalLock((HGLOBAL)hDrop);
  123. if (lpdfs)
  124. {
  125. if (LOWORD(lpdfs->pFiles) == sizeof(DROPFILES16))
  126. {
  127. //
  128. // This is Win31-stye HDROP
  129. //
  130. LPDROPFILES16 pdf16 = (LPDROPFILES16)lpdfs;
  131. ppt->x = pdf16->pt.x;
  132. ppt->y = pdf16->pt.y;
  133. fRet = !pdf16->fNC;
  134. }
  135. else
  136. {
  137. //
  138. // This is a new (NT-compatible) HDROP
  139. //
  140. ppt->x = (UINT)lpdfs->pt.x;
  141. ppt->y = (UINT)lpdfs->pt.y;
  142. fRet = !lpdfs->fNC;
  143. // there could be other data in there, but all
  144. // the HDROPs we build should be this size
  145. ASSERT(lpdfs->pFiles == sizeof(DROPFILES));
  146. }
  147. GlobalUnlock((HGLOBAL)hDrop);
  148. }
  149. return fRet;
  150. }
  151. //
  152. // Unfortunately we need it split out this way because WOW needs to
  153. // able to call a function named DragQueryFileAorW (so it can shorten them)
  154. //
  155. STDAPI_(UINT) DragQueryFileAorW(HDROP hDrop, UINT iFile, void *lpFile, UINT cb, BOOL fNeedAnsi, BOOL fShorten)
  156. {
  157. UINT i;
  158. LPDROPFILESTRUCT lpdfs = (LPDROPFILESTRUCT)GlobalLock(hDrop);
  159. if (lpdfs)
  160. {
  161. // see if it is the new format
  162. BOOL fWide = LOWORD(lpdfs->pFiles) == sizeof(DROPFILES) && lpdfs->fWide;
  163. if (fWide)
  164. {
  165. LPWSTR lpList;
  166. WCHAR szPath[MAX_PATH];
  167. //
  168. // UNICODE HDROP
  169. //
  170. lpList = (LPWSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  171. // find either the number of files or the start of the file
  172. // we're looking for
  173. //
  174. for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++)
  175. {
  176. while (*lpList++)
  177. ;
  178. }
  179. if (iFile == (UINT)-1)
  180. goto Exit;
  181. iFile = i = lstrlenW(lpList);
  182. if (fShorten && iFile < MAX_PATH)
  183. {
  184. StringCchCopy(szPath, ARRAYSIZE(szPath), lpList);
  185. SheShortenPathW(szPath, TRUE);
  186. lpList = szPath;
  187. iFile = i = lstrlenW(lpList);
  188. }
  189. if (fNeedAnsi)
  190. {
  191. // Do not assume that a count of characters == a count of bytes
  192. i = WideCharToMultiByte(CP_ACP, 0, lpList, -1, NULL, 0, NULL, NULL);
  193. iFile = i ? --i : i;
  194. }
  195. if (!i || !cb || !lpFile)
  196. goto Exit;
  197. if (fNeedAnsi)
  198. {
  199. SHUnicodeToAnsi(lpList, (LPSTR)lpFile, cb);
  200. }
  201. else
  202. {
  203. cb--;
  204. if (cb < i)
  205. i = cb;
  206. lstrcpynW((LPWSTR)lpFile, lpList, i + 1);
  207. }
  208. }
  209. else
  210. {
  211. LPSTR lpList;
  212. CHAR szPath[MAX_PATH];
  213. //
  214. // This is Win31-style HDROP or an ANSI NT Style HDROP
  215. //
  216. lpList = (LPSTR)((LPBYTE)lpdfs + lpdfs->pFiles);
  217. // find either the number of files or the start of the file
  218. // we're looking for
  219. //
  220. for (i = 0; (iFile == (UINT)-1 || i != iFile) && *lpList; i++)
  221. {
  222. while (*lpList++)
  223. ;
  224. }
  225. if (iFile == (UINT)-1)
  226. goto Exit;
  227. iFile = i = lstrlenA(lpList);
  228. if (fShorten && iFile < MAX_PATH)
  229. {
  230. StringCchCopyA(szPath, ARRAYSIZE(szPath), lpList);
  231. SheShortenPathA(szPath, TRUE);
  232. lpList = szPath;
  233. iFile = i = lstrlenA(lpList);
  234. }
  235. if (!fNeedAnsi)
  236. {
  237. i = MultiByteToWideChar(CP_ACP, 0, lpList, -1, NULL, 0);
  238. iFile = i ? --i : i;
  239. }
  240. if (!i || !cb || !lpFile)
  241. goto Exit;
  242. if (fNeedAnsi)
  243. {
  244. cb--;
  245. if (cb < i)
  246. i = cb;
  247. lstrcpynA((LPSTR)lpFile, lpList, i + 1);
  248. }
  249. else
  250. {
  251. SHAnsiToUnicode(lpList, (LPWSTR)lpFile, cb);
  252. }
  253. }
  254. }
  255. i = iFile;
  256. Exit:
  257. GlobalUnlock(hDrop);
  258. return i;
  259. }
  260. STDAPI_(UINT) DragQueryFileW(HDROP hDrop, UINT wFile, LPWSTR lpFile, UINT cb)
  261. {
  262. return DragQueryFileAorW(hDrop, wFile, lpFile, cb, FALSE, FALSE);
  263. }
  264. STDAPI_(UINT) DragQueryFileA(HDROP hDrop, UINT wFile, LPSTR lpFile, UINT cb)
  265. {
  266. return DragQueryFileAorW(hDrop, wFile, lpFile, cb, TRUE, FALSE);
  267. }
  268. STDAPI_(void) DragFinish(HDROP hDrop)
  269. {
  270. GlobalFree((HGLOBAL)hDrop);
  271. }
  272. STDAPI_(void) DragAcceptFiles(HWND hwnd, BOOL fAccept)
  273. {
  274. long exstyle = GetWindowLong(hwnd, GWL_EXSTYLE);
  275. if (fAccept)
  276. exstyle |= WS_EX_ACCEPTFILES;
  277. else
  278. exstyle &= (~WS_EX_ACCEPTFILES);
  279. SetWindowLong(hwnd, GWL_EXSTYLE, exstyle);
  280. }