Example #1
0
/**************************************************************************
 *		CloseClipboard (USER32.@)
 */
BOOL WINAPI CloseClipboard(void)
{
    BOOL bRet = FALSE;

    TRACE("(%d)\n", bCBHasChanged);

    if (CLIPBOARD_CloseClipboard())
    {
        if (bCBHasChanged)
        {
            HWND hWndViewer = GetClipboardViewer();

            USER_Driver->pEndClipboardUpdate();

            if (hWndViewer)
                SendMessageW(hWndViewer, WM_DRAWCLIPBOARD, 0, 0);

            bCBHasChanged = FALSE;
        }

        bRet = TRUE;
    }

    return bRet;
}
Example #2
0
/**************************************************************************
 *              ChangeClipboardChain (USER32.@)
 */
BOOL WINAPI ChangeClipboardChain(HWND hWnd, HWND hWndNext)
{
    BOOL bRet = TRUE;
    HWND hWndViewer = GetClipboardViewer();

    if (hWndViewer)
    {
        if (WIN_GetFullHandle(hWnd) == hWndViewer)
            SetClipboardViewer(WIN_GetFullHandle(hWndNext));
        else
            bRet = !SendMessageW(hWndViewer, WM_CHANGECBCHAIN, (WPARAM)hWnd, (LPARAM)hWndNext);
    }
    else
        ERR("hWndViewer is lost\n");

    return bRet;
}
static PyObject *
py_get_clipboard_viewer(PyObject* self, PyObject* args)
{

  CHECK_NO_ARGS2(args, "GetClipboardViewer");

  HWND rc;
  Py_BEGIN_ALLOW_THREADS;
  rc = GetClipboardViewer();
  Py_END_ALLOW_THREADS;

  if (!rc)
    return ReturnAPIError("GetClipboardViewer");
  return PyWinLong_FromHANDLE(rc);

  // @pyseeapi GetClipboardViewer

  // @rdesc If the function succeeds, the return value is the handle of the
  // first window in the clipboard viewer chain. 
  // If the function fails, win32api.error is raised with the GetLastError
  // info.

}
Example #4
0
/* This is the fastpoll function which gathers up info by calling various api's */
BOOL FastPoll (void)
{
	int nOriginalRandIndex = nRandIndex;
	static BOOL addedFixedItems = FALSE;
	FILETIME creationTime, exitTime, kernelTime, userTime;
	SIZE_T minimumWorkingSetSize, maximumWorkingSetSize;
	LARGE_INTEGER performanceCount;
	MEMORYSTATUS memoryStatus;
	HANDLE handle;
	POINT point;

	/* Get various basic pieces of system information */
	RandaddIntPtr (GetActiveWindow ());	/* Handle of active window */
	RandaddIntPtr (GetCapture ());	/* Handle of window with mouse
					   capture */
	RandaddIntPtr (GetClipboardOwner ());	/* Handle of clipboard owner */
	RandaddIntPtr (GetClipboardViewer ());	/* Handle of start of
						   clpbd.viewer list */
	RandaddIntPtr (GetCurrentProcess ());	/* Pseudohandle of current
						   process */
	RandaddInt32 (GetCurrentProcessId ());	/* Current process ID */
	RandaddIntPtr (GetCurrentThread ());	/* Pseudohandle of current
						   thread */
	RandaddInt32 (GetCurrentThreadId ());	/* Current thread ID */
	RandaddInt32 (GetCurrentTime ());	/* Milliseconds since Windows
						   started */
	RandaddIntPtr (GetDesktopWindow ());	/* Handle of desktop window */
	RandaddIntPtr (GetFocus ());	/* Handle of window with kb.focus */
	RandaddInt32 (GetInputState ());	/* Whether sys.queue has any events */
	RandaddInt32 (GetMessagePos ());	/* Cursor pos.for last message */
	RandaddInt32 (GetMessageTime ());	/* 1 ms time for last message */
	RandaddIntPtr (GetOpenClipboardWindow ());	/* Handle of window with
							   clpbd.open */
	RandaddIntPtr (GetProcessHeap ());	/* Handle of process heap */
	RandaddIntPtr (GetProcessWindowStation ());	/* Handle of procs
							   window station */
	RandaddInt32 (GetQueueStatus (QS_ALLEVENTS));	/* Types of events in
							   input queue */

	/* Get multiword system information */
	GetCaretPos (&point);	/* Current caret position */
	RandaddBuf ((unsigned char *) &point, sizeof (POINT));
	GetCursorPos (&point);	/* Current mouse cursor position */
	RandaddBuf ((unsigned char *) &point, sizeof (POINT));

	/* Get percent of memory in use, bytes of physical memory, bytes of
	   free physical memory, bytes in paging file, free bytes in paging
	   file, user bytes of address space, and free user bytes */
	memoryStatus.dwLength = sizeof (MEMORYSTATUS);
	GlobalMemoryStatus (&memoryStatus);
	RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS));

	/* Get thread and process creation time, exit time, time in kernel
	   mode, and time in user mode in 100ns intervals */
	handle = GetCurrentThread ();
	GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
	RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
	RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
	RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
	RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));
	handle = GetCurrentProcess ();
	GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime);
	RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME));
	RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME));
	RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME));
	RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME));

	/* Get the minimum and maximum working set size for the current
	   process */
	GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
				  &maximumWorkingSetSize);
	RandaddIntPtr (minimumWorkingSetSize);
	RandaddIntPtr (maximumWorkingSetSize);

	/* The following are fixed for the lifetime of the process so we only
	   add them once */
	if (addedFixedItems == 0)
	{
		STARTUPINFO startupInfo;

		/* Get name of desktop, console window title, new window
		   position and size, window flags, and handles for stdin,
		   stdout, and stderr */
		startupInfo.cb = sizeof (STARTUPINFO);
		GetStartupInfo (&startupInfo);
		RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO));
		addedFixedItems = TRUE;
	}
	/* The docs say QPC can fail if appropriate hardware is not
	   available. It works on 486 & Pentium boxes, but hasn't been tested
	   for 386 or RISC boxes */
	if (QueryPerformanceCounter (&performanceCount))
		RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER));
	else
	{
		/* Millisecond accuracy at best... */
		DWORD dwTicks = GetTickCount ();
		RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks));
	}

	// CryptoAPI: We always have a valid CryptoAPI context when we arrive here but
	//            we keep the check for clarity purpose
	if ( !CryptoAPIAvailable )
		return FALSE;
	if (CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) 
	{
		RandaddBuf (buffer, sizeof (buffer));
		burn (buffer, sizeof(buffer));
	}
	else
	{
		/* return error in case CryptGenRandom fails */
		CryptoAPILastError = GetLastError ();
		return FALSE;
	}

	/* Apply the pool mixing function */
	Randmix();

	/* Restore the original pool cursor position. If this wasn't done, mouse coordinates
	   could be written to a limited area of the pool, especially when moving the mouse
	   uninterruptedly. The severity of the problem would depend on the length of data
	   written by FastPoll (if it was equal to the size of the pool, mouse coordinates
	   would be written only to a particular 4-byte area, whenever moving the mouse
	   uninterruptedly). */
	nRandIndex = nOriginalRandIndex;

	return TRUE;
}
Example #5
0
static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    AssertPtr(pCtx);

    LRESULT rc = 0;

    switch (msg)
    {
        case WM_CLIPBOARDUPDATE:
        {
            Log(("WM_CLIPBOARDUPDATE\n"));

            if (GetClipboardOwner() != hwnd)
            {
                /* Clipboard was updated by another application. */
                vboxClipboardChanged(pCtx);
            }
        } break;

        case WM_CHANGECBCHAIN:
        {
            if (vboxClipboardIsNewAPI(pCtx))
            {
                rc = DefWindowProc(hwnd, msg, wParam, lParam);
                break;
            }

            HWND hwndRemoved = (HWND)wParam;
            HWND hwndNext    = (HWND)lParam;

            LogFlowFunc(("WM_CHANGECBCHAIN: hwndRemoved %p, hwndNext %p, hwnd %p\n", hwndRemoved, hwndNext, pCtx->hwnd));

            if (hwndRemoved == pCtx->hwndNextInChain)
            {
                /* The window that was next to our in the chain is being removed.
                 * Relink to the new next window. */
                pCtx->hwndNextInChain = hwndNext;
            }
            else
            {
                if (pCtx->hwndNextInChain)
                {
                    /* Pass the message further. */
                    DWORD_PTR dwResult;
                    rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
                    if (!rc)
                        rc = (LRESULT) dwResult;
                }
            }
        } break;

        case WM_DRAWCLIPBOARD:
        {
            LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pCtx->hwnd));

            if (GetClipboardOwner() != hwnd)
            {
                /* Clipboard was updated by another application. */
                /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
                int vboxrc = vboxClipboardChanged(pCtx);
                if (RT_FAILURE(vboxrc))
                    LogFlowFunc(("vboxClipboardChanged failed, rc = %Rrc\n", vboxrc));
            }

            if (pCtx->hwndNextInChain)
            {
                /* Pass the message to next windows in the clipboard chain. */
                SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, NULL);
            }
        } break;

        case WM_TIMER:
        {
            if (vboxClipboardIsNewAPI(pCtx))
                break;

            HWND hViewer = GetClipboardViewer();

            /* Re-register ourselves in the clipboard chain if our last ping
             * timed out or there seems to be no valid chain. */
            if (!hViewer || pCtx->fCBChainPingInProcess)
            {
                vboxClipboardRemoveFromCBChain(pCtx);
                vboxClipboardAddToCBChain(pCtx);
            }
            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
             * processed by ourselves to the chain. */
            pCtx->fCBChainPingInProcess = TRUE;
            hViewer = GetClipboardViewer();
            if (hViewer)
                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, vboxClipboardChainPingProc, (ULONG_PTR)pCtx);
        } break;

        case WM_CLOSE:
        {
            /* Do nothing. Ignore the message. */
        } break;

        case WM_RENDERFORMAT:
        {
            /* Insert the requested clipboard format data into the clipboard. */
            uint32_t u32Format = 0;
            UINT format = (UINT)wParam;

            LogFlowFunc(("WM_RENDERFORMAT, format = %x\n", format));
            switch (format)
            {
                case CF_UNICODETEXT:
                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
                    break;

                case CF_DIB:
                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
                    break;

                default:
                    if (format >= 0xC000)
                    {
                        TCHAR szFormatName[256];

                        int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));
                        if (cActual)
                        {
                            if (strcmp (szFormatName, "HTML Format") == 0)
                            {
                                u32Format |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
                            }
                        }
                    }
                    break;
            }

            if (u32Format == 0)
            {
                /* Unsupported clipboard format is requested. */
                LogFlowFunc(("Unsupported clipboard format requested: %ld\n", u32Format));
                EmptyClipboard();
            }
            else
            {
                const uint32_t cbPrealloc = 4096; /** @todo r=andy Make it dynamic for supporting larger text buffers! */
                uint32_t cb = 0;

                /* Preallocate a buffer, most of small text transfers will fit into it. */
                HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
                LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));

                if (hMem)
                {
                    void *pMem = GlobalLock(hMem);
                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));

                    if (pMem)
                    {
                        /* Read the host data to the preallocated buffer. */
                        int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cbPrealloc, &cb);
                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));

                        if (RT_SUCCESS(vboxrc))
                        {
                            if (cb == 0)
                            {
                                /* 0 bytes returned means the clipboard is empty.
                                 * Deallocate the memory and set hMem to NULL to get to
                                 * the clipboard empty code path. */
                                GlobalUnlock(hMem);
                                GlobalFree(hMem);
                                hMem = NULL;
                            }
                            else if (cb > cbPrealloc)
                            {
                                GlobalUnlock(hMem);

                                /* The preallocated buffer is too small, adjust the size. */
                                hMem = GlobalReAlloc(hMem, cb, 0);
                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));

                                if (hMem)
                                {
                                    pMem = GlobalLock(hMem);
                                    LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));

                                    if (pMem)
                                    {
                                        /* Read the host data to the preallocated buffer. */
                                        uint32_t cbNew = 0;
                                        vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, u32Format, pMem, cb, &cbNew);
                                        LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));

                                        if (RT_SUCCESS (vboxrc) && cbNew <= cb)
                                        {
                                            cb = cbNew;
                                        }
                                        else
                                        {
                                            GlobalUnlock(hMem);
                                            GlobalFree(hMem);
                                            hMem = NULL;
                                        }
                                    }
                                    else
                                    {
                                        GlobalFree(hMem);
                                        hMem = NULL;
                                    }
                                }
                            }

                            if (hMem)
                            {
                                /* pMem is the address of the data. cb is the size of returned data. */
                                /* Verify the size of returned text, the memory block for clipboard
                                 * must have the exact string size.
                                 */
                                if (u32Format == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                                {
                                    size_t cbActual = 0;
                                    HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
                                    if (FAILED (hrc))
                                    {
                                        /* Discard invalid data. */
                                        GlobalUnlock(hMem);
                                        GlobalFree(hMem);
                                        hMem = NULL;
                                    }
                                    else
                                    {
                                        /* cbActual is the number of bytes, excluding those used
                                         * for the terminating null character.
                                         */
                                        cb = (uint32_t)(cbActual + 2);
                                    }
                                }
                            }

                            if (hMem)
                            {
                                GlobalUnlock(hMem);

                                hMem = GlobalReAlloc(hMem, cb, 0);
                                LogFlowFunc(("Reallocated hMem = %p\n", hMem));

                                if (hMem)
                                {
                                    /* 'hMem' contains the host clipboard data.
                                     * size is 'cb' and format is 'format'. */
                                    HANDLE hClip = SetClipboardData(format, hMem);
                                    LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));

                                    if (hClip)
                                    {
                                        /* The hMem ownership has gone to the system. Finish the processing. */
                                        break;
                                    }

                                    /* Cleanup follows. */
                                }
                            }
                        }
                        if (hMem)
                            GlobalUnlock(hMem);
                    }
                    if (hMem)
                        GlobalFree(hMem);
                }

                /* Something went wrong. */
                EmptyClipboard();
            }
        } break;

        case WM_RENDERALLFORMATS:
        {
            /* Do nothing. The clipboard formats will be unavailable now, because the
             * windows is to be destroyed and therefore the guest side becomes inactive.
             */
            int vboxrc = vboxOpenClipboard(hwnd);
            if (RT_SUCCESS(vboxrc))
            {
                EmptyClipboard();
                CloseClipboard();
            }
            else
            {
                LogFlowFunc(("WM_RENDERALLFORMATS: Failed to open clipboard! rc: %Rrc\n", vboxrc));
            }
        } break;

        case WM_USER:
        {
            /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
            uint32_t u32Formats = (uint32_t)lParam;

            int vboxrc = vboxOpenClipboard(hwnd);
            if (RT_SUCCESS(vboxrc))
            {
                EmptyClipboard();

                HANDLE hClip = NULL;

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                {
                    LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));
                    hClip = SetClipboardData(CF_UNICODETEXT, NULL);
                }

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
                    LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));
                    hClip = SetClipboardData(CF_DIB, NULL);
                }

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
                {
                    UINT format = RegisterClipboardFormat ("HTML Format");
                    LogFlowFunc(("WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
                    if (format != 0)
                    {
                        hClip = SetClipboardData(format, NULL);
                    }
                }

                CloseClipboard();
                LogFlowFunc(("WM_USER: hClip = %p, err = %ld\n", hClip, GetLastError ()));
            }
            else
            {
                LogFlowFunc(("WM_USER: Failed to open clipboard! error = %Rrc\n", vboxrc));
            }
        } break;

        case WM_USER + 1:
        {
            /* Send data in the specified format to the host. */
            uint32_t u32Formats = (uint32_t)lParam;
            HANDLE hClip = NULL;

            int vboxrc = vboxOpenClipboard(hwnd);
            if (RT_SUCCESS(vboxrc))
            {
                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
                    hClip = GetClipboardData(CF_DIB);

                    if (hClip != NULL)
                    {
                        LPVOID lp = GlobalLock(hClip);
                        if (lp != NULL)
                        {
                            LogFlowFunc(("WM_USER + 1: CF_DIB\n"));
                            vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
                                                              lp, GlobalSize(hClip));
                            GlobalUnlock(hClip);
                        }
                        else
                        {
                            hClip = NULL;
                        }
                    }
                }
                else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                {
                    hClip = GetClipboardData(CF_UNICODETEXT);

                    if (hClip != NULL)
                    {
                        LPWSTR uniString = (LPWSTR)GlobalLock(hClip);

                        if (uniString != NULL)
                        {
                            LogFlowFunc(("WM_USER + 1: CF_UNICODETEXT\n"));
                            vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
                                                              uniString, (lstrlenW(uniString) + 1) * 2);
                            GlobalUnlock(hClip);
                        }
                        else
                        {
                            hClip = NULL;
                        }
                    }
                }
                else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
                {
                    UINT format = RegisterClipboardFormat ("HTML Format");
                    if (format != 0)
                    {
                        hClip = GetClipboardData(format);
                        if (hClip != NULL)
                        {
                            LPVOID lp = GlobalLock(hClip);

                            if (lp != NULL)
                            {
                                LogFlowFunc(("WM_USER + 1: CF_HTML\n"));
                                vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
                                                                  lp, GlobalSize(hClip));
                                GlobalUnlock(hClip);
                            }
                            else
                            {
                                hClip = NULL;
                            }
                        }
                    }
                }

                CloseClipboard();
            }
            else
            {
                LogFlowFunc(("WM_USER: Failed to open clipboard! rc: %Rrc\n", vboxrc));
            }

            if (hClip == NULL)
            {
                /* Requested clipboard format is not available, send empty data. */
                VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
            }
        } break;

        case WM_DESTROY:
        {
            vboxClipboardRemoveFromCBChain(pCtx);
            if (pCtx->timerRefresh)
                KillTimer(pCtx->hwnd, 0);
            /*
             * don't need to call PostQuitMessage cause
             * the VBoxTray already finished a message loop
             */
        } break;

        default:
        {
            rc = DefWindowProc(hwnd, msg, wParam, lParam);
        }
    }

