Changeset 50508 in vbox for trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
- Timestamp:
- Feb 19, 2014 3:45:58 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/VBoxGuestR3LibDragAndDrop.cpp
r50462 r50508 38 38 #include <iprt/cpp/ministring.h> 39 39 40 #ifdef LOG_GROUP 41 #undef LOG_GROUP 42 #endif 43 #define LOG_GROUP LOG_GROUP_GUEST_DND 44 #include <VBox/log.h> 45 40 46 #include <VBox/GuestHost/DragAndDrop.h> 41 47 #include <VBox/HostServices/DragAndDropSvc.h> … … 79 85 if (RT_SUCCESS(rc)) 80 86 { 81 /* Fetch results */82 87 rc = Msg.msg.GetUInt32(puMsg); AssertRC(rc); 83 88 rc = Msg.num_parms.GetUInt32(pcParms); AssertRC(rc); … … 128 133 if (RT_SUCCESS(rc)) 129 134 { 130 /* Fetch results */131 135 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 132 136 rc = Msg.uX.GetUInt32(puX); AssertRC(rc); … … 135 139 rc = Msg.uAllActions.GetUInt32(puAllActions); AssertRC(rc); 136 140 rc = Msg.cFormats.GetUInt32(pcbFormatsRecv); AssertRC(rc); 137 /* A little bit paranoia */ 141 138 142 AssertReturn(cbFormats >= *pcbFormatsRecv, VERR_TOO_MUCH_DATA); 139 143 } … … 191 195 192 196 Msg.pvName.SetPtr(pszDirname, cbDirname); 193 Msg.c Name.SetUInt32(0);197 Msg.cbName.SetUInt32(0); 194 198 Msg.fMode.SetUInt32(0); 195 199 … … 200 204 if (RT_SUCCESS(Msg.hdr.result)) 201 205 { 202 /* Fetch results */ 203 rc = Msg.cName.GetUInt32(pcbDirnameRecv); AssertRC(rc); 204 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 205 /* A little bit paranoia */ 206 rc = Msg.cbName.GetUInt32(pcbDirnameRecv); AssertRC(rc); 207 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 208 206 209 AssertReturn(cbDirname >= *pcbDirnameRecv, VERR_TOO_MUCH_DATA); 207 210 } … … 235 238 236 239 Msg.pvName.SetPtr(pszFilename, cbFilename); 237 Msg.c Name.SetUInt32(0);240 Msg.cbName.SetUInt32(0); 238 241 Msg.pvData.SetPtr(pvData, cbData); 239 Msg.c Data.SetUInt32(0);242 Msg.cbData.SetUInt32(0); 240 243 Msg.fMode.SetUInt32(0); 241 244 … … 246 249 if (RT_SUCCESS(rc)) 247 250 { 248 /* Fetch results */ 249 rc = Msg.cName.GetUInt32(pcbFilenameRecv); AssertRC(rc); 250 rc = Msg.cData.GetUInt32(pcbDataRecv); AssertRC(rc); 251 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 252 /* A little bit paranoia */ 251 rc = Msg.cbName.GetUInt32(pcbFilenameRecv); AssertRC(rc); 252 rc = Msg.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 253 rc = Msg.fMode.GetUInt32(pfMode); AssertRC(rc); 254 253 255 AssertReturn(cbFilename >= *pcbFilenameRecv, VERR_TOO_MUCH_DATA); 254 256 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); … … 275 277 return VERR_INVALID_PARAMETER; 276 278 277 /* Make a string list out of the uri data. */ 278 RTCList<RTCString> uriList = 279 RTCString(static_cast<char*>(*ppvData), *pcbDataRecv - 1).split("\r\n"); 280 if (uriList.isEmpty()) 281 return VINF_SUCCESS; 282 279 /* Allocate temp buffer. */ 283 280 uint32_t cbTmpData = _1M * 10; /** @todo r=andy 10MB, uh, really?? */ 284 281 void *pvTmpData = RTMemAlloc(cbTmpData); … … 297 294 /* Patch the old drop data with the new drop directory, so the drop target 298 295 * can find the files. */ 299 RTCList<RTCString> guestUriList; 300 for (size_t i = 0; i < uriList.size(); ++i) 301 { 302 const RTCString &strUri = uriList.at(i); 303 /* Query the path component of a file URI. If this hasn't a 304 * file scheme, null is returned. */ 305 char *pszFilePath = RTUriFilePath(strUri.c_str(), URI_FILE_FORMAT_AUTO); 306 if (pszFilePath) 307 { 308 rc = DnDPathSanitize(pszFilePath, strlen(pszFilePath)); 309 if (RT_FAILURE(rc)) 310 break; 311 312 /** @todo Use RTPathJoin? */ 313 RTCString strFullPath 314 = RTCString().printf("%s%c%s", pszDropDir, RTPATH_SLASH, pszFilePath); 315 char *pszNewUri = RTUriFileCreate(strFullPath.c_str()); 316 if (pszNewUri) 317 { 318 guestUriList.append(pszNewUri); 319 RTStrFree(pszNewUri); 320 } 321 } 322 else 323 guestUriList.append(strUri); 324 } 325 296 DnDURIList lstURI; 297 rc = lstURI.RootFromURIData(*ppvData, *pcbDataRecv, 298 0 /* fFlags */); 326 299 if (RT_SUCCESS(rc)) 327 300 { 328 301 /* Cleanup the old data and write the new data back to the event. */ 329 302 RTMemFree(*ppvData); 330 RTCString newData = RTCString::join(guestUriList, "\r\n") + "\r\n"; 331 332 *ppvData = RTStrDupN( newData.c_str(), newData.length());333 *pcbDataRecv = newData.length() + 1;303 304 RTCString strData = lstURI.RootToString(pszDropDir); 305 *ppvData = RTStrDupN(strData.c_str(), strData.length()); 306 *pcbDataRecv = strData.length() + 1; 334 307 } 335 308 … … 403 376 if (RT_SUCCESS(rc)) 404 377 { 378 /** @todo r=andy Not very safe to assume that we were last appending to the current file. */ 405 379 rc = RTFileSeek(hFile, 0, RTFILE_SEEK_END, NULL); 406 380 if (RT_SUCCESS(rc)) … … 488 462 Msg.cFormat.SetUInt32(0); 489 463 Msg.pvData.SetPtr(pvData, cbData); 490 Msg.c Data.SetUInt32(0);464 Msg.cbData.SetUInt32(0); 491 465 492 466 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 497 471 || rc == VERR_BUFFER_OVERFLOW) 498 472 { 499 /* Fetch results */500 473 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 501 474 rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc); 502 rc = Msg.c Data.GetUInt32(pcbDataTotal); AssertRC(rc);503 /* A little bit paranoia */ 475 rc = Msg.cbData.GetUInt32(pcbDataTotal); AssertRC(rc); 476 504 477 AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA); 505 478 AssertReturn(cbData >= *pcbDataTotal, VERR_TOO_MUCH_DATA); … … 526 499 527 500 Msg.pvData.SetPtr(pvData, cbData); 528 Msg.c Data.SetUInt32(0);501 Msg.cbData.SetUInt32(0); 529 502 530 503 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 535 508 || rc == VERR_BUFFER_OVERFLOW) 536 509 { 537 /* Fetch results */ 538 rc = Msg.cData.GetUInt32(pcbDataRecv); AssertRC(rc); 539 /* A little bit paranoia */ 510 rc = Msg.cbData.GetUInt32(pcbDataRecv); AssertRC(rc); 540 511 AssertReturn(cbData >= *pcbDataRecv, VERR_TOO_MUCH_DATA); 541 512 } … … 629 600 * This keeps the actual (guest OS-)dependent client (like VBoxClient / 630 601 * VBoxTray) small by not having too much redundant code. */ 631 if (RTStrNICmp(pszFormat, "text/uri-list", *pcbFormatRecv) == 0) 602 AssertPtr(pcbFormatRecv); 603 if (DnDMIMEHasFileURLs(pszFormat, *pcbFormatRecv)) 632 604 rc = vbglR3DnDHGProcessURIMessages(uClientId, 633 605 puScreenId, … … 661 633 rc = Msg.hdr.result; 662 634 if (RT_SUCCESS(rc)) 663 {664 /* Fetch results */665 635 rc = Msg.uScreenId.GetUInt32(puScreenId); AssertRC(rc); 666 }667 636 } 668 637 … … 697 666 if (RT_SUCCESS(rc)) 698 667 { 699 /* Fetch results */700 668 rc = Msg.cFormat.GetUInt32(pcbFormatRecv); AssertRC(rc); 701 669 rc = Msg.uAction.GetUInt32(puAction); AssertRC(rc); 702 /* A little bit paranoia */ 670 703 671 AssertReturn(cbFormat >= *pcbFormatRecv, VERR_TOO_MUCH_DATA); 704 672 } … … 872 840 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_ACK_OP; 873 841 Msg.hdr.cParms = 1; 874 /* Initialize parameter */ 842 875 843 Msg.uAction.SetUInt32(uAction); 876 /* Do request */ 844 877 845 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 878 846 if (RT_SUCCESS(rc)) … … 892 860 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_HG_REQ_DATA; 893 861 Msg.hdr.cParms = 1; 894 /* Initialize parameter */ 862 895 863 Msg.pFormat.SetPtr((void*)pcszFormat, (uint32_t)strlen(pcszFormat) + 1); 896 /* Do request */ 864 897 865 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 898 866 if (RT_SUCCESS(rc)) … … 914 882 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_ACK_PENDING; 915 883 Msg.hdr.cParms = 3; 916 /* Initialize parameter */ 884 917 885 Msg.uDefAction.SetUInt32(uDefAction); 918 886 Msg.uAllActions.SetUInt32(uAllActions); 919 887 Msg.pFormat.SetPtr((void*)pcszFormats, (uint32_t)strlen(pcszFormats) + 1); 920 /* Do request */ 921 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 922 if (RT_SUCCESS(rc)) 923 rc = Msg.hdr.result; 924 925 return rc; 926 } 927 928 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, 929 void *pvData, uint32_t cbData) 888 889 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 890 if (RT_SUCCESS(rc)) 891 rc = Msg.hdr.result; 892 893 return rc; 894 } 895 896 static int vbglR3DnDGHSendDataInternal(uint32_t u32ClientId, 897 void *pvData, uint32_t cbData, 898 uint32_t cbAdditionalData) 930 899 { 931 900 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 932 AssertReturn(cbData, 901 AssertReturn(cbData, VERR_INVALID_PARAMETER); 933 902 934 903 DragAndDropSvc::VBOXDNDGHSENDDATAMSG Msg; … … 938 907 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DATA; 939 908 Msg.hdr.cParms = 2; 940 Msg.uSize.SetUInt32(cbData); 941 942 int rc = VINF_SUCCESS; 943 uint32_t cbMax = _64K; /* Transfer max. 64K chunks per message. */ 944 uint32_t cbSent = 0; 909 910 /* Total amount of bytes to send (including this data block). */ 911 Msg.cbTotalBytes.SetUInt32(cbData + cbAdditionalData); 912 913 int rc; 914 915 uint32_t cbMaxChunk = _64K; /* Transfer max. 64K chunks per message. */ 916 uint32_t cbSent = 0; 945 917 946 918 while (cbSent < cbData) 947 919 { 948 uint32_t cb ToSend = RT_MIN(cbData - cbSent, cbMax);949 Msg.p Data.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbToSend);920 uint32_t cbCurChunk = RT_MIN(cbData - cbSent, cbMaxChunk); 921 Msg.pvData.SetPtr(static_cast<uint8_t*>(pvData) + cbSent, cbCurChunk); 950 922 951 923 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); … … 956 928 break; 957 929 958 cbSent += cb ToSend;930 cbSent += cbCurChunk; 959 931 } 960 932 961 933 if (RT_SUCCESS(rc)) 962 934 Assert(cbSent == cbData); 935 936 LogFlowFunc(("Returning rc=%Rrc, cbData=%RU32, cbAddtionalData=%RU32\n", 937 rc, cbData, cbAdditionalData)); 938 return rc; 939 } 940 941 static int vbglR3DnDGHSendDir(uint32_t u32ClientId, DnDURIObject &obj) 942 { 943 AssertReturn(obj.GetType() == DnDURIObject::Directory, VERR_INVALID_PARAMETER); 944 945 DragAndDropSvc::VBOXDNDGHSENDDIRMSG Msg; 946 RT_ZERO(Msg); 947 Msg.hdr.result = VERR_WRONG_ORDER; 948 Msg.hdr.u32ClientID = u32ClientId; 949 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_DIR; 950 Msg.hdr.cParms = 3; 951 952 RTCString strPath = obj.GetDestPath(); 953 LogFlowFunc(("strDir=%s (%zu), fMode=0x%x\n", 954 strPath.c_str(), strPath.length(), obj.GetMode())); 955 956 Msg.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1)); 957 Msg.cbName.SetUInt32((uint32_t)(strPath.length() + 1)); 958 Msg.fMode.SetUInt32(obj.GetMode()); 959 960 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 961 if (RT_SUCCESS(rc)) 962 rc = Msg.hdr.result; 963 964 LogFlowFuncLeaveRC(rc); 965 return rc; 966 } 967 968 static int vbglR3DnDGHSendFile(uint32_t u32ClientId, DnDURIObject &obj) 969 { 970 AssertReturn(obj.GetType() == DnDURIObject::File, VERR_INVALID_PARAMETER); 971 972 uint32_t cbBuf = _64K; /** @todo Make this configurable? */ 973 void *pvBuf = RTMemAlloc(cbBuf); 974 if (!pvBuf) 975 return VERR_NO_MEMORY; 976 977 DragAndDropSvc::VBOXDNDGHSENDFILEMSG Msg; 978 RT_ZERO(Msg); 979 Msg.hdr.result = VERR_WRONG_ORDER; 980 Msg.hdr.u32ClientID = u32ClientId; 981 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_SND_FILE; 982 Msg.hdr.cParms = 5; 983 984 RTCString strPath = obj.GetDestPath(); 985 LogFlowFunc(("strFile=%s (%zu), fMode=0x%x\n", 986 strPath.c_str(), strPath.length(), obj.GetMode())); 987 988 Msg.pvName.SetPtr((void *)strPath.c_str(), (uint32_t)(strPath.length() + 1)); 989 Msg.cbName.SetUInt32((uint32_t)(strPath.length() + 1)); 990 Msg.fMode.SetUInt32(obj.GetMode()); 991 992 int rc = VINF_SUCCESS; 993 uint32_t cbData = obj.GetSize(); 994 995 do 996 { 997 uint32_t cbToRead = RT_MIN(cbData, cbBuf); 998 uint32_t cbRead = 0; 999 if (cbToRead) 1000 rc = obj.Read(pvBuf, cbToRead, &cbRead); 1001 if (RT_SUCCESS(rc)) 1002 { 1003 Msg.cbData.SetUInt32(cbRead); 1004 Msg.pvData.SetPtr(pvBuf, cbRead); 1005 1006 rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1007 if (RT_SUCCESS(rc)) 1008 rc = Msg.hdr.result; 1009 } 1010 1011 if (RT_FAILURE(rc)) 1012 break; 1013 1014 Assert(cbRead <= cbData); 1015 cbData -= cbRead; 1016 1017 } while (cbData); 1018 1019 RTMemFree(pvBuf); 1020 1021 LogFlowFuncLeaveRC(rc); 1022 return rc; 1023 } 1024 1025 static int vbglR3DnDGHSendURIObject(uint32_t u32ClientId, DnDURIObject &obj) 1026 { 1027 int rc; 1028 1029 switch (obj.GetType()) 1030 { 1031 case DnDURIObject::Directory: 1032 rc = vbglR3DnDGHSendDir(u32ClientId, obj); 1033 break; 1034 1035 case DnDURIObject::File: 1036 rc = vbglR3DnDGHSendFile(u32ClientId, obj); 1037 break; 1038 1039 default: 1040 AssertMsgFailed(("Type %ld not implemented\n", 1041 obj.GetType())); 1042 rc = VERR_NOT_IMPLEMENTED; 1043 break; 1044 } 1045 1046 return rc; 1047 } 1048 1049 static int vbglR3DnDGHProcessURIMessages(uint32_t u32ClientId, 1050 void *pvData, uint32_t cbData) 1051 { 1052 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1053 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1054 1055 RTCList<RTCString> lstPaths = 1056 RTCString((const char *)pvData, cbData).split("\r\n"); 1057 1058 DnDURIList lstURI; 1059 int rc = lstURI.AppendNativePathsFromList(lstPaths, 0 /* fFlags */); 1060 if (RT_SUCCESS(rc)) 1061 { 1062 /* Send metadata; in this case it's the (non-recursive) file/directory 1063 * URI list the host needs to know to initialize the drag'n drop operation. */ 1064 RTCString strRootDest = lstURI.RootToString(); 1065 Assert(strRootDest.isNotEmpty()); 1066 1067 void *pvToSend = (void *)strRootDest.c_str(); 1068 uint32_t cbToSend = (uint32_t)strRootDest.length() + 1; 1069 1070 rc = vbglR3DnDGHSendDataInternal(u32ClientId, pvToSend, cbToSend, 1071 /* Include total bytes of all file paths, 1072 * file sizes etc. */ 1073 lstURI.TotalBytes()); 1074 } 1075 1076 if (RT_SUCCESS(rc)) 1077 { 1078 while (!lstURI.IsEmpty()) 1079 { 1080 DnDURIObject &nextObj = lstURI.First(); 1081 1082 rc = vbglR3DnDGHSendURIObject(u32ClientId, nextObj); 1083 if (RT_FAILURE(rc)) 1084 break; 1085 1086 lstURI.RemoveFirst(); 1087 } 1088 } 1089 1090 return rc; 1091 } 1092 1093 VBGLR3DECL(int) VbglR3DnDGHSendData(uint32_t u32ClientId, 1094 const char *pszFormat, 1095 void *pvData, uint32_t cbData) 1096 { 1097 AssertPtrReturn(pszFormat, VERR_INVALID_POINTER); 1098 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 1099 AssertReturn(cbData, VERR_INVALID_PARAMETER); 1100 1101 int rc; 1102 if (DnDMIMEHasFileURLs(pszFormat, strlen(pszFormat))) 1103 { 1104 rc = vbglR3DnDGHProcessURIMessages(u32ClientId, pvData, cbData); 1105 } 1106 else 1107 rc = vbglR3DnDGHSendDataInternal(u32ClientId, pvData, cbData, 1108 0 /* cbAdditionalData */); 963 1109 964 1110 return rc; … … 973 1119 Msg.hdr.u32Function = DragAndDropSvc::GUEST_DND_GH_EVT_ERROR; 974 1120 Msg.hdr.cParms = 1; 975 /* Initialize parameter */ 1121 976 1122 Msg.uRC.SetUInt32(rcOp); 977 /* Do request */ 978 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 979 if (RT_SUCCESS(rc)) 980 rc = Msg.hdr.result; 981 982 return rc; 983 } 984 985 VBGLR3DECL(int) VbglR3DnDGHSendFile(uint32_t u32ClientId, const char *pszPath) 986 { 987 return 0; 988 } 989 1123 1124 int rc = vbglR3DoIOCtl(VBOXGUEST_IOCTL_HGCM_CALL(sizeof(Msg)), &Msg, sizeof(Msg)); 1125 if (RT_SUCCESS(rc)) 1126 rc = Msg.hdr.result; 1127 1128 return rc; 1129 } 1130
Note:
See TracChangeset
for help on using the changeset viewer.