Changeset 50734 in vbox
- Timestamp:
- Mar 10, 2014 1:54:03 PM (11 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 6 edited
-
Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp (modified) (1 diff)
-
Additions/x11/VBoxClient/draganddrop.cpp (modified) (25 diffs)
-
Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp (modified) (5 diffs)
-
Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h (modified) (1 diff)
-
GuestHost/DragAndDrop/DnDURIList.cpp (modified) (2 diffs)
-
Main/src-client/GuestDnDImpl.cpp (modified) (14 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDnDDropTarget.cpp
r50732 r50734 464 464 RTCString strRoot = lstURI.RootToString(); 465 465 size_t cbRoot = strRoot.length() + 1; /* Include termination */ 466 Assert(cbRoot);467 466 468 467 mpvData = RTMemAlloc(cbRoot); -
trunk/src/VBox/Additions/x11/VBoxClient/draganddrop.cpp
r50724 r50734 45 45 * their behavior. Don't have this enabled in release builds! */ 46 46 #ifdef DEBUG 47 # define VBOX_DND_DEBUG_WND47 //# define VBOX_DND_DEBUG_WND 48 48 #endif 49 49 … … 76 76 * the data in the specified mime-type. This data is send back to the host. 77 77 * After that we send a XdndLeave event to the source window. 78 * Todo: 79 * - this isn't finished, yet. Currently the mouse isn't correctly released 80 * in the guest (both, when the drop was successfully or canceled). 81 * - cancel (e.g. with the ESC key) doesn't work 78 * 79 * To-do: 80 * - Cancelling (e.g. with ESC key) doesn't work. 82 81 * 83 * Todo: 84 * - XdndProxy window support 85 * - INCR support 86 * - make this much more robust for crashes of the other party 87 * - really check for the Xdnd version and the supported features 82 * To-do: 83 * - INCR (incremental transfers) support. 84 * - Make this much more robust for crashes of the other party. 85 * - Really check for the Xdnd version and the supported features. 88 86 */ 89 87 … … 390 388 void mouseButtonSet(Window wndDest, int rx, int ry, int iButton, bool fPress) const; 391 389 int proxyWinShow(int *piRootX = NULL, int *piRootY = NULL, bool fMouseMove = false) const; 392 int proxyWinHide(void) const;390 int proxyWinHide(void); 393 391 void registerForEvents(Window w) const; 394 392 … … 569 567 m_curVer = -1; 570 568 m_state = Initialized; 569 m_eventQueue.clear(); 571 570 } 572 571 … … 740 739 case GH: 741 740 { 742 //if (m_state == Dropped) 743 //{ 744 LogFlowThisFunc(("Enqueuing ClientMessage\n")); 745 746 m_eventQueue.append(e); 747 rc = RTSemEventSignal(m_hEventSem); 748 //} 749 750 //rc = VINF_SUCCESS; 741 LogFlowThisFunc(("Enqueuing ClientMessage\n")); 742 743 m_eventQueue.append(e); 744 rc = RTSemEventSignal(m_hEventSem); 751 745 break; 752 746 } … … 885 879 memcpy(&m_eventHgSelection, &e, sizeof(XEvent)); 886 880 887 const char *pcszFormat = xAtomToString(e.xselectionrequest.target).c_str();888 Assert Ptr(pcszFormat);889 rc = VbglR3DnDHGRequestData(m_uClientID, pcszFormat);881 RTCString strFormat = xAtomToString(e.xselectionrequest.target); 882 Assert(strFormat.isNotEmpty()); 883 rc = VbglR3DnDHGRequestData(m_uClientID, strFormat.c_str()); 890 884 LogFlowThisFunc(("Requesting data from host as \"%s\", rc=%Rrc\n", 891 pcszFormat, rc));885 strFormat.c_str(), rc)); 892 886 } 893 887 } … … 936 930 switch (e.type) 937 931 { 932 case ButtonPress: 933 LogFlowThisFunc(("ButtonPress\n")); 934 rc = VINF_SUCCESS; 935 break; 936 937 case ButtonRelease: 938 LogFlowThisFunc(("ButtonRelease\n")); 939 rc = VINF_SUCCESS; 940 break; 941 942 case ClientMessage: 943 rc = onX11ClientMessage(e); 944 break; 945 946 case SelectionClear: 947 LogFlowThisFunc(("SelectionClear\n")); 948 reset(); 949 rc = VINF_SUCCESS; 950 break; 951 938 952 case SelectionNotify: 939 953 rc = onX11SelectionNotify(e); … … 943 957 rc = onX11SelectionRequest(e); 944 958 break; 945 946 case ClientMessage:947 rc = onX11ClientMessage(e);948 break;949 950 case SelectionClear:951 LogFlowThisFunc(("SelectionClear\n"));952 rc = VINF_SUCCESS;953 break;954 959 955 960 /*case MotionNotify: … … 1135 1140 0, 2, False, AnyPropertyType, 1136 1141 &atmp, &fmt, &cItems, &cbRemaining, &pcData); 1142 1137 1143 if (RT_UNLIKELY(xrc != Success)) 1138 1144 LogFlowThisFunc(("Error in getting the window property: %s\n", gX11->xErrorToString(xrc).c_str())); … … 1146 1152 LogFlowThisFunc(("wndCursor=%#x, XdndAware=%u\n", newVer)); 1147 1153 } 1154 1148 1155 XFree(pcData); 1149 1156 } … … 1153 1160 * Is the window under the cursor another one than our current one? 1154 1161 */ 1155 if (wndCursor != m_wndCur && m_curVer != -1) 1162 if ( wndCursor != m_wndCur 1163 && m_curVer != -1) 1156 1164 { 1157 1165 LogFlowThisFunc(("Leaving window=%#x\n", m_wndCur)); … … 1212 1220 */ 1213 1221 Atom pa = toX11Action(uAction); 1214 LogFlowThisFunc(("strAction= '%s'", xAtomToString(pa).c_str()));1222 LogFlowThisFunc(("strAction=%s\n", xAtomToString(pa).c_str())); 1215 1223 1216 1224 XClientMessageEvent m; … … 1231 1239 } 1232 1240 1233 if (wndCursor == None && newVer == -1) 1241 if ( wndCursor == None 1242 && newVer == -1) 1234 1243 { 1235 1244 /* No window to process, so send a ignore ack event to the host. */ … … 1356 1365 AssertPtr(pEventClient); 1357 1366 1358 LogFlowThisFunc((" Next X event is:%s\n",1367 LogFlowThisFunc(("Received event=%s\n", 1359 1368 gX11->xAtomToString(pEventClient->message_type).c_str())); 1360 1369 … … 1370 1379 m_state = Dragging; 1371 1380 m_wndCur = wndSelection; 1381 Assert(m_wndCur == pEventClient->data.l[0]); 1372 1382 1373 1383 LogFlowThisFunc(("XA_XdndEnter\n")); … … 1438 1448 XClientMessageEvent m; 1439 1449 RT_ZERO(m); 1440 1441 1450 m.type = ClientMessage; 1442 1451 m.display = m_pDisplay; 1443 m.window = pEventClient->data.l[0];1452 m.window = m_wndCur; 1444 1453 m.message_type = xAtom(XA_XdndStatus); 1445 1454 m.format = 32; 1446 1455 m.data.l[0] = m_wndProxy; 1447 m.data.l[1] = 1;1448 m.data.l[4] = xAtom(XA_XdndActionCopy); 1449 1450 xRc = XSendEvent(m_pDisplay, pEventClient->data.l[0],1456 m.data.l[1] = RT_BIT(0); /* Accept the drop. */ 1457 m.data.l[4] = xAtom(XA_XdndActionCopy); /** @todo Make the accepted action configurable. */ 1458 1459 xRc = XSendEvent(m_pDisplay, m_wndCur, 1451 1460 False, 0, reinterpret_cast<XEvent*>(&m)); 1452 1461 if (RT_UNLIKELY(xRc == 0)) … … 1464 1473 m.type = ClientMessage; 1465 1474 m.display = m_pDisplay; 1466 m.window = pEventClient->data.l[0];1475 m.window = m_wndCur; 1467 1476 m.message_type = xAtom(XA_XdndStatus); 1468 1477 m.format = 32; 1469 1478 m.data.l[0] = m_wndProxy; 1470 m.data.l[1] = 1;1471 m.data.l[4] = pEventClient->data.l[4];1472 1473 xRc = XSendEvent(m_pDisplay, pEventClient->data.l[0],1479 m.data.l[1] = RT_BIT(0); /* Accept the drop. */ 1480 m.data.l[4] = xAtom(XA_XdndActionCopy); /** @todo Make the accepted action configurable. */ 1481 1482 xRc = XSendEvent(m_pDisplay, m_wndCur, 1474 1483 False, 0, reinterpret_cast<XEvent*>(&m)); 1475 1484 if (RT_UNLIKELY(xRc == 0)) … … 1482 1491 } 1483 1492 1484 proxyWinHide();1485 1486 1493 /* Do we need to acknowledge at least one format to the host? */ 1487 1494 if (!m_formats.isEmpty()) … … 1527 1534 /* We send a fake release event to the current window, cause 1528 1535 * this should have the grab. */ 1529 mouseButtonSet(m_wndCur , iRootX, iRootY,1536 mouseButtonSet(m_wndCur /* Source window */, iRootX, iRootY, 1530 1537 1 /* Button */, false /* Release button */); 1531 1538 … … 1542 1549 /* Request to convert the selection in the specific format and 1543 1550 * place it to our proxy window as property. */ 1544 Window srcWin = m_wndCur;//clme->data.l[0]; 1551 Window wndSource = evDnDDrop.data.l[0]; /* Source window which sent the message. */ 1552 Assert(wndSource == m_wndCur); 1545 1553 Atom aFormat = gX11->stringToxAtom(strFormat.c_str()); 1546 1554 … … 1554 1562 if (waitForX11Msg(evSelNotify, SelectionNotify)) 1555 1563 { 1564 bool fCancel = false; 1565 1556 1566 /* Make some paranoid checks. */ 1557 1567 if ( evSelNotify.xselection.type == SelectionNotify … … 1616 1626 strFormat.c_str(), rc)); 1617 1627 1618 /* Confirm the result of the transfer to the source window. */ 1619 XClientMessageEvent m; 1620 RT_ZERO(m); 1621 m.type = ClientMessage; 1622 m.display = m_pDisplay; 1623 m.window = srcWin; 1624 m.message_type = xAtom(XA_XdndFinished); 1625 m.format = 32; 1626 m.data.l[0] = m_wndProxy; 1627 m.data.l[1] = RT_SUCCESS(rc) ? 1 : 0; /* Confirm or deny success */ 1628 m.data.l[2] = RT_SUCCESS(rc) ? toX11Action(uAction) : None; /* Action used on success */ 1629 1630 int xrc = XSendEvent(m_pDisplay, srcWin, True, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1631 if (RT_UNLIKELY(xrc == 0)) 1632 LogFlowThisFunc(("Error sending xEvent\n")); 1628 if (RT_SUCCESS(rc)) 1629 { 1630 /* Confirm the result of the transfer to the source window. */ 1631 XClientMessageEvent m; 1632 RT_ZERO(m); 1633 m.type = ClientMessage; 1634 m.display = m_pDisplay; 1635 m.window = m_wndProxy; 1636 m.message_type = xAtom(XA_XdndFinished); 1637 m.format = 32; 1638 m.data.l[0] = m_wndProxy; /* Target window. */ 1639 m.data.l[1] = 0; /* Don't accept the drop to not make the guest stuck. */ 1640 m.data.l[2] = RT_SUCCESS(rc) ? toX11Action(uAction) : None; /* Action used on success */ 1641 1642 int xrc = XSendEvent(m_pDisplay, wndSource, True, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1643 if (RT_UNLIKELY(xrc == 0)) 1644 LogFlowThisFunc(("Error sending xEvent\n")); 1645 } 1646 else 1647 fCancel = true; 1633 1648 } 1634 1649 else … … 1642 1657 else 1643 1658 { 1644 AssertMsgFailed(("Not supported data type\n")); 1659 AssertMsgFailed(("Not supported data type (%s)\n", 1660 gX11->xAtomToString(aPropType).c_str())); 1645 1661 rc = VERR_INVALID_PARAMETER; 1646 1662 } 1663 1664 fCancel = true; 1665 } 1666 1667 if (fCancel) 1668 { 1669 LogFlowFunc(("Cancelling drop ...\n")); 1647 1670 1648 1671 /* Cancel this. */ … … 1651 1674 m.type = ClientMessage; 1652 1675 m.display = m_pDisplay; 1653 m.window = srcWin;1676 m.window = m_wndProxy; 1654 1677 m.message_type = xAtom(XA_XdndFinished); 1655 1678 m.format = 32; 1656 m.data.l[0] = m_wndProxy; 1657 m.data.l[1] = 0; 1658 m.data.l[2] = None; 1659 1660 int xrc = XSendEvent(m_pDisplay, srcWin, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1679 m.data.l[0] = m_wndProxy; /* Target window. */ 1680 m.data.l[1] = 0; /* Don't accept the drop to not make the guest stuck. */ 1681 1682 int xrc = XSendEvent(m_pDisplay, wndSource, False, NoEventMask, reinterpret_cast<XEvent*>(&m)); 1661 1683 if (RT_UNLIKELY(xrc == 0)) 1662 LogFlowThisFunc(("Error sending xEvent\n")); 1663 m_wndCur = 0; 1684 LogFlowThisFunc(("Error sending cancel event\n")); 1664 1685 } 1665 1686 … … 1848 1869 } 1849 1870 1850 int DragInstance::proxyWinHide(void) const 1851 { 1852 LogFlowThisFuncEnter(); 1853 return 0; 1871 int DragInstance::proxyWinHide(void) 1872 { 1873 LogFlowFuncEnter(); 1854 1874 1855 1875 XUnmapWindow(m_pDisplay, m_wndProxy); 1876 m_eventQueue.clear(); 1856 1877 1857 1878 return VINF_SUCCESS; /** @todo Add error checking. */ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.cpp
r50640 r50734 185 185 186 186 #ifndef RT_OS_WINDOWS 187 bool UIDnDMimeData::eventFilter(QObject * /* pObject */, QEvent *pEvent)187 bool UIDnDMimeData::eventFilter(QObject *pObject, QEvent *pEvent) 188 188 { 189 189 if (pEvent) … … 198 198 LogFlowFunc(("MouseMove: x=%d, y=%d\n", 199 199 pMouseEvent->globalX(), pMouseEvent->globalY())); 200 break; 200 201 return true; 202 /* Never reached. */ 201 203 } 202 204 #endif … … 205 207 LogFlowFunc(("MouseButtonRelease\n")); 206 208 m_enmState = Dropped; 207 break; 209 210 return true; 211 /* Never reached. */ 208 212 } 209 213 … … 216 220 m_enmState = Canceled; 217 221 } 218 break; 222 223 return true; 224 /* Never reached. */ 219 225 } 220 226 … … 224 230 } 225 231 226 /* Propagate the event further. */ 227 return false; 232 return QObject::eventFilter(pObject, pEvent); 228 233 } 229 234 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIDnDMIMEData.h
r50602 r50734 81 81 82 82 #ifndef RT_OS_WINDOWS 83 bool eventFilter(QObject * /* pObject */, QEvent *pEvent);83 bool eventFilter(QObject *pObject, QEvent *pEvent); 84 84 #endif 85 85 /** @} */ -
trunk/src/VBox/GuestHost/DragAndDrop/DnDURIList.cpp
r50724 r50734 410 410 AssertPtrReturn(pszURI, VERR_INVALID_POINTER); 411 411 412 /** @todo Check for string termination? */ 412 413 #ifdef DEBUG_andy 413 414 LogFlowFunc(("pszPath=%s, fFlags=0x%x\n", pszURI, fFlags)); … … 422 423 /* Add the path to our internal file list (recursive in 423 424 * the case of a directory). */ 424 char *pszFileName = RTPathFilename(pszFilePath); 425 if (pszFileName) 426 { 427 Assert(pszFileName >= pszFilePath); 428 char *pszRoot = &pszFilePath[pszFileName - pszFilePath]; 429 m_lstRoot.append(pszRoot); 430 #ifdef DEBUG_andy 431 LogFlowFunc(("pszFilePath=%s, pszFileName=%s, pszRoot=%s\n", 432 pszFilePath, pszFileName, pszRoot)); 433 #endif 434 rc = appendPathRecursive(pszFilePath, 435 pszFileName - pszFilePath, 436 fFlags); 425 size_t cbPathLen = RTPathStripTrailingSlash(pszFilePath); 426 if (cbPathLen) 427 { 428 char *pszFileName = RTPathFilename(pszFilePath); 429 if (pszFileName) 430 { 431 Assert(pszFileName >= pszFilePath); 432 char *pszRoot = &pszFilePath[pszFileName - pszFilePath]; 433 m_lstRoot.append(pszRoot); 434 #ifdef DEBUG_andy 435 LogFlowFunc(("pszFilePath=%s, pszFileName=%s, pszRoot=%s\n", 436 pszFilePath, pszFileName, pszRoot)); 437 #endif 438 rc = appendPathRecursive(pszFilePath, 439 pszFileName - pszFilePath, 440 fFlags); 441 } 442 else 443 rc = VERR_NOT_FOUND; 437 444 } 438 445 else 439 rc = VERR_ NOT_FOUND;446 rc = VERR_INVALID_PARAMETER; 440 447 441 448 RTStrFree(pszFilePath); -
trunk/src/VBox/Main/src-client/GuestDnDImpl.cpp
r50724 r50734 204 204 HRESULT queryProgressTo(IProgress **ppProgress); 205 205 206 int writeToFile(const char *pszPath, size_t cbPath, void *pvData, size_t cbData, uint32_t fMode); 207 206 208 public: 207 209 … … 223 225 /** Dropped files directory on the host. */ 224 226 Utf8Str m_strDropDir; 227 /** The handle of the currently opened file being written to 228 * or read from. */ 229 RTFILE m_hFile; 230 Utf8Str m_strFile; 225 231 226 232 ComObjPtr<Guest> m_parent; … … 294 300 , m_cbDataCurrent(0) 295 301 , m_cbDataTotal(0) 302 , m_hFile(NIL_RTFILE) 296 303 , m_parent(pGuest) 297 304 { … … 303 310 { 304 311 reset(); 312 305 313 int rc = RTSemEventDestroy(m_EventSem); 306 314 AssertRC(rc); … … 346 354 break; 347 355 356 case VERR_NOT_FOUND: 357 /* Should not happen due to file locking on the guest, but anyway ... */ 358 strError += Utf8StrFmt(pGuest->tr("One or more guest files or directories selected for transferring to the host were not" 359 "found on the guest anymore. This can be the case if the guest files were moved and/or" 360 "altered while the drag'n drop operation was in progress.")); 361 break; 362 348 363 case VERR_SHARING_VIOLATION: 349 364 strError += Utf8StrFmt(pGuest->tr("One or more guest files or directories selected for transferring to the host were locked. " … … 367 382 void DnDGuestResponse::reset(void) 368 383 { 384 LogFlowThisFuncEnter(); 385 386 m_defAction = 0; 387 m_allActions = 0; 388 369 389 m_strDropDir = ""; 370 390 m_strFormat = ""; … … 375 395 m_pvData = NULL; 376 396 } 377 m_cbData = 0; 378 397 m_cbData = 0; 379 398 m_cbDataCurrent = 0; 380 399 m_cbDataTotal = 0; 400 401 if (m_hFile != NIL_RTFILE) 402 { 403 RTFileClose(m_hFile); 404 m_hFile = NIL_RTFILE; 405 } 406 m_strFile = ""; 381 407 } 382 408 … … 492 518 } 493 519 520 int DnDGuestResponse::writeToFile(const char *pszPath, size_t cbPath, 521 void *pvData, size_t cbData, uint32_t fMode) 522 { 523 /** @todo Support locking more than one file at a time! We 524 * might want to have a table in DnDGuestImpl which 525 * keeps those file pointers around, or extend the 526 * actual protocol for explicit open calls. 527 * 528 * For now we only keep one file open at a time, so if 529 * a client does alternating writes to different files 530 * this function will close the old and re-open the new 531 * file on every call. */ 532 int rc; 533 if ( m_hFile == NIL_RTFILE 534 || m_strFile != pszPath) 535 { 536 char *pszFile = RTPathJoinA(m_strDropDir.c_str(), pszPath); 537 if (pszFile) 538 { 539 RTFILE hFile; 540 /** @todo Respect fMode! */ 541 rc = RTFileOpen(&hFile, pszFile, 542 RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE 543 | RTFILE_O_WRITE | RTFILE_O_APPEND); 544 if (RT_SUCCESS(rc)) 545 { 546 LogFlowFunc(("Opening \"%s\" (fMode=0x%x) for writing ...\n", 547 pszFile, fMode)); 548 549 m_hFile = hFile; 550 m_strFile = pszPath; 551 } 552 553 RTStrFree(pszFile); 554 } 555 else 556 rc = VERR_NO_MEMORY; 557 } 558 else 559 rc = VINF_SUCCESS; 560 561 if (RT_SUCCESS(rc)) 562 { 563 rc = RTFileWrite(m_hFile, pvData, cbData, 564 NULL /* No partial writes */); 565 566 if (RT_SUCCESS(rc)) 567 rc = dataSetStatus(cbData); 568 } 569 570 return rc; 571 } 572 494 573 /////////////////////////////////////////////////////////////////////////////// 495 574 … … 719 798 720 799 DnDGuestResponse *pResp = d->response(); 721 /* This blocks until the request is answered (or timeout). */722 800 if (pResp->waitForGuestResponse() == VERR_TIMEOUT) 723 801 return S_OK; … … 783 861 784 862 DnDGuestResponse *pResp = d->response(); 785 /* This blocks until the request is answered (or timeout). */786 863 if (pResp->waitForGuestResponse() == VERR_TIMEOUT) 787 864 return S_OK; … … 813 890 814 891 DnDGuestResponse *pResp = d->response(); 815 /* This blocks until the request is answered (or timeout). */816 892 pResp->waitForGuestResponse(); 817 893 } … … 873 949 874 950 DnDGuestResponse *pResp = d->response(); 875 /* This blocks until the request is answered (or timeout). */876 951 if (pResp->waitForGuestResponse() == VERR_TIMEOUT) 877 952 return S_OK; 878 953 879 /* Copy the response info*/954 /* Get the resulting action from the guest. */ 880 955 *pResultAction = d->toMainAction(pResp->defAction()); 956 957 LogFlowFunc(("resFormat=%s, resAction=%RU32\n", 958 pResp->format().c_str(), pResp->defAction())); 959 881 960 Bstr(pResp->format()).cloneTo(pstrFormat); 882 883 LogFlowFunc(("*pResultAction=%ld\n", *pResultAction));884 961 } 885 962 catch (HRESULT hr2) … … 957 1034 paParms); 958 1035 959 /* This blocks until the request is answered (or timed out). */960 1036 DnDGuestResponse *pResp = d->response(); 961 1037 if (pResp->waitForGuestResponse() == VERR_TIMEOUT) … … 1167 1243 pszPath, cbPath, fMode)); 1168 1244 1169 /** @todo Add file locking between calls! */ 1170 int rc; 1171 char *pszFile = RTPathJoinA(pResp->dropDir().c_str(), pszPath); 1172 if (pszFile) 1173 { 1174 RTFILE hFile; 1175 rc = RTFileOpen(&hFile, pszFile, 1176 RTFILE_O_CREATE_REPLACE | RTFILE_O_DENY_WRITE | RTFILE_O_WRITE); 1177 if (RT_SUCCESS(rc)) 1178 { 1179 rc = RTFileWrite(hFile, pvData, cbData, 1180 NULL /* No partial writes */); 1181 RTFileClose(hFile); 1182 } 1183 RTStrFree(pszFile); 1184 } 1185 else 1186 rc = VERR_NO_MEMORY; 1187 1188 if (RT_SUCCESS(rc)) 1189 rc = pResp->dataSetStatus(cbData); 1245 int rc = pResp->writeToFile(pszPath, cbPath, pvData, cbData, fMode); 1190 1246 1191 1247 LogFlowFuncLeaveRC(rc);
Note:
See TracChangeset
for help on using the changeset viewer.