#ifndef DEBUG_andy
    LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
#endif
    return rc;
}
Example #6
0
LRESULT CALLBACK
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND s_hwndNextViewer;
    static Bool s_fCBCInitialized;

    /* Branch on message type */
    switch (message) {
    case WM_DESTROY:
    {
        winDebug("winClipboardWindowProc - WM_DESTROY\n");

        /* Remove ourselves from the clipboard chain */
        ChangeClipboardChain(hwnd, s_hwndNextViewer);

        s_hwndNextViewer = NULL;

        PostQuitMessage(0);
    }
        return 0;

    case WM_CREATE:
    {
        HWND first, next;
        DWORD error_code = 0;

        winDebug("winClipboardWindowProc - WM_CREATE\n");

        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
        if (first == hwnd)
            return 0;           /* Make sure it's not us! */
        /* Add ourselves to the clipboard viewer chain */
        next = SetClipboardViewer(hwnd);
        error_code = GetLastError();
        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
        else
            s_fCBCInitialized = FALSE;
    }
        return 0;

    case WM_CHANGECBCHAIN:
    {
        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%x) "
                 "lParam(%x) s_hwndNextViewer(%x)\n",
                 wParam, lParam, s_hwndNextViewer);

        if ((HWND) wParam == s_hwndNextViewer) {
            s_hwndNextViewer = (HWND) lParam;
            if (s_hwndNextViewer == hwnd) {
                s_hwndNextViewer = NULL;
                winErrorFVerb(1, "winClipboardWindowProc - WM_CHANGECBCHAIN: "
                              "attempted to set next window to ourselves.");
            }
        }
        else if (s_hwndNextViewer)
            SendMessage(s_hwndNextViewer, message, wParam, lParam);

    }
        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
        return 0;

    case WM_WM_REINIT:
    {
        /* Ensure that we're in the clipboard chain.  Some apps,
         * WinXP's remote desktop for one, don't play nice with the
         * chain.  This message is called whenever we receive a
         * WM_ACTIVATEAPP message to ensure that we continue to
         * receive clipboard messages.
         *
         * It might be possible to detect if we're still in the chain
         * by calling SendMessage (GetClipboardViewer(),
         * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
         * WM_DRAWCLIPBOARD message.  That, however, might be more
         * expensive than just putting ourselves back into the chain.
         */

        HWND first, next;
        DWORD error_code = 0;

        winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");

        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
        if (first == hwnd)
            return 0;           /* Make sure it's not us! */
        winDebug("  WM_WM_REINIT: Replacing us(%x) with %x at head "
                 "of chain\n", hwnd, s_hwndNextViewer);
        s_fCBCInitialized = FALSE;
        ChangeClipboardChain(hwnd, s_hwndNextViewer);
        s_hwndNextViewer = NULL;
        s_fCBCInitialized = FALSE;
        winDebug("  WM_WM_REINIT: Putting us back at head of chain.\n");
        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
        if (first == hwnd)
            return 0;           /* Make sure it's not us! */
        next = SetClipboardViewer(hwnd);
        error_code = GetLastError();
        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
        else
            s_fCBCInitialized = FALSE;
    }
        winDebug("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
        return 0;

    case WM_DRAWCLIPBOARD:
    {
        static Atom atomClipboard;
        static int generation;
        static Bool s_fProcessingDrawClipboard = FALSE;
        Display *pDisplay = g_pClipboardDisplay;
        Window iWindow = g_iClipboardWindow;
        int iReturn;

        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");

        if (generation != serverGeneration) {
            generation = serverGeneration;
            atomClipboard = XInternAtom(pDisplay, "CLIPBOARD", False);
        }

        /*
         * We've occasionally seen a loop in the clipboard chain.
         * Try and fix it on the first hint of recursion.
         */
        if (!s_fProcessingDrawClipboard) {
            s_fProcessingDrawClipboard = TRUE;
        }
        else {
            /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
            s_fCBCInitialized = FALSE;
            ChangeClipboardChain(hwnd, s_hwndNextViewer);
            winFixClipboardChain();
            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                          "Nested calls detected.  Re-initing.\n");
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
            s_fProcessingDrawClipboard = FALSE;
            return 0;
        }

        /* Bail on first message */
        if (!s_fCBCInitialized) {
            s_fCBCInitialized = TRUE;
            s_fProcessingDrawClipboard = FALSE;
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
            return 0;
        }

        /*
         * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
         * because some applications deal with the clipboard in a manner
         * that causes the clipboard owner to be NULL when they are in
         * fact taking ownership.  One example of this is the Win32
         * native compile of emacs.
         */

        /* Bail when we still own the clipboard */
        if (hwnd == GetClipboardOwner()) {

            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "We own the clipboard, returning.\n");
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
            s_fProcessingDrawClipboard = FALSE;
            if (s_hwndNextViewer)
                SendMessage(s_hwndNextViewer, message, wParam, lParam);
            return 0;
        }

        /*
         * Do not take ownership of the X11 selections when something
         * other than CF_TEXT or CF_UNICODETEXT has been copied
         * into the Win32 clipboard.
         */
        if (!IsClipboardFormatAvailable(CF_TEXT)
            && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {

            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "Clipboard does not contain CF_TEXT nor "
                     "CF_UNICODETEXT.\n");

            /*
             * We need to make sure that the X Server has processed
             * previous XSetSelectionOwner messages.
             */
            XSync(pDisplay, FALSE);

            winDebug("winClipboardWindowProc - XSync done.\n");

            /* Release PRIMARY selection if owned */
            iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
            if (iReturn == g_iClipboardWindow) {
                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                         "PRIMARY selection is owned by us.\n");
                XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
            }
            else if (BadWindow == iReturn || BadAtom == iReturn)
                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                              "XGetSelection failed for PRIMARY: %d\n",
                              iReturn);

            /* Release CLIPBOARD selection if owned */
            iReturn = XGetSelectionOwner(pDisplay, atomClipboard);
            if (iReturn == g_iClipboardWindow) {
                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                         "CLIPBOARD selection is owned by us.\n");
                XSetSelectionOwner(pDisplay, atomClipboard, None, CurrentTime);
            }
            else if (BadWindow == iReturn || BadAtom == iReturn)
                winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                              "XGetSelection failed for CLIPBOARD: %d\n",
                              iReturn);

            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
            s_fProcessingDrawClipboard = FALSE;
            if (s_hwndNextViewer)
                SendMessage(s_hwndNextViewer, message, wParam, lParam);
            return 0;
        }

        /* Reassert ownership of PRIMARY */
        iReturn = XSetSelectionOwner(pDisplay,
                                     XA_PRIMARY, iWindow, CurrentTime);
        if (iReturn == BadAtom || iReturn == BadWindow ||
            XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                          "Could not reassert ownership of PRIMARY\n");
        }
        else {
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "Reasserted ownership of PRIMARY\n");
        }

        /* Reassert ownership of the CLIPBOARD */
        iReturn = XSetSelectionOwner(pDisplay,
                                     atomClipboard, iWindow, CurrentTime);

        if (iReturn == BadAtom || iReturn == BadWindow ||
            XGetSelectionOwner(pDisplay, atomClipboard) != iWindow) {
            winErrorFVerb(1, "winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                          "Could not reassert ownership of CLIPBOARD\n");
        }
        else {
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "Reasserted ownership of CLIPBOARD\n");
        }

        /* Flush the pending SetSelectionOwner event now */
        XFlush(pDisplay);

        s_fProcessingDrawClipboard = FALSE;
    }
        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
        /* Pass the message on the next window in the clipboard viewer chain */
        if (s_hwndNextViewer)
            SendMessage(s_hwndNextViewer, message, wParam, lParam);
        return 0;

    case WM_DESTROYCLIPBOARD:
        /*
         * NOTE: Intentionally do nothing.
         * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
         * above.  We only process this message to conform to the specs
         * for delayed clipboard rendering in Win32.  You might think
         * that we need to release ownership of the X11 selections, but
         * we do not, because a WM_DRAWCLIPBOARD message will closely
         * follow this message and reassert ownership of the X11
         * selections, handling the issue for us.
         */
        winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
        return 0;

    case WM_RENDERFORMAT:
    case WM_RENDERALLFORMATS:
    {
        int iReturn;
        Display *pDisplay = g_pClipboardDisplay;
        Window iWindow = g_iClipboardWindow;
        Bool fConvertToUnicode;

        winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Hello.\n");

        /* Flag whether to convert to Unicode or not */
        if (message == WM_RENDERALLFORMATS)
            fConvertToUnicode = FALSE;
        else
            fConvertToUnicode = g_fUnicodeSupport && (CF_UNICODETEXT == wParam);

        /* Request the selection contents */
        iReturn = XConvertSelection(pDisplay,
                                    g_atomLastOwnedSelection,
                                    XInternAtom(pDisplay,
                                                "COMPOUND_TEXT", False),
                                    XInternAtom(pDisplay,
                                                "CYGX_CUT_BUFFER", False),
                                    iWindow, CurrentTime);
        if (iReturn == BadAtom || iReturn == BadWindow) {
            winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMAT - "
                          "XConvertSelection () failed\n");
            break;
        }

        /* Special handling for WM_RENDERALLFORMATS */
        if (message == WM_RENDERALLFORMATS) {
            /* We must open and empty the clipboard */

            /* Close clipboard if we have it open already */
            if (GetOpenClipboardWindow() == hwnd) {
                CloseClipboard();
            }

            if (!OpenClipboard(hwnd)) {
                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
                              "OpenClipboard () failed: %08x\n",
                              GetLastError());
                break;
            }

            if (!EmptyClipboard()) {
                winErrorFVerb(1, "winClipboardWindowProc - WM_RENDER*FORMATS - "
                              "EmptyClipboard () failed: %08x\n",
                              GetLastError());
                break;
            }
        }

        /* Process the SelectionNotify event */
        iReturn = winProcessXEventsTimeout(hwnd,
                                           iWindow,
                                           pDisplay,
                                           fConvertToUnicode, WIN_POLL_TIMEOUT);

        /*
         * The last call to winProcessXEventsTimeout
         * from above had better have seen a notify event, or else we
         * are dealing with a buggy or old X11 app.  In these cases we
         * have to paste some fake data to the Win32 clipboard to
         * satisfy the requirement that we write something to it.
         */
        if (WIN_XEVENTS_NOTIFY != iReturn) {
            /* Paste no data, to satisfy required call to SetClipboardData */
            if (g_fUnicodeSupport)
                SetClipboardData(CF_UNICODETEXT, NULL);
            SetClipboardData(CF_TEXT, NULL);

            ErrorF
                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY\n");
        }

        /* Special handling for WM_RENDERALLFORMATS */
        if (message == WM_RENDERALLFORMATS) {
            /* We must close the clipboard */

            if (!CloseClipboard()) {
                winErrorFVerb(1,
                              "winClipboardWindowProc - WM_RENDERALLFORMATS - "
                              "CloseClipboard () failed: %08x\n",
                              GetLastError());
                break;
            }
        }

        winDebug("winClipboardWindowProc - WM_RENDER*FORMAT - Returning.\n");
        return 0;
    }
    }

    /* Let Windows perform default processing for unhandled messages */
    return DefWindowProc(hwnd, message, wParam, lParam);
}
Example #7
0
int
_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, int),
                                 int requester )
{
    static int addedFixedItems = 0;

    if ( debug_me )
	log_debug ("rndw32#gather_random_fast: req=%d\n", requester );

    /* Get various basic pieces of system information: Handle of active
     * window, handle of window with mouse capture, handle of clipboard owner
     * handle of start of clpboard viewer list, pseudohandle of current
     * process, current process ID, pseudohandle of current thread, current
     * thread ID, handle of desktop window, handle  of window with keyboard
     * focus, whether system queue has any events, cursor position for last
     * message, 1 ms time for last message, handle of window with clipboard
     * open, handle of process heap, handle of procs window station, types of
     * events in input queue, and milliseconds since Windows was started */
    {	byte buffer[20*sizeof(ulong)], *bufptr;
	bufptr = buffer;
#define ADD(f)  do { ulong along = (ulong)(f);		      \
			   memcpy (bufptr, &along, sizeof (along) );  \
			   bufptr += sizeof (along); } while (0)
	ADD ( GetActiveWindow ());
	ADD ( GetCapture ());
	ADD ( GetClipboardOwner ());
	ADD ( GetClipboardViewer ());
	ADD ( GetCurrentProcess ());
	ADD ( GetCurrentProcessId ());
	ADD ( GetCurrentThread ());
	ADD ( GetCurrentThreadId ());
	ADD ( GetDesktopWindow ());
	ADD ( GetFocus ());
	ADD ( GetInputState ());
	ADD ( GetMessagePos ());
	ADD ( GetMessageTime ());
	ADD ( GetOpenClipboardWindow ());
	ADD ( GetProcessHeap ());
	ADD ( GetProcessWindowStation ());
	ADD ( GetQueueStatus (QS_ALLEVENTS));
	ADD ( GetTickCount ());

	assert ( bufptr-buffer < sizeof (buffer) );
	(*add) ( buffer, bufptr-buffer, requester );
#undef ADD
    }

    /* Get multiword system information: Current caret position, current
     * mouse cursor position */
    {	POINT point;
	GetCaretPos (&point);
	(*add) ( &point, sizeof (point), requester );
	GetCursorPos (&point);
	(*add) ( &point, sizeof (point), requester );
    }

    /* Get percent of memory in use, bytes of physical memory, bytes of free
     * physical memory, bytes in paging file, free bytes in paging file, user
     * bytes of address space, and free user bytes */
    {	MEMORYSTATUS memoryStatus;
	memoryStatus.dwLength = sizeof (MEMORYSTATUS);
	GlobalMemoryStatus (&memoryStatus);
	(*add) ( &memoryStatus, sizeof (memoryStatus), requester );
    }

    /* Get thread and process creation time, exit time, time in kernel mode,
       and time in user mode in 100ns intervals */
    {	HANDLE handle;
	FILETIME creationTime, exitTime, kernelTime, userTime;
	DWORD minimumWorkingSetSize, maximumWorkingSetSize;

	handle = GetCurrentThread ();
	GetThreadTimes (handle, &creationTime, &exitTime,
					       &kernelTime, &userTime);
	(*add) ( &creationTime, sizeof (creationTime), requester );
	(*add) ( &exitTime, sizeof (exitTime), requester );
	(*add) ( &kernelTime, sizeof (kernelTime), requester );
	(*add) ( &userTime, sizeof (userTime), requester );

	handle = GetCurrentProcess ();
	GetProcessTimes (handle, &creationTime, &exitTime,
						&kernelTime, &userTime);
	(*add) ( &creationTime, sizeof (creationTime), requester );
	(*add) ( &exitTime, sizeof (exitTime), requester );
	(*add) ( &kernelTime, sizeof (kernelTime), requester );
	(*add) ( &userTime, sizeof (userTime), requester );

	/* Get the minimum and maximum working set size for the
           current process */
	GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
					  &maximumWorkingSetSize);
	(*add) ( &minimumWorkingSetSize,
				   sizeof (minimumWorkingSetSize), requester );
	(*add) ( &maximumWorkingSetSize,
				   sizeof (maximumWorkingSetSize), requester );
    }


    /* The following are fixed for the lifetime of the process so we only
     * add them once */
    if (!addedFixedItems) {
	STARTUPINFO startupInfo;

	/* Get name of desktop, console window title, new window position and
	 * size, window flags, and handles for stdin, stdout, and stderr */
	startupInfo.cb = sizeof (STARTUPINFO);
	GetStartupInfo (&startupInfo);
	(*add) ( &startupInfo, sizeof (STARTUPINFO), requester );
	addedFixedItems = 1;
    }

    /* The performance of QPC varies depending on the architecture it's
     * running on and on the OS.  Under NT it reads the CPU's 64-bit timestamp
     * counter (at least on a Pentium and newer '486's, it hasn't been tested
     * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC
     * timer.  There are vague mumblings in the docs that it may fail if the
     * appropriate hardware isn't available (possibly '386's or MIPS machines
     * running NT), but who's going to run NT on a '386? */
    {	LARGE_INTEGER performanceCount;
	if (QueryPerformanceCounter (&performanceCount)) {
	    if ( debug_me )
		log_debug ("rndw32#gather_random_fast: perf data\n");
	    (*add) (&performanceCount, sizeof (performanceCount), requester);
	}
	else { /* Millisecond accuracy at best... */
	    DWORD aword = GetTickCount ();
	    (*add) (&aword, sizeof (aword), requester );
	}
    }

    return 0;
}
Example #8
0
void CNewRandom::Initialize()
{
	++g_dwNewRandomInstanceCounter;

	DWORD dw;
	dw = timeGetTime();
	AddRandomObject(&dw, 4);

	LARGE_INTEGER li;
	QueryPerformanceCounter(&li);
	AddRandomObject(&li, sizeof(LARGE_INTEGER));

	SYSTEMTIME st;
	ZeroMemory(&st, sizeof(SYSTEMTIME));
	GetLocalTime(&st);
	AddRandomObject(&st, sizeof(SYSTEMTIME));

	POINT pt;
	GetCursorPos(&pt);
	AddRandomObject(&pt, sizeof(POINT));

	WORD ww;
	ww = (WORD)(rand());
	AddRandomObject(&ww, 2);
	ww = (WORD)(rand());
	AddRandomObject(&ww, 2);
	ww = (WORD)(rand());
	AddRandomObject(&ww, 2);

	GetCaretPos(&pt);
	AddRandomObject(&pt, sizeof(POINT));

	MEMORYSTATUS ms;
	GlobalMemoryStatus(&ms);
	AddRandomObject(&ms, sizeof(MEMORYSTATUS));

	dw = (DWORD)(UINT_PTR)GetActiveWindow();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetCapture();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetClipboardOwner();
	AddRandomObject(&dw, 4);

#ifndef _WIN32_WCE
	// No support under Windows CE
	dw = (DWORD)(UINT_PTR)GetClipboardViewer();
	AddRandomObject(&dw, 4);
#endif

	dw = GetCurrentProcessId();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetCurrentProcess();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetActiveWindow();
	AddRandomObject(&dw, 4);

	dw = GetCurrentThreadId();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetCurrentThread();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetDesktopWindow();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetFocus();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetForegroundWindow();
	AddRandomObject(&dw, 4);

#ifndef _WIN32_WCE
	dw = (DWORD)GetInputState();
	AddRandomObject(&dw, 4); 
#endif

	dw = GetMessagePos();
	AddRandomObject(&dw, 4);

#ifndef _WIN32_WCE
	dw = (DWORD)GetMessageTime();
	AddRandomObject(&dw, 4);
#endif

	dw = (DWORD)(UINT_PTR)GetOpenClipboardWindow();
	AddRandomObject(&dw, 4);

	dw = (DWORD)(UINT_PTR)GetProcessHeap();
	AddRandomObject(&dw, 4);

	SYSTEM_INFO si;
	GetSystemInfo(&si);
	AddRandomObject(&si, sizeof(SYSTEM_INFO));

	dw = (DWORD)randXorShift();
	AddRandomObject(&dw, 4);

#ifndef _WIN32_WCE
	STARTUPINFO sui;
	GetStartupInfo(&sui);
	AddRandomObject(&sui, sizeof(STARTUPINFO));
#endif

	GUID guid;
	VERIFY(CoCreateGuid(&guid) == S_OK);
	AddRandomObject(&guid, sizeof(GUID));

	BYTE pbCrypt[64];
	CNewRandom::SysCryptGetRandom(&pbCrypt[0], 64);
	AddRandomObject(&pbCrypt[0], 64);

	AddRandomObject(&g_dwNewRandomInstanceCounter, 4);
}
static LRESULT vboxClipboardProcessMsg(PVBOXCLIPBOARDCONTEXT pCtx, HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    AssertPtr(pCtx);

    const PVBOXCLIPBOARDWINCTX pWinCtx = &pCtx->Win;

    LRESULT rc = 0;

    switch (msg)
    {
        case WM_CLIPBOARDUPDATE:
        {
           Log(("WM_CLIPBOARDUPDATE\n"));

           if (GetClipboardOwner() != hwnd)
           {
               /* Clipboard was updated by another application. */
               uint32_t uFormats;
               int vboxrc = VBoxClipboardWinGetFormats(&pCtx->Win, &uFormats);
               if (RT_SUCCESS(vboxrc))
                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
           }
        }
        break;

        case WM_CHANGECBCHAIN:
        {
           if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
           {
               rc = DefWindowProc(hwnd, msg, wParam, lParam);
               break;
           }

           HWND hWndRemoved = (HWND)wParam;
           HWND hWndNext    = (HWND)lParam;

           LogFlowFunc(("WM_CHANGECBCHAIN: hWndRemoved=%p, hWndNext=%p, hWnd=%p\n", hWndRemoved, hWndNext, pWinCtx->hWnd));

           if (hWndRemoved == pWinCtx->hWndNextInChain)
           {
               /* The window that was next to our in the chain is being removed.
                * Relink to the new next window. */
               pWinCtx->hWndNextInChain = hWndNext;
           }
           else
           {
               if (pWinCtx->hWndNextInChain)
               {
                   /* Pass the message further. */
                   DWORD_PTR dwResult;
                   rc = SendMessageTimeout(pWinCtx->hWndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0,
                                           VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, &dwResult);
                   if (!rc)
                       rc = (LRESULT)dwResult;
               }
           }
        }
        break;

        case WM_DRAWCLIPBOARD:
        {
           LogFlowFunc(("WM_DRAWCLIPBOARD, hwnd %p\n", pWinCtx->hWnd));

           if (GetClipboardOwner() != hwnd)
           {
               /* Clipboard was updated by another application. */
               /* WM_DRAWCLIPBOARD always expects a return code of 0, so don't change "rc" here. */
               uint32_t uFormats;
               int vboxrc = VBoxClipboardWinGetFormats(pWinCtx, &uFormats);
               if (RT_SUCCESS(vboxrc))
                   vboxrc = VbglR3ClipboardReportFormats(pCtx->u32ClientID, uFormats);
           }

           if (pWinCtx->hWndNextInChain)
           {
               /* Pass the message to next windows in the clipboard chain. */
               SendMessageTimeout(pWinCtx->hWndNextInChain, msg, wParam, lParam, 0, VBOX_CLIPBOARD_CBCHAIN_TIMEOUT_MS, NULL);
           }
        }
        break;

        case WM_TIMER:
        {
           if (VBoxClipboardWinIsNewAPI(&pWinCtx->newAPI))
               break;

           HWND hViewer = GetClipboardViewer();

           /* Re-register ourselves in the clipboard chain if our last ping
            * timed out or there seems to be no valid chain. */
           if (!hViewer || pWinCtx->oldAPI.fCBChainPingInProcess)
           {
               VBoxClipboardWinRemoveFromCBChain(pWinCtx);
               VBoxClipboardWinAddToCBChain(pWinCtx);
           }

           /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
            * processed by ourselves to the chain. */
           pWinCtx->oldAPI.fCBChainPingInProcess = TRUE;

           hViewer = GetClipboardViewer();
           if (hViewer)
               SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pWinCtx->hWndNextInChain, (LPARAM)pWinCtx->hWndNextInChain,
                                   VBoxClipboardWinChainPingProc, (ULONG_PTR)pWinCtx);
        }
        break;

        case WM_CLOSE:
        {
           /* Do nothing. Ignore the message. */
        }
        break;

        case WM_RENDERFORMAT:
        {
           /* Insert the requested clipboard format data into the clipboard. */
           uint32_t fFormat = VBOX_SHARED_CLIPBOARD_FMT_NONE;

           const UINT cfFormat = (UINT)wParam;
           switch (cfFormat)
           {
              case CF_UNICODETEXT:
                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
                  break;

              case CF_DIB:
                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
                  break;

#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
              case CF_HDROP:
                  fFormat = VBOX_SHARED_CLIPBOARD_FMT_URI_LIST;
                  break;
#endif
              default:
                  if (cfFormat >= 0xC000) /** @todo r=andy Explain. */
                  {
                      TCHAR szFormatName[256]; /** @todo r=andy Do we need Unicode support here as well? */

                      int cActual = GetClipboardFormatName(cfFormat, szFormatName, sizeof(szFormatName) / sizeof(TCHAR));
                      if (cActual)
                      {
                          if (strcmp(szFormatName, "HTML Format") == 0)
                              fFormat = VBOX_SHARED_CLIPBOARD_FMT_HTML;
                      }
                  }
                  break;
           }

           LogFunc(("WM_RENDERFORMAT: format=%u -> fFormat=0x%x\n", cfFormat, fFormat));

           if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_NONE)
           {
               /* Unsupported clipboard format is requested. */
               LogRel(("Clipboard: Unsupported clipboard format requested (0x%x)\n", fFormat));
               VBoxClipboardWinClear();
           }
#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
           else if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
           {

           }
#endif
           else
           {
               const uint32_t cbPrealloc = _4K;
               uint32_t cb = 0;

               /* Preallocate a buffer, most of small text transfers will fit into it. */
               HANDLE hMem = GlobalAlloc(GMEM_DDESHARE | GMEM_MOVEABLE, cbPrealloc);
               LogFlowFunc(("Preallocated handle hMem = %p\n", hMem));

               if (hMem)
               {
                   void *pMem = GlobalLock(hMem);
                   LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));

                   if (pMem)
                   {
                       /* Read the host data to the preallocated buffer. */
                       int vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cbPrealloc, &cb);
                       LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc\n",  vboxrc));

                       if (RT_SUCCESS(vboxrc))
                       {
                           if (cb == 0)
                           {
                               /* 0 bytes returned means the clipboard is empty.
                                * Deallocate the memory and set hMem to NULL to get to
                                * the clipboard empty code path. */
                               GlobalUnlock(hMem);
                               GlobalFree(hMem);
                               hMem = NULL;
                           }
                           else if (cb > cbPrealloc)
                           {
                               GlobalUnlock(hMem);

                               /* The preallocated buffer is too small, adjust the size. */
                               hMem = GlobalReAlloc(hMem, cb, 0);
                               LogFlowFunc(("Reallocated hMem = %p\n", hMem));

                               if (hMem)
                               {
                                   pMem = GlobalLock(hMem);
                                   LogFlowFunc(("Locked pMem = %p, GlobalSize = %ld\n", pMem, GlobalSize(hMem)));

                                   if (pMem)
                                   {
                                       /* Read the host data to the preallocated buffer. */
                                       uint32_t cbNew = 0;
                                       vboxrc = VbglR3ClipboardReadData(pCtx->u32ClientID, fFormat, pMem, cb, &cbNew);
                                       LogFlowFunc(("VbglR3ClipboardReadData returned with rc = %Rrc, cb = %d, cbNew = %d\n", vboxrc, cb, cbNew));

                                       if (RT_SUCCESS(vboxrc) && cbNew <= cb)
                                       {
                                           cb = cbNew;
                                       }
                                       else
                                       {
                                           GlobalUnlock(hMem);
                                           GlobalFree(hMem);
                                           hMem = NULL;
                                       }
                                   }
                                   else
                                   {
                                       GlobalFree(hMem);
                                       hMem = NULL;
                                   }
                               }
                           }

                           if (hMem)
                           {
                               /* pMem is the address of the data. cb is the size of returned data. */
                               /* Verify the size of returned text, the memory block for clipboard
                                * must have the exact string size.
                                */
                               if (fFormat == VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                               {
                                   size_t cbActual = 0;
                                   HRESULT hrc = StringCbLengthW((LPWSTR)pMem, cb, &cbActual);
                                   if (FAILED(hrc))
                                   {
                                       /* Discard invalid data. */
                                       GlobalUnlock(hMem);
                                       GlobalFree(hMem);
                                       hMem = NULL;
                                   }
                                   else
                                   {
                                       /* cbActual is the number of bytes, excluding those used
                                        * for the terminating null character.
                                        */
                                       cb = (uint32_t)(cbActual + 2);
                                   }
                               }
                           }

                           if (hMem)
                           {
                               GlobalUnlock(hMem);

                               hMem = GlobalReAlloc(hMem, cb, 0);
                               LogFlowFunc(("Reallocated hMem = %p\n", hMem));

                               if (hMem)
                               {
                                   /* 'hMem' contains the host clipboard data.
                                    * size is 'cb' and format is 'format'. */
                                   HANDLE hClip = SetClipboardData(cfFormat, hMem);
                                   LogFlowFunc(("WM_RENDERFORMAT hClip = %p\n", hClip));

                                   if (hClip)
                                   {
                                       /* The hMem ownership has gone to the system. Finish the processing. */
                                       break;
                                   }

                                   /* Cleanup follows. */
                               }
                           }
                       }
                       if (hMem)
                           GlobalUnlock(hMem);
                   }
                   if (hMem)
                       GlobalFree(hMem);
               }

               /* Something went wrong. */
               VBoxClipboardWinClear();
           }
        }
        break;

        case WM_RENDERALLFORMATS:
        {
           /* Do nothing. The clipboard formats will be unavailable now, because the
            * windows is to be destroyed and therefore the guest side becomes inactive.
            */
           int vboxrc = VBoxClipboardWinOpen(hwnd);
           if (RT_SUCCESS(vboxrc))
           {
               VBoxClipboardWinClear();
               VBoxClipboardWinClose();
           }
        }
        break;

        case VBOX_CLIPBOARD_WM_SET_FORMATS:
        {
           /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
           VBOXCLIPBOARDFORMATS fFormats = (uint32_t)lParam;

           LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: fFormats=0x%x\n", fFormats));

           int vboxrc = VBoxClipboardWinOpen(hwnd);
           if (RT_SUCCESS(vboxrc))
           {
               VBoxClipboardWinClear();

               HANDLE hClip = NULL;

               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                   hClip = SetClipboardData(CF_UNICODETEXT, NULL);

               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                   hClip = SetClipboardData(CF_DIB, NULL);

               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
               {
                   UINT format = RegisterClipboardFormat("HTML Format");
                   if (format != 0)
                       hClip = SetClipboardData(format, NULL);
               }

#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
               if (fFormats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
                   hClip = SetClipboardData(CF_HDROP, NULL);
#endif

               /** @todo Implement more flexible clipboard precedence for supported formats. */

               if (hClip == NULL)
                   LogRel(("Clipboard: Unsupported format(s) from host (0x%x), ignoring\n", fFormats));

               VBoxClipboardWinClose();

               LogFlowFunc(("VBOX_WM_SHCLPB_SET_FORMATS: hClip=%p, lastErr=%ld\n", hClip, GetLastError()));
           }
        }
        break;

        case VBOX_CLIPBOARD_WM_READ_DATA:
        {
           /* Send data in the specified format to the host. */
           uint32_t u32Formats = (uint32_t)lParam;
           HANDLE hClip = NULL;

           LogFlowFunc(("VBOX_WM_SHCLPB_READ_DATA: u32Formats=0x%x\n", u32Formats));

           int vboxrc = VBoxClipboardWinOpen(hwnd);
           if (RT_SUCCESS(vboxrc))
           {
               if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
               {
                   hClip = GetClipboardData(CF_DIB);

                   if (hClip != NULL)
                   {
                       LPVOID lp = GlobalLock(hClip);
                       if (lp != NULL)
                       {
                           vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_BITMAP,
                                                             lp, GlobalSize(hClip));
                           GlobalUnlock(hClip);
                       }
                       else
                       {
                           hClip = NULL;
                       }
                   }
               }
               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
               {
                   hClip = GetClipboardData(CF_UNICODETEXT);

                   if (hClip != NULL)
                   {
                       LPWSTR uniString = (LPWSTR)GlobalLock(hClip);

                       if (uniString != NULL)
                       {
                           vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT,
                                                             uniString, (lstrlenW(uniString) + 1) * 2);
                           GlobalUnlock(hClip);
                       }
                       else
                       {
                           hClip = NULL;
                       }
                   }
               }
               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
               {
                   UINT format = RegisterClipboardFormat("HTML Format");
                   if (format != 0)
                   {
                       hClip = GetClipboardData(format);
                       if (hClip != NULL)
                       {
                           LPVOID lp = GlobalLock(hClip);

                           if (lp != NULL)
                           {
                               vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_HTML,
                                                                 lp, GlobalSize(hClip));
                               GlobalUnlock(hClip);
                           }
                           else
                           {
                               hClip = NULL;
                           }
                       }
                   }
               }
