Changeset 92228 in vbox
- Timestamp:
- Nov 4, 2021 11:48:50 PM (3 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/utils/clipboard/ClipUtil.cpp
r92161 r92228 177 177 { "--target", 't', RTGETOPT_REQ_STRING }, 178 178 #endif 179 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 180 { "--close", 'k', RTGETOPT_REQ_NOTHING }, 181 #endif 182 { "--wait", 'w', RTGETOPT_REQ_UINT32 }, 179 183 { "--quiet", 'q', RTGETOPT_REQ_NOTHING }, 180 184 { "--verbose", 'v', RTGETOPT_REQ_NOTHING }, … … 227 231 #elif defined(RT_OS_OS2) 228 232 /** Anchorblock handle. */ 229 static HAB g_hOs2 Hab = NULLHANDLE;233 static HAB g_hOs2Ab = NULLHANDLE; 230 234 /** The message queue handle. */ 231 235 static HMQ g_hOs2MsgQueue = NULLHANDLE; … … 236 240 /** Set if we're the clipboard owner. */ 237 241 static bool g_fOs2ClipboardOwner = false; 242 /** Set when we receive a WM_TIMER message during DoWait(). */ 243 static bool volatile g_fOs2TimerTicked = false; 238 244 239 245 #elif defined(RT_OS_WINDOWS) 240 246 /** Set if we've opened the clipboard. */ 241 static bool g_fOpenedClipboard = false; 247 static bool g_fWinOpenedClipboard = false; 248 /** Set when we receive a WM_TIMER message during DoWait(). */ 249 static bool volatile g_fWinTimerTicked = false; 250 /** Window that becomes clipboard owner when setting data. */ 251 static HWND g_hWinWnd = NULL; 242 252 243 253 #else … … 275 285 g_aFormats[i].fFormat = WinAddAtom(WinQuerySystemAtomTable(), g_aFormats[i].pszFormat); 276 286 if (g_aFormats[i].fFormat == 0) 277 RTMsgError("WinAddAtom(,%s) failed: %#x", g_aFormats[i].pszFormat, WinGetLastError(g_hOs2 Hab));287 RTMsgError("WinAddAtom(,%s) failed: %#x", g_aFormats[i].pszFormat, WinGetLastError(g_hOs2Ab)); 278 288 } 279 289 … … 308 318 if (AdHoc.fFormat == 0) 309 319 { 310 RTMsgError("Invalid format '%s' (%#x)", pszFormat, WinGetLastError(g_hOs2 Hab));320 RTMsgError("Invalid format '%s' (%#x)", pszFormat, WinGetLastError(g_hOs2Ab)); 311 321 return NULL; 312 322 } … … 412 422 case WM_ADJUSTWINDOWPOS: 413 423 break; 424 425 /* 426 * We use this window fielding WM_TIMER during DoWait. 427 */ 428 case WM_TIMER: 429 if (SHORT1FROMMP(mp1) == 1) 430 g_fOs2TimerTicked = true; 431 break; 414 432 } 415 433 return NULL; 416 434 } 417 435 436 418 437 /** 419 438 * Initialize the OS/2 bits. … … 421 440 static RTEXITCODE CuOs2Init(void) 422 441 { 423 g_hOs2 Hab = WinInitialize(0);424 if (g_hOs2 Hab == NULLHANDLE)442 g_hOs2Ab = WinInitialize(0); 443 if (g_hOs2Ab == NULLHANDLE) 425 444 return RTMsgErrorExitFailure("WinInitialize failed!"); 426 445 427 g_hOs2MsgQueue = WinCreateMsgQueue(g_hOs2 Hab, 10);446 g_hOs2MsgQueue = WinCreateMsgQueue(g_hOs2Ab, 10); 428 447 if (g_hOs2MsgQueue == NULLHANDLE) 429 return RTMsgErrorExitFailure("WinCreateMsgQueue failed: %#x", WinGetLastError(g_hOs2 Hab));448 return RTMsgErrorExitFailure("WinCreateMsgQueue failed: %#x", WinGetLastError(g_hOs2Ab)); 430 449 431 450 static char s_szClass[] = "VBox-ClipUtilClipboardClass"; 432 451 if (!WinRegisterClass(g_hOs2Wnd, (PCSZ)s_szClass, CuOs2WinProc, 0, 0)) 433 return RTMsgErrorExitFailure("WinRegisterClass failed: %#x", WinGetLastError(g_hOs2 Hab));452 return RTMsgErrorExitFailure("WinRegisterClass failed: %#x", WinGetLastError(g_hOs2Ab)); 434 453 435 454 g_hOs2Wnd = WinCreateWindow(HWND_OBJECT, /* hwndParent */ … … 444 463 NULL); /* pPresParams */ 445 464 if (g_hOs2Wnd == NULLHANDLE) 446 return RTMsgErrorExitFailure("WinCreateWindow failed: %#x", WinGetLastError(g_hOs2 Hab));465 return RTMsgErrorExitFailure("WinCreateWindow failed: %#x", WinGetLastError(g_hOs2Ab)); 447 466 448 467 return RTEXITCODE_SUCCESS; … … 457 476 if (g_fOs2OpenedClipboard) 458 477 { 459 if (!WinCloseClipbrd(g_hOs2 Hab))460 return RTMsgErrorExitFailure("WinCloseClipbrd failed: %#x", WinGetLastError(g_hOs2 Hab));478 if (!WinCloseClipbrd(g_hOs2Ab)) 479 return RTMsgErrorExitFailure("WinCloseClipbrd failed: %#x", WinGetLastError(g_hOs2Ab)); 461 480 g_fOs2OpenedClipboard = false; 462 481 } … … 468 487 g_hOs2MsgQueue = NULLHANDLE; 469 488 470 WinTerminate(g_hOs2 Hab);471 g_hOs2 Hab = NULLHANDLE;489 WinTerminate(g_hOs2Ab); 490 g_hOs2Ab = NULLHANDLE; 472 491 473 492 return RTEXITCODE_SUCCESS; … … 482 501 if (g_fOs2OpenedClipboard) 483 502 return RTEXITCODE_SUCCESS; 484 if (WinOpenClipbrd(g_hOs2Hab)) 485 { 503 if (WinOpenClipbrd(g_hOs2Ab)) 504 { 505 if (g_uVerbosity > 0) 506 RTMsgInfo("Opened the clipboard\n"); 486 507 g_fOs2OpenedClipboard = true; 487 508 return RTEXITCODE_SUCCESS; 488 509 } 489 return RTMsgErrorExitFailure("WinOpenClipbrd failed: %#x", WinGetLastError(g_hOs2 Hab));510 return RTMsgErrorExitFailure("WinOpenClipbrd failed: %#x", WinGetLastError(g_hOs2Ab)); 490 511 } 491 512 … … 494 515 495 516 /** 517 * Window procedure for the clipboard owner window on Windows. 518 */ 519 static LRESULT CALLBACK CuWinWndProc(HWND hWnd, UINT idMsg, WPARAM wParam, LPARAM lParam) RT_NOTHROW_DEF 520 { 521 if (g_uVerbosity > 2) 522 RTMsgInfo("CuWinWndProc: hWnd=%p idMsg=%#05x wParam=%#zx lParam=%#zx\n", hWnd, idMsg, wParam, lParam); 523 524 switch (idMsg) 525 { 526 case WM_TIMER: 527 if (wParam == 1) 528 g_fWinTimerTicked = true; 529 break; 530 } 531 return DefWindowProc(hWnd, idMsg, wParam, lParam); 532 } 533 534 535 /** 536 * Initialize the Windows bits. 537 */ 538 static RTEXITCODE CuWinInit(void) 539 { 540 /* Register the window class: */ 541 static wchar_t s_wszClass[] = L"VBox-ClipUtilClipboardClass"; 542 WNDCLASSW WndCls = {0}; 543 WndCls.style = CS_NOCLOSE; 544 WndCls.lpfnWndProc = CuWinWndProc; 545 WndCls.cbClsExtra = 0; 546 WndCls.cbWndExtra = 0; 547 WndCls.hInstance = (HINSTANCE)GetModuleHandle(NULL); 548 WndCls.hIcon = NULL; 549 WndCls.hCursor = NULL; 550 WndCls.hbrBackground = (HBRUSH)(COLOR_BACKGROUND + 1); 551 WndCls.lpszMenuName = NULL; 552 WndCls.lpszClassName = s_wszClass; 553 554 ATOM uAtomWndClass = RegisterClassW(&WndCls); 555 if (!uAtomWndClass) 556 return RTMsgErrorExitFailure("RegisterClassW failed: %u (%#x)", GetLastError(), GetLastError()); 557 558 /* Create the clipboard owner window: */ 559 g_hWinWnd = CreateWindowExW(WS_EX_TRANSPARENT, /* fExStyle */ 560 s_wszClass, /* pwszClass */ 561 L"VirtualBox Clipboard Utility", /* pwszName */ 562 0, /* fStyle */ 563 0, 0, 0, 0, /* x, y, cx, cy */ 564 HWND_MESSAGE, /* hWndParent */ 565 NULL, /* hMenu */ 566 (HINSTANCE)GetModuleHandle(NULL), /* hinstance */ 567 NULL); /* pParam */ 568 if (g_hWinWnd == NULL) 569 return RTMsgErrorExitFailure("CreateWindowExW failed: %u (%#x)", GetLastError(), GetLastError()); 570 571 return RTEXITCODE_SUCCESS; 572 } 573 574 /** 496 575 * Terminates the Windows bits. 497 576 */ 498 577 static RTEXITCODE CuWinTerm(void) 499 578 { 500 if (g_fOpenedClipboard) 501 { 502 if (!CloseClipboard()) 503 return RTMsgErrorExitFailure("CloseClipboard failed: %u (%#x)", GetLastError(), GetLastError()); 504 g_fOpenedClipboard = false; 505 } 506 return RTEXITCODE_SUCCESS; 579 RTEXITCODE rcExit = RTEXITCODE_SUCCESS; 580 if (g_fWinOpenedClipboard) 581 { 582 if (CloseClipboard()) 583 g_fWinOpenedClipboard = false; 584 else 585 rcExit = RTMsgErrorExitFailure("CloseClipboard failed: %u (%#x)", GetLastError(), GetLastError()); 586 } 587 588 if (g_hWinWnd != NULL) 589 { 590 if (!DestroyWindow(g_hWinWnd)) 591 rcExit = RTMsgErrorExitFailure("DestroyWindow failed: %u (%#x)", GetLastError(), GetLastError()); 592 g_hWinWnd = NULL; 593 } 594 595 return rcExit; 507 596 } 508 597 … … 513 602 static RTEXITCODE WinOpenClipboardIfNecessary(void) 514 603 { 515 if (g_f OpenedClipboard)604 if (g_fWinOpenedClipboard) 516 605 return RTEXITCODE_SUCCESS; 517 if (OpenClipboard(NULL)) 518 { 519 g_fOpenedClipboard = true; 606 if (OpenClipboard(g_hWinWnd)) 607 { 608 if (g_uVerbosity > 0) 609 RTMsgInfo("Opened the clipboard\n"); 610 g_fWinOpenedClipboard = true; 520 611 return RTEXITCODE_SUCCESS; 521 612 } … … 585 676 586 677 678 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 679 /** 680 * Closes the clipboard if open. 681 */ 682 static RTEXITCODE CuCloseClipboard(void) 683 { 684 # if defined(RT_OS_OS2) 685 if (g_fOs2OpenedClipboard) 686 { 687 if (!WinCloseClipbrd(g_hOs2Ab)) 688 return RTMsgErrorExitFailure("WinCloseClipbrd failed: %#x", WinGetLastError(g_hOs2Ab)); 689 g_fOs2OpenedClipboard = false; 690 if (g_uVerbosity > 0) 691 RTMsgInfo("Closed the clipboard.\n"); 692 } 693 # else 694 if (g_fWinOpenedClipboard) 695 { 696 if (!CloseClipboard()) 697 return RTMsgErrorExitFailure("CloseClipboard failed: %u (%#x)", GetLastError(), GetLastError()); 698 g_fWinOpenedClipboard = false; 699 if (g_uVerbosity > 0) 700 RTMsgInfo("Closed the clipboard.\n"); 701 } 702 # endif 703 else if (g_uVerbosity > 0) 704 RTMsgInfo("No need to close clipboard, not opened.\n"); 705 706 return RTEXITCODE_SUCCESS; 707 } 708 #endif /* RT_OS_OS2 || RT_OS_WINDOWS */ 709 710 587 711 /** 588 712 * Lists the clipboard format. … … 597 721 uint32_t idx = 0; 598 722 ULONG fFormat = 0; 599 while ((fFormat = WinEnumClipbrdFmts(g_hOs2 Hab)) != 0)723 while ((fFormat = WinEnumClipbrdFmts(g_hOs2Ab)) != 0) 600 724 { 601 725 char szName[256] = {0}; … … 763 887 { 764 888 ULONG fFmtInfo = 0; 765 if (WinQueryClipbrdFmtInfo(g_hOs2 Hab, pFmtDesc->fFormat, &fFmtInfo))766 { 767 ULONG uData = WinQueryClipbrdData(g_hOs2 Hab, pFmtDesc->fFormat);889 if (WinQueryClipbrdFmtInfo(g_hOs2Ab, pFmtDesc->fFormat, &fFmtInfo)) 890 { 891 ULONG uData = WinQueryClipbrdData(g_hOs2Ab, pFmtDesc->fFormat); 768 892 if (fFmtInfo & CFI_POINTER) 769 893 { … … 813 937 else 814 938 rcExit = RTMsgErrorExitFailure("WinQueryClipbrdFmtInfo(,%s,) failed: %#x\n", 815 pFmtDesc->pszName, WinGetLastError(g_hOs2 Hab));939 pFmtDesc->pszName, WinGetLastError(g_hOs2Ab)); 816 940 } 817 941 return rcExit; … … 965 1089 memcpy(pvShared, pvData, cbData); 966 1090 967 if (WinSetClipbrdData(g_hOs2Hab, (uintptr_t)pvShared, pFmtDesc->fFormat, CFI_POINTER)) 1091 if (WinSetClipbrdData(g_hOs2Ab, (uintptr_t)pvShared, pFmtDesc->fFormat, CFI_POINTER)) 1092 { 1093 if (g_uVerbosity > 0) 1094 RTMsgInfo("Put '%s' on the clipboard: %p LB %zu\n", pFmtDesc->pszName, pvShared, cbData); 968 1095 rcExit = RTEXITCODE_SUCCESS; 1096 } 969 1097 else 970 1098 { 971 1099 rcExit = RTMsgErrorExitFailure("WinSetClipbrdData(,%p LB %#x,%s,) failed: %#x\n", 972 pvShared, cbData, pFmtDesc->pszName, WinGetLastError(g_hOs2 Hab));1100 pvShared, cbData, pFmtDesc->pszName, WinGetLastError(g_hOs2Ab)); 973 1101 DosFreeMem(pvShared); 974 1102 } … … 1024 1152 if (rcExit == RTEXITCODE_SUCCESS) 1025 1153 { 1026 if (!SetClipboardData(pFmtDesc->fFormat, hDstData)) 1154 if (SetClipboardData(pFmtDesc->fFormat, hDstData)) 1155 { 1156 if (g_uVerbosity > 0) 1157 RTMsgInfo("Put '%s' on the clipboard: %p LB %zu\n", pFmtDesc->pszName, hDstData, cbData + cbZeroPadding); 1158 } 1159 else 1027 1160 { 1028 1161 rcExit = RTMsgErrorExitFailure("SetClipboardData(%s) failed: %u (%#x)\n", … … 1226 1359 { 1227 1360 ULONG fFmtInfo = 0; 1228 if (WinQueryClipbrdFmtInfo(g_hOs2 Hab, pFmtDesc->fFormat, &fFmtInfo))1361 if (WinQueryClipbrdFmtInfo(g_hOs2Ab, pFmtDesc->fFormat, &fFmtInfo)) 1229 1362 rcExit = RTMsgErrorExitFailure("Format '%s' is present"); 1230 1363 } … … 1259 1392 { 1260 1393 ULONG fFmtInfo = 0; 1261 if (WinEmptyClipbrd(g_hOs2 Hab))1262 { 1263 WinSetClipbrdOwner(g_hOs2 Hab, g_hOs2Wnd); /* Probably unnecessary? */1264 WinSetClipbrdOwner(g_hOs2 Hab, NULLHANDLE);1394 if (WinEmptyClipbrd(g_hOs2Ab)) 1395 { 1396 WinSetClipbrdOwner(g_hOs2Ab, g_hOs2Wnd); /* Probably unnecessary? */ 1397 WinSetClipbrdOwner(g_hOs2Ab, NULLHANDLE); 1265 1398 g_fOs2ClipboardOwner = false; 1266 1399 } 1267 1400 else 1268 rcExit = RTMsgErrorExitFailure("WinEmptyClipbrd() failed: %#x\n", WinGetLastError(g_hOs2 Hab));1401 rcExit = RTMsgErrorExitFailure("WinEmptyClipbrd() failed: %#x\n", WinGetLastError(g_hOs2Ab)); 1269 1402 } 1270 1403 return rcExit; … … 1286 1419 1287 1420 /** 1421 * Waits/delays at least @a cMsWait milliseconds. 1422 * 1423 * @returns Success indicator. 1424 * @param cMsWait Minimum wait/delay time in milliseconds. 1425 */ 1426 static RTEXITCODE DoWait(uint32_t cMsWait) 1427 { 1428 uint64_t const msStart = RTTimeMilliTS(); 1429 if (g_uVerbosity > 1) 1430 RTMsgInfo("Waiting %u ms...\n", cMsWait); 1431 1432 #if defined(RT_OS_OS2) 1433 /* 1434 * Arm a timer which will timeout after the desired period and 1435 * quit when we've dispatched it. 1436 */ 1437 g_fOs2TimerTicked = false; 1438 if (WinStartTimer(g_hOs2Ab, g_hOs2Wnd, 1 /*idEvent*/, cMsWait + 1) != 0) 1439 { 1440 QMSG Msg; 1441 while (WinGetMsg(g_hOs2Ab, &Msg, NULL, 0, 0)) 1442 { 1443 WinDispatchMsg(g_hOs2Ab, &Msg); 1444 if (g_fOs2TimerTicked || RTTimeMilliTS() - msStart >= cMsWait) 1445 break; 1446 } 1447 1448 if (!WinStopTimer(g_hOs2Ab, g_hOs2Wnd, 1 /*idEvent*/)) 1449 RTMsgWarning("WinStopTimer failed: %#x", WinGetLastError(g_hOs2Ab)); 1450 } 1451 else 1452 return RTMsgErrorExitFailure("WinStartTimer(,,,%u ms) failed: %#x", cMsWait + 1, WinGetLastError(g_hOs2Ab)); 1453 1454 #elif defined(RT_OS_WINDOWS) 1455 /* 1456 * Arm a timer which will timeout after the desired period and 1457 * quit when we've dispatched it. 1458 */ 1459 g_fWinTimerTicked = false; 1460 if (SetTimer(g_hWinWnd, 1 /*idEvent*/, cMsWait + 1, NULL /*pfnTimerProc*/) != 0) 1461 { 1462 MSG Msg; 1463 while (GetMessageW(&Msg, NULL, 0, 0)) 1464 { 1465 TranslateMessage(&Msg); 1466 DispatchMessageW(&Msg); 1467 if (g_fWinTimerTicked || RTTimeMilliTS() - msStart >= cMsWait) 1468 break; 1469 } 1470 1471 if (!KillTimer(g_hWinWnd, 1 /*idEvent*/)) 1472 RTMsgWarning("KillTimer failed: %u (%#x)", GetLastError(), GetLastError()); 1473 } 1474 else 1475 return RTMsgErrorExitFailure("SetTimer(,,%u ms,) failed: %u (%#x)", cMsWait + 1, GetLastError(), GetLastError()); 1476 1477 #else 1478 /** @todo X11 needs to run it's message queue too, because if we're offering 1479 * things on the "clipboard" we must reply to requests for them. */ 1480 /* 1481 * Just a plain simple RTThreadSleep option (will probably not be used in the end): 1482 */ 1483 for (;;) 1484 { 1485 uint64_t cMsElapsed = RTTimeMilliTS() - msStart; 1486 if (cMsElapsed >= cMsWait) 1487 break; 1488 RTThreadSleep(cMsWait - cMsElapsed); 1489 } 1490 #endif 1491 1492 if (g_uVerbosity > 2) 1493 RTMsgInfo("Done waiting after %u ms.\n", RTTimeMilliTS() - msStart); 1494 return RTEXITCODE_SUCCESS; 1495 } 1496 1497 1498 /** 1288 1499 * Display the usage to @a pStrm. 1289 1500 */ … … 1292 1503 RTStrmPrintf(pStrm, 1293 1504 "usage: %s [--get <fmt> [--get ...]] [--get-file <fmt> <file> [--get-file ...]]\n" 1294 " %s [--zap] [--put <fmt> <content> [--put ...]] [--put-file <fmt> <file> [--put-file ...]] \n"1505 " %s [--zap] [--put <fmt> <content> [--put ...]] [--put-file <fmt> <file> [--put-file ...]] [--wait <ms>]\n" 1295 1506 " %s [--check <fmt> <expected> [--check ...]] [--check-file <fmt> <file> [--check-file ...]]\n" 1296 1507 " [--check-no <fmt> [--check-no ...]]\n" 1297 1508 , RTProcShortName(), RTProcShortName(), RTProcShortName()); 1298 1509 RTStrmPrintf(pStrm, "\n"); 1299 RTStrmPrintf(pStrm, " Options:\n");1510 RTStrmPrintf(pStrm, "Actions/Options:\n"); 1300 1511 1301 1512 for (unsigned i = 0; i < RT_ELEMENTS(g_aCmdOptions); i++) … … 1316 1527 case 't': pszHelp = "Selects the target clipboard."; break; 1317 1528 #endif 1529 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 1530 case 'k': pszHelp = "Closes the clipboard if open (win,os2)."; break; 1531 #endif 1532 case 'w': pszHelp = "Waits a given number of milliseconds before continuing."; break; 1318 1533 case 'v': pszHelp = "More verbose execution."; break; 1319 1534 case 'q': pszHelp = "Quiet execution."; break; … … 1334 1549 RTStrmPrintf(pStrm, " %-19s %s\n", g_aCmdOptions[i].pszLong, pszHelp); 1335 1550 } 1336 RTStrmPrintf(pStrm, "Note! Options are processed in the order they are given.\n"); 1551 RTStrmPrintf(pStrm, 1552 "\n" 1553 "Note! Options are processed in the order they are given.\n"); 1337 1554 1338 1555 RTStrmPrintf(pStrm, "\nFormats:\n"); … … 1365 1582 RTEXITCODE rcExit = CuOs2Init(); 1366 1583 #elif defined(RT_OS_WINDOWS) 1367 RTEXITCODE rcExit = RTEXITCODE_SUCCESS;1584 RTEXITCODE rcExit = CuWinInit(); 1368 1585 #else 1369 1586 RTEXITCODE rcExit = CuX11Init(); … … 1383 1600 switch (rc) 1384 1601 { 1602 #if defined(RT_OS_OS2) || defined(RT_OS_WINDOWS) 1603 case 'k': 1604 rcExit2 = CuCloseClipboard(); 1605 break; 1606 #endif 1607 1385 1608 case 'l': 1386 1609 rcExit2 = ListClipboardContent(); … … 1511 1734 #endif 1512 1735 1736 case 'w': 1737 rcExit2 = DoWait(ValueUnion.u32); 1738 break; 1739 1513 1740 case 'q': 1514 1741 g_uVerbosity = 0;
Note:
See TracChangeset
for help on using the changeset viewer.