#ifdef VBOX_WITH_SHARED_CLIPBOARD_URI_LIST
               else if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_URI_LIST)
               {
                   hClip = GetClipboardData(CF_HDROP);
                   if (hClip)
                   {
                       HDROP hDrop = (HDROP)GlobalLock(hClip);
                       if (hDrop)
                       {
       /*                    vboxrc = VbglR3ClipboardWriteData(pCtx->u32ClientID, VBOX_SHARED_CLIPBOARD_FMT_URI_LIST,
                                                             );*/
                           GlobalUnlock(hClip);
                       }
                       else
                       {
                           hClip = NULL;
                       }
                   }
               }
#endif
               VBoxClipboardWinClose();
           }

           if (hClip == NULL)
           {
               /* Requested clipboard format is not available, send empty data. */
               VbglR3ClipboardWriteData(pCtx->u32ClientID, 0, NULL, 0);
           }
        }
        break;

        case WM_DESTROY:
        {
           VBoxClipboardWinRemoveFromCBChain(pWinCtx);
           if (pWinCtx->oldAPI.timerRefresh)
               KillTimer(pWinCtx->hWnd, 0);
           /*
            * don't need to call PostQuitMessage cause
            * the VBoxTray already finished a message loop
            */
        }
        break;

        default:
        {
           rc = DefWindowProc(hwnd, msg, wParam, lParam);
        }
        break;
    }

#ifndef DEBUG_andy
    LogFlowFunc(("vboxClipboardProcessMsg returned with rc = %ld\n", rc));
#endif
    return rc;
}
Example #10
0
void
_gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t,
                                             enum random_origins),
                                 enum random_origins origin)
{
  static int addedFixedItems = 0;

  if ( debug_me )
    log_debug ("rndw32#gather_random_fast: ori=%d\n", origin );

  /* Get various basic pieces of system information: Handle of active
     window, handle of window with mouse capture, handle of clipboard
     owner handle of start of clpboard viewer list, pseudohandle of
     current process, current process ID, pseudohandle of current
     thread, current thread ID, handle of desktop window, handle of
     window with keyboard focus, whether system queue has any events,
     cursor position for last message, 1 ms time for last message,
     handle of window with clipboard open, handle of process heap,
     handle of procs window station, types of events in input queue,
     and milliseconds since Windows was started.  */

  {
    byte buffer[20*sizeof(ulong)], *bufptr;

    bufptr = buffer;
#define ADD(f)  do { ulong along = (ulong)(f);                  \
                     memcpy (bufptr, &along, sizeof (along) );  \
                     bufptr += sizeof (along);                  \
                   } while (0)

    ADD ( GetActiveWindow ());
    ADD ( GetCapture ());
    ADD ( GetClipboardOwner ());
    ADD ( GetClipboardViewer ());
    ADD ( GetCurrentProcess ());
    ADD ( GetCurrentProcessId ());
    ADD ( GetCurrentThread ());
    ADD ( GetCurrentThreadId ());
    ADD ( GetDesktopWindow ());
    ADD ( GetFocus ());
    ADD ( GetInputState ());
    ADD ( GetMessagePos ());
    ADD ( GetMessageTime ());
    ADD ( GetOpenClipboardWindow ());
    ADD ( GetProcessHeap ());
    ADD ( GetProcessWindowStation ());
    ADD ( GetQueueStatus (QS_ALLEVENTS));
    ADD ( GetTickCount ());

    gcry_assert ( bufptr-buffer < sizeof (buffer) );
    (*add) ( buffer, bufptr-buffer, origin );
#undef ADD
  }

  /* Get multiword system information: Current caret position, current
     mouse cursor position.  */
  {
    POINT point;

    GetCaretPos (&point);
    (*add) ( &point, sizeof (point), origin );
    GetCursorPos (&point);
    (*add) ( &point, sizeof (point), origin );
  }

  /* Get percent of memory in use, bytes of physical memory, bytes of
     free physical memory, bytes in paging file, free bytes in paging
     file, user bytes of address space, and free user bytes.  */
  {
    MEMORYSTATUS memoryStatus;

    memoryStatus.dwLength = sizeof (MEMORYSTATUS);
    GlobalMemoryStatus (&memoryStatus);
    (*add) ( &memoryStatus, sizeof (memoryStatus), origin );
  }

  /* Get thread and process creation time, exit time, time in kernel
     mode, and time in user mode in 100ns intervals.  */
  {
    HANDLE handle;
    FILETIME creationTime, exitTime, kernelTime, userTime;
    DWORD minimumWorkingSetSize, maximumWorkingSetSize;

    handle = GetCurrentThread ();
    GetThreadTimes (handle, &creationTime, &exitTime,
                    &kernelTime, &userTime);
    (*add) ( &creationTime, sizeof (creationTime), origin );
    (*add) ( &exitTime, sizeof (exitTime), origin );
    (*add) ( &kernelTime, sizeof (kernelTime), origin );
    (*add) ( &userTime, sizeof (userTime), origin );

    handle = GetCurrentProcess ();
    GetProcessTimes (handle, &creationTime, &exitTime,
                     &kernelTime, &userTime);
    (*add) ( &creationTime, sizeof (creationTime), origin );
    (*add) ( &exitTime, sizeof (exitTime), origin );
    (*add) ( &kernelTime, sizeof (kernelTime), origin );
    (*add) ( &userTime, sizeof (userTime), origin );

    /* Get the minimum and maximum working set size for the current
       process.  */
    GetProcessWorkingSetSize (handle, &minimumWorkingSetSize,
                              &maximumWorkingSetSize);
    (*add) ( &minimumWorkingSetSize,
             sizeof (minimumWorkingSetSize), origin );
    (*add) ( &maximumWorkingSetSize,
             sizeof (maximumWorkingSetSize), origin );
  }


  /* The following are fixed for the lifetime of the process so we only
   * add them once */
  if (!addedFixedItems)
    {
      STARTUPINFO startupInfo;

      /* Get name of desktop, console window title, new window
         position and size, window flags, and handles for stdin,
         stdout, and stderr.  */
      startupInfo.cb = sizeof (STARTUPINFO);
      GetStartupInfo (&startupInfo);
      (*add) ( &startupInfo, sizeof (STARTUPINFO), origin );
      addedFixedItems = 1;
    }

  /* The performance of QPC varies depending on the architecture it's
     running on and on the OS, the MS documentation is vague about the
     details because it varies so much.  Under Win9x/ME it reads the
     1.193180 MHz PIC timer.  Under NT/Win2K/XP it may or may not read the
     64-bit TSC depending on the HAL and assorted other circumstances,
     generally on machines with a uniprocessor HAL
     KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines
     with a multiprocessor or APIC HAL it uses the TSC (the exact time
     source is controlled by the HalpUse8254 flag in the kernel).  That
     choice of time sources is somewhat peculiar because on a
     multiprocessor machine it's theoretically possible to get completely
     different TSC readings depending on which CPU you're currently
     running on, while for uniprocessor machines it's not a problem.
     However, the kernel appears to synchronise the TSCs across CPUs at
     boot time (it resets the TSC as part of its system init), so this
     shouldn't really be a problem.  Under WinCE it's completely platform-
     dependant, if there's no hardware performance counter available, it
     uses the 1ms system timer.

     Another feature of the TSC (although it doesn't really affect us here)
     is that mobile CPUs will turn off the TSC when they idle, Pentiums
     will change the rate of the counter when they clock-throttle (to
     match the current CPU speed), and hyperthreading Pentiums will turn
     it off when both threads are idle (this more or less makes sense,
     since the CPU will be in the halted state and not executing any
     instructions to count).

     To make things unambiguous, we detect a CPU new enough to call RDTSC
     directly by checking for CPUID capabilities, and fall back to QPC if
     this isn't present.  */
#ifdef __GNUC__
/*   FIXME: We would need to implement the CPU feature tests first.  */
/*   if (cpu_has_feature_rdtsc) */
/*     { */
/*       uint32_t lo, hi; */
      /* We cannot use "=A", since this would use %rax on x86_64. */
/*       __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */
      /* Ignore high 32 bits, hwich are >1s res.  */
/*       (*add) (&lo, 4, origin ); */
/*     } */
/*   else */
#endif /*!__GNUC__*/
    {
      LARGE_INTEGER performanceCount;

      if (QueryPerformanceCounter (&performanceCount))
        {
          if ( debug_me )
          log_debug ("rndw32#gather_random_fast: perf data\n");
          (*add) (&performanceCount, sizeof (performanceCount), origin);
        }
      else
        {
          /* Millisecond accuracy at best... */
          DWORD aword = GetTickCount ();
          (*add) (&aword, sizeof (aword), origin );
        }
    }


}
LRESULT CALLBACK
winClipboardWindowProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static HWND s_hwndNextViewer;
    static Bool s_fCBCInitialized;
    static Display *pDisplay;
    static Window iWindow;
    static ClipboardAtoms *atoms;
    static Bool fRunning;

    /* Branch on message type */
    switch (message) {
    case WM_DESTROY:
    {
        winDebug("winClipboardWindowProc - WM_DESTROY\n");

        if (g_fHasModernClipboardApi)
            {
                /* Remove clipboard listener */
                g_fpRemoveClipboardFormatListener(hwnd);
            }
        else
            {
                /* Remove ourselves from the clipboard chain */
                ChangeClipboardChain(hwnd, s_hwndNextViewer);
            }

        s_hwndNextViewer = NULL;
    }
        return 0;

    case WM_WM_QUIT:
    {
        winDebug("winClipboardWindowProc - WM_WM_QUIT\n");
        fRunning = FALSE;
        PostQuitMessage(0);
    }
        return 0;

    case WM_CREATE:
    {
        ClipboardWindowCreationParams *cwcp = (ClipboardWindowCreationParams *)((CREATESTRUCT *)lParam)->lpCreateParams;

        winDebug("winClipboardWindowProc - WM_CREATE\n");

        pDisplay = cwcp->pClipboardDisplay;
        iWindow = cwcp->iClipboardWindow;
        atoms = cwcp->atoms;
        fRunning = TRUE;

        if (g_fHasModernClipboardApi)
            {
                g_fpAddClipboardFormatListener(hwnd);
            }
        else
            {
                HWND first, next;
                DWORD error_code = 0;

                first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
                if (first == hwnd)
                    return 0;           /* Make sure it's not us! */
                /* Add ourselves to the clipboard viewer chain */
                next = SetClipboardViewer(hwnd);
                error_code = GetLastError();
                if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
                    s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
                else
                    s_fCBCInitialized = FALSE;
            }
    }
        return 0;

    case WM_CHANGECBCHAIN:
    {
        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: wParam(%p) "
                 "lParam(%p) s_hwndNextViewer(%p)\n",
                 (HWND)wParam, (HWND)lParam, s_hwndNextViewer);

        if ((HWND) wParam == s_hwndNextViewer) {
            s_hwndNextViewer = (HWND) lParam;
            if (s_hwndNextViewer == hwnd) {
                s_hwndNextViewer = NULL;
                ErrorF("winClipboardWindowProc - WM_CHANGECBCHAIN: "
                       "attempted to set next window to ourselves.");
            }
        }
        else if (s_hwndNextViewer)
            SendMessage(s_hwndNextViewer, message, wParam, lParam);

    }
        winDebug("winClipboardWindowProc - WM_CHANGECBCHAIN: Exit\n");
        return 0;

    case WM_WM_REINIT:
    {
        /* Ensure that we're in the clipboard chain.  Some apps,
         * WinXP's remote desktop for one, don't play nice with the
         * chain.  This message is called whenever we receive a
         * WM_ACTIVATEAPP message to ensure that we continue to
         * receive clipboard messages.
         *
         * It might be possible to detect if we're still in the chain
         * by calling SendMessage (GetClipboardViewer(),
         * WM_DRAWCLIPBOARD, 0, 0); and then seeing if we get the
         * WM_DRAWCLIPBOARD message.  That, however, might be more
         * expensive than just putting ourselves back into the chain.
         */

        HWND first, next;
        DWORD error_code = 0;

        winDebug("winClipboardWindowProc - WM_WM_REINIT: Enter\n");

        if (g_fHasModernClipboardApi)
            {
                return 0;
            }

        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
        if (first == hwnd)
            return 0;           /* Make sure it's not us! */
        winDebug("  WM_WM_REINIT: Replacing us(%p) with %p at head "
                 "of chain\n", hwnd, s_hwndNextViewer);
        s_fCBCInitialized = FALSE;
        ChangeClipboardChain(hwnd, s_hwndNextViewer);
        s_hwndNextViewer = NULL;
        s_fCBCInitialized = FALSE;
        winDebug("  WM_WM_REINIT: Putting us back at head of chain.\n");
        first = GetClipboardViewer();   /* Get handle to first viewer in chain. */
        if (first == hwnd)
            return 0;           /* Make sure it's not us! */
        next = SetClipboardViewer(hwnd);
        error_code = GetLastError();
        if (SUCCEEDED(error_code) && (next == first))   /* SetClipboardViewer must have succeeded, and the handle */
            s_hwndNextViewer = next;    /* it returned must have been the first window in the chain */
        else
            s_fCBCInitialized = FALSE;
    }
        winDebug("winClipboardWindowProc - WM_WM_REINIT: Exit\n");
        return 0;

    case WM_DRAWCLIPBOARD:
    case WM_CLIPBOARDUPDATE:
    {
        static Bool s_fProcessingDrawClipboard = FALSE;
        int iReturn;

        if (message == WM_DRAWCLIPBOARD)
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Enter\n");
        else
            winDebug("winClipboardWindowProc -  WM_CLIPBOARDUPDATE: Enter\n");

        if (!g_fHasModernClipboardApi)
            {
                /*
                 * We've occasionally seen a loop in the clipboard chain.
                 * Try and fix it on the first hint of recursion.
                 */
                if (!s_fProcessingDrawClipboard) {
                    s_fProcessingDrawClipboard = TRUE;
                }
                else {
                    /* Attempt to break the nesting by getting out of the chain, twice?, and then fix and bail */
                    s_fCBCInitialized = FALSE;
                    ChangeClipboardChain(hwnd, s_hwndNextViewer);
                    winFixClipboardChain();
                    ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                           "Nested calls detected.  Re-initing.\n");
                    winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
                    s_fProcessingDrawClipboard = FALSE;
                    return 0;
                }

                /* Bail on first message */
                if (!s_fCBCInitialized) {
                    s_fCBCInitialized = TRUE;
                    s_fProcessingDrawClipboard = FALSE;
                    winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
                    return 0;
                }
            }

        /*
         * NOTE: We cannot bail out when NULL == GetClipboardOwner ()
         * because some applications deal with the clipboard in a manner
         * that causes the clipboard owner to be NULL when they are in
         * fact taking ownership.  One example of this is the Win32
         * native compile of emacs.
         */

        /* Bail when we still own the clipboard */
        if (hwnd == GetClipboardOwner()) {

            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "We own the clipboard, returning.\n");
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
            s_fProcessingDrawClipboard = FALSE;
            if (s_hwndNextViewer)
                SendMessage(s_hwndNextViewer, message, wParam, lParam);
            return 0;
        }

        /* Bail when shutting down */
        if (!fRunning)
            return 0;

        /*
         * Do not take ownership of the X11 selections when something
         * other than CF_TEXT or CF_UNICODETEXT has been copied
         * into the Win32 clipboard.
         */
        if (!IsClipboardFormatAvailable(CF_TEXT)
            && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {

            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "Clipboard does not contain CF_TEXT nor "
                     "CF_UNICODETEXT.\n");

            /*
             * We need to make sure that the X Server has processed
             * previous XSetSelectionOwner messages.
             */
            XSync(pDisplay, FALSE);

            winDebug("winClipboardWindowProc - XSync done.\n");

            /* Release PRIMARY selection if owned */
            iReturn = XGetSelectionOwner(pDisplay, XA_PRIMARY);
            if (iReturn == iWindow) {
                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                         "PRIMARY selection is owned by us.\n");
                XSetSelectionOwner(pDisplay, XA_PRIMARY, None, CurrentTime);
            }
            else if (BadWindow == iReturn || BadAtom == iReturn)
                ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                       "XGetSelectionOwner failed for PRIMARY: %d\n",
                       iReturn);

            /* Release CLIPBOARD selection if owned */
            iReturn = XGetSelectionOwner(pDisplay, atoms->atomClipboard);
            if (iReturn == iWindow) {
                winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                         "CLIPBOARD selection is owned by us, releasing\n");
                XSetSelectionOwner(pDisplay, atoms->atomClipboard, None, CurrentTime);
            }
            else if (BadWindow == iReturn || BadAtom == iReturn)
                ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                       "XGetSelectionOwner failed for CLIPBOARD: %d\n",
                       iReturn);

            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
            s_fProcessingDrawClipboard = FALSE;
            if (s_hwndNextViewer)
                SendMessage(s_hwndNextViewer, message, wParam, lParam);
            return 0;
        }

        /* Reassert ownership of PRIMARY */
        iReturn = XSetSelectionOwner(pDisplay,
                                     XA_PRIMARY, iWindow, CurrentTime);
        if (iReturn == BadAtom || iReturn == BadWindow ||
            XGetSelectionOwner(pDisplay, XA_PRIMARY) != iWindow) {
            ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                   "Could not reassert ownership of PRIMARY\n");
        }
        else {
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "Reasserted ownership of PRIMARY\n");
        }

        /* Reassert ownership of the CLIPBOARD */
        iReturn = XSetSelectionOwner(pDisplay,
                                     atoms->atomClipboard, iWindow, CurrentTime);

        if (iReturn == BadAtom || iReturn == BadWindow ||
            XGetSelectionOwner(pDisplay, atoms->atomClipboard) != iWindow) {
            ErrorF("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                    "Could not reassert ownership of CLIPBOARD\n");
        }
        else {
            winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD - "
                     "Reasserted ownership of CLIPBOARD\n");
        }

        /* Flush the pending SetSelectionOwner event now */
        XFlush(pDisplay);

        s_fProcessingDrawClipboard = FALSE;
    }
        winDebug("winClipboardWindowProc - WM_DRAWCLIPBOARD: Exit\n");
        /* Pass the message on the next window in the clipboard viewer chain */
        if (s_hwndNextViewer)
            SendMessage(s_hwndNextViewer, message, wParam, lParam);
        return 0;

    case WM_DESTROYCLIPBOARD:
        /*
         * NOTE: Intentionally do nothing.
         * Changes in the Win32 clipboard are handled by WM_DRAWCLIPBOARD
         * above.  We only process this message to conform to the specs
         * for delayed clipboard rendering in Win32.  You might think
         * that we need to release ownership of the X11 selections, but
         * we do not, because a WM_DRAWCLIPBOARD message will closely
         * follow this message and reassert ownership of the X11
         * selections, handling the issue for us.
         */
        winDebug("winClipboardWindowProc - WM_DESTROYCLIPBOARD - Ignored.\n");
        return 0;

    case WM_RENDERALLFORMATS:
        winDebug("winClipboardWindowProc - WM_RENDERALLFORMATS - Hello.\n");

        /*
          WM_RENDERALLFORMATS is sent as we are shutting down, to render the
          clipboard so it's contents remains available to other applications.

          Unfortunately, this can't work without major changes. The server is
          already waiting for us to stop, so we can't ask for the rendering of
          clipboard text now.
        */

        return 0;

    case WM_RENDERFORMAT:
    {
        int iReturn;
        Bool fConvertToUnicode;
        Bool pasted = FALSE;
        Atom selection;
        ClipboardConversionData data;
        int best_target = 0;

        winDebug("winClipboardWindowProc - WM_RENDERFORMAT %d - Hello.\n",
                 (int)wParam);

        /* Flag whether to convert to Unicode or not */
        fConvertToUnicode = (CF_UNICODETEXT == wParam);

        selection = winClipboardGetLastOwnedSelectionAtom(atoms);
        if (selection == None) {
            ErrorF("winClipboardWindowProc - no monitored selection is owned\n");
            goto fake_paste;
        }

        winDebug("winClipboardWindowProc - requesting targets for selection from owner\n");

        /* Request the selection's supported conversion targets */
        XConvertSelection(pDisplay,
                          selection,
                          atoms->atomTargets,
                          atoms->atomLocalProperty,
                          iWindow, CurrentTime);

        /* Process X events */
        data.fUseUnicode = fConvertToUnicode;
        iReturn = winProcessXEventsTimeout(hwnd,
                                           iWindow,
                                           pDisplay,
                                           &data,
                                           atoms,
                                           WIN_POLL_TIMEOUT);

        if (WIN_XEVENTS_NOTIFY_TARGETS != iReturn) {
            ErrorF
                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_TARGETS\n");
            goto fake_paste;
        }

        /* Choose the most preferred target */
        {
            struct target_priority
            {
                Atom target;
                unsigned int priority;
            };

            struct target_priority target_priority_table[] =
                {
                    { atoms->atomCompoundText, 0 },
#ifdef X_HAVE_UTF8_STRING
                    { atoms->atomUTF8String,   1 },
#endif
                    { XA_STRING,               2 },
                };

            int best_priority = INT_MAX;

            int i,j;
            for (i = 0 ; data.targetList[i] != 0; i++)
                {
                    for (j = 0; j < sizeof(target_priority_table)/sizeof(struct target_priority); j ++)
                        {
                            if ((data.targetList[i] == target_priority_table[j].target) &&
                                (target_priority_table[j].priority < best_priority))
                                {
                                    best_target = target_priority_table[j].target;
                                    best_priority = target_priority_table[j].priority;
                                }
                        }
                }
        }

        free(data.targetList);
        data.targetList = 0;

        winDebug("winClipboardWindowProc - best target is %d\n", best_target);

        /* No useful targets found */
        if (best_target == 0)
          goto fake_paste;

        winDebug("winClipboardWindowProc - requesting selection from owner\n");

        /* Request the selection contents */
        XConvertSelection(pDisplay,
                          selection,
                          best_target,
                          atoms->atomLocalProperty,
                          iWindow, CurrentTime);

        /* Process X events */
        iReturn = winProcessXEventsTimeout(hwnd,
                                           iWindow,
                                           pDisplay,
                                           &data,
                                           atoms,
                                           WIN_POLL_TIMEOUT);

        /*
         * winProcessXEventsTimeout had better have seen a notify event,
         * or else we are dealing with a buggy or old X11 app.
         */
        if (WIN_XEVENTS_NOTIFY_DATA != iReturn) {
            ErrorF
                ("winClipboardWindowProc - timed out waiting for WIN_XEVENTS_NOTIFY_DATA\n");
        }
        else {
            pasted = TRUE;
        }

         /*
          * If we couldn't get the data from the X clipboard, we
          * have to paste some fake data to the Win32 clipboard to
          * satisfy the requirement that we write something to it.
          */
    fake_paste:
        if (!pasted)
          {
            /* Paste no data, to satisfy required call to SetClipboardData */
            SetClipboardData(CF_UNICODETEXT, NULL);
            SetClipboardData(CF_TEXT, NULL);
          }

        winDebug("winClipboardWindowProc - WM_RENDERFORMAT - Returning.\n");
        return 0;
    }
    }

    /* Let Windows perform default processing for unhandled messages */
    return DefWindowProc(hwnd, message, wParam, lParam);
}
static LRESULT CALLBACK vboxClipboardWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    LRESULT rc = 0;

    VBOXCLIPBOARDCONTEXT *pCtx = &g_ctx;

    switch (msg)
    {
        case WM_CHANGECBCHAIN:
        {
            Log(("WM_CHANGECBCHAIN\n"));

            HWND hwndRemoved = (HWND)wParam;
            HWND hwndNext    = (HWND)lParam;

            if (hwndRemoved == pCtx->hwndNextInChain)
            {
                /* The window that was next to our in the chain is being removed.
                 * Relink to the new next window.
                 */
                pCtx->hwndNextInChain = hwndNext;
            }
            else
            {
                if (pCtx->hwndNextInChain)
                {
                    /* Pass the message further. */
                    DWORD_PTR dwResult;
                    rc = SendMessageTimeout(pCtx->hwndNextInChain, WM_CHANGECBCHAIN, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
                    if (!rc)
                        rc = (LRESULT)dwResult;
                }
            }
        } break;

        case WM_DRAWCLIPBOARD:
        {
            Log(("WM_DRAWCLIPBOARD next %p\n", pCtx->hwndNextInChain));

            if (GetClipboardOwner () != hwnd)
            {
                /* Clipboard was updated by another application. */
                vboxClipboardChanged (pCtx);
            }

            if (pCtx->hwndNextInChain)
            {
                /* Pass the message to next windows in the clipboard chain. */
                DWORD_PTR dwResult;
                rc = SendMessageTimeout(pCtx->hwndNextInChain, msg, wParam, lParam, 0, CBCHAIN_TIMEOUT, &dwResult);
                if (!rc)
                    rc = dwResult;
            }
        } break;

        case WM_TIMER:
        {
            HWND hViewer = GetClipboardViewer();

            /* Re-register ourselves in the clipboard chain if our last ping
             * timed out or there seems to be no valid chain. */
            if (!hViewer || pCtx->fCBChainPingInProcess)
            {
                removeFromCBChain(pCtx);
                addToCBChain(pCtx);
            }
            /* Start a new ping by passing a dummy WM_CHANGECBCHAIN to be
             * processed by ourselves to the chain. */
            pCtx->fCBChainPingInProcess = TRUE;
            hViewer = GetClipboardViewer();
            if (hViewer)
                SendMessageCallback(hViewer, WM_CHANGECBCHAIN, (WPARAM)pCtx->hwndNextInChain, (LPARAM)pCtx->hwndNextInChain, CBChainPingProc, (ULONG_PTR) pCtx);
        } break;

        case WM_CLOSE:
        {
            /* Do nothing. Ignore the message. */
        } break;

        case WM_RENDERFORMAT:
        {
            /* Insert the requested clipboard format data into the clipboard. */
            uint32_t u32Format = 0;

            UINT format = (UINT)wParam;

            Log(("WM_RENDERFORMAT %d\n", format));

            switch (format)
            {
                case CF_UNICODETEXT:
                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT;
                    break;

                case CF_DIB:
                    u32Format |= VBOX_SHARED_CLIPBOARD_FMT_BITMAP;
                    break;

                default:
                    if (format >= 0xC000)
                    {
                        TCHAR szFormatName[256];

                        int cActual = GetClipboardFormatName(format, szFormatName, sizeof(szFormatName)/sizeof (TCHAR));

                        if (cActual)
                        {
                            if (strcmp (szFormatName, "HTML Format") == 0)
                            {
                                u32Format |= VBOX_SHARED_CLIPBOARD_FMT_HTML;
                            }
                        }
                    }
                    break;
            }

            if (u32Format == 0 || pCtx->pClient == NULL)
            {
                /* Unsupported clipboard format is requested. */
                Log(("WM_RENDERFORMAT unsupported format requested or client is not active.\n"));
                EmptyClipboard ();
            }
            else
            {
                int vboxrc = vboxClipboardReadDataFromClient (pCtx, u32Format);

                dprintf(("vboxClipboardReadDataFromClient vboxrc = %d\n", vboxrc));

                if (   RT_SUCCESS (vboxrc)
                    && pCtx->pClient->data.pv != NULL
                    && pCtx->pClient->data.cb > 0
                    && pCtx->pClient->data.u32Format == u32Format)
                {
                    HANDLE hMem = GlobalAlloc (GMEM_DDESHARE | GMEM_MOVEABLE, pCtx->pClient->data.cb);

                    dprintf(("hMem %p\n", hMem));

                    if (hMem)
                    {
                        void *pMem = GlobalLock (hMem);

                        dprintf(("pMem %p, GlobalSize %d\n", pMem, GlobalSize (hMem)));

                        if (pMem)
                        {
                            Log(("WM_RENDERFORMAT setting data\n"));

                            if (pCtx->pClient->data.pv)
                            {
                                memcpy (pMem, pCtx->pClient->data.pv, pCtx->pClient->data.cb);

                                RTMemFree (pCtx->pClient->data.pv);
                                pCtx->pClient->data.pv        = NULL;
                            }

                            pCtx->pClient->data.cb        = 0;
                            pCtx->pClient->data.u32Format = 0;

                            /* The memory must be unlocked before inserting to the Clipboard. */
                            GlobalUnlock (hMem);

                            /* 'hMem' contains the host clipboard data.
                             * size is 'cb' and format is 'format'.
                             */
                            HANDLE hClip = SetClipboardData (format, hMem);

                            dprintf(("vboxClipboardHostEvent hClip %p\n", hClip));

                            if (hClip)
                            {
                                /* The hMem ownership has gone to the system. Nothing to do. */
                                break;
                            }
                        }

                        GlobalFree (hMem);
                    }
                }

                RTMemFree (pCtx->pClient->data.pv);
                pCtx->pClient->data.pv        = NULL;
                pCtx->pClient->data.cb        = 0;
                pCtx->pClient->data.u32Format = 0;

                /* Something went wrong. */
                EmptyClipboard ();
            }
        } break;

        case WM_RENDERALLFORMATS:
        {
            Log(("WM_RENDERALLFORMATS\n"));

            /* Do nothing. The clipboard formats will be unavailable now, because the
             * windows is to be destroyed and therefore the guest side becomes inactive.
             */
            if (OpenClipboard (hwnd))
            {
                EmptyClipboard();

                CloseClipboard();
            }
        } break;

        case WM_USER:
        {
            if (pCtx->pClient == NULL || pCtx->pClient->fMsgFormats)
            {
                /* Host has pending formats message. Ignore the guest announcement,
                 * because host clipboard has more priority.
                 */
                break;
            }

            /* Announce available formats. Do not insert data, they will be inserted in WM_RENDER*. */
            uint32_t u32Formats = (uint32_t)lParam;

            Log(("WM_USER u32Formats = %02X\n", u32Formats));

            if (OpenClipboard (hwnd))
            {
                EmptyClipboard();

                Log(("WM_USER emptied clipboard\n"));

                HANDLE hClip = NULL;

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT)
                {
                    dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_UNICODETEXT\n"));

                    hClip = SetClipboardData (CF_UNICODETEXT, NULL);
                }

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_BITMAP)
                {
                    dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_BITMAP\n"));

                    hClip = SetClipboardData (CF_DIB, NULL);
                }

                if (u32Formats & VBOX_SHARED_CLIPBOARD_FMT_HTML)
                {
                    UINT format = RegisterClipboardFormat ("HTML Format");
                    dprintf(("window proc WM_USER: VBOX_SHARED_CLIPBOARD_FMT_HTML 0x%04X\n", format));
                    if (format != 0)
                    {
                        hClip = SetClipboardData (format, NULL);
                    }
                }

                CloseClipboard();

                dprintf(("window proc WM_USER: hClip %p, err %d\n", hClip, GetLastError ()));
            }
            else
            {
                dprintf(("window proc WM_USER: failed to open clipboard\n"));
            }
        } break;

        default:
        {
            Log(("WM_ %p\n", msg));
            rc = DefWindowProc (hwnd, msg, wParam, lParam);
        }
    }

    Log(("WM_ rc %d\n", rc));
    return rc;
}