static PyObject *
py_get_open_clipboard_window(PyObject* self, PyObject* args)
{

  CHECK_NO_ARGS2(args, "GetOpenClipboardWindow");

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

  if (!rc)
    return ReturnAPIError("GetOpenClipboardWindow");

  return PyWinLong_FromHANDLE(rc);

  // @comm If an application or dynamic-link library (DLL) specifies a NULL
  // window handle when calling the OpenClipboard function, the clipboard is
  // opened but is not associated with a window. In such a case,
  // GetOpenClipboardWindow returns NULL. 

  // @pyseeapi GetOpenClipboardWindow

  // @rdesc If the function succeeds, the return value is the handle of the
  // window that has the clipboard open. 
  // If the function fails, win32api.error is raised with the GetLastError
  // info.

}
void CopyPopupDataToClipboard(HWND hList, int selection)
{
	if (!selection)
	{
		return;
	}
	
	if (!GetOpenClipboardWindow())
	{
		if (OpenClipboard(hList))
		{
			TCHAR buffer[2048];
			buffer[0] = _T('\0');
			TCHAR *clipboard;
			int i;
			int found = 0;
			int count = ListView_GetItemCount(hList);
			int textType;
#ifdef _UNICODE
			textType = CF_UNICODETEXT;
#else
			textType = CF_TEXT;
#endif
			
			for (i = 0; i < count; i++)
			{
				if (ListView_GetItemState(hList, i, LVIS_SELECTED))
				{
					ListView_GetItemText(hList, i, selection - 100, buffer, 2048);
					found = 1;
					break;
				}
			}
			if (found)
			{
				EmptyClipboard();
				int len = (int)_tcslen(buffer);
				
				HANDLE hData = GlobalAlloc(GMEM_MOVEABLE, (len + 2) * sizeof(TCHAR));
				clipboard = (TCHAR *) GlobalLock(hData);
				_tcsncpy(clipboard, buffer, len);
				clipboard[len] = _T('\0');
				GlobalUnlock(hData);
				if (!SetClipboardData(textType, hData))
				{
					PUShowMessage("Could not set clipboard data", SM_WARNING);
				}
			}
			CloseClipboard();
		}
		else{
			PUShowMessage("Could not open clipboard", SM_WARNING);
		}
	}
	else{
		PUShowMessage("The clipboard is not available", SM_WARNING);
	}
}
Example #3
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 #4
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);
}
int
winProcSetSelectionOwner (ClientPtr client)
{
  int			i;
  DrawablePtr		pDrawable;
  WindowPtr		pWindow = None;
  Bool			fOwnedToNotOwned = FALSE;
  static Window		s_iOwners[CLIP_NUM_SELECTIONS] = {None};
  static unsigned long	s_ulServerGeneration = 0;
  REQUEST(xSetSelectionOwnerReq);
  
  REQUEST_SIZE_MATCH(xSetSelectionOwnerReq);

#if 0
  ErrorF ("winProcSetSelectionOwner - Hello.\n");
#endif

  /* Watch for server reset */
  if (s_ulServerGeneration != serverGeneration)
    {
      /* Save new generation number */
      s_ulServerGeneration = serverGeneration;

      /* Initialize static variables */
      for (i = 0; i < CLIP_NUM_SELECTIONS; ++i)
	s_iOwners[i] = None;
    }

  /* Abort if clipboard not completely initialized yet */
  if (!g_fClipboardStarted)
    {
      ErrorF ("winProcSetSelectionOwner - Clipboard not yet started, "
	      "aborting.\n");
      goto winProcSetSelectionOwner_Done;
    }
  
  /* Grab window if we have one */
  if (None != stuff->window)
    {
      /* Grab the Window from the request */
      int rc = dixLookupWindow(&pWindow, stuff->window, client, DixReadAccess);
      if (rc != Success) {
	  ErrorF ("winProcSetSelectionOwner - Found BadWindow, aborting.\n");
	  goto winProcSetSelectionOwner_Done;
      }
    }

  /* Now we either have a valid window or None */

  /* Save selection owners for monitored selections, ignore other selections */
  if (XA_PRIMARY == stuff->selection)
    {
      /* Look for owned -> not owned transition */
      if (None == stuff->window
	  && None != s_iOwners[CLIP_OWN_PRIMARY])
	{
	  fOwnedToNotOwned = TRUE;

#if 0
	  ErrorF ("winProcSetSelectionOwner - PRIMARY - Going from "
		  "owned to not owned.\n");
#endif

	  /* Adjust last owned selection */
	  if (None != s_iOwners[CLIP_OWN_CLIPBOARD])
	    g_atomLastOwnedSelection = MakeAtom ("CLIPBOARD", 9, TRUE);
	  else
	    g_atomLastOwnedSelection = None;
	}
      
      /* Save new selection owner or None */
      s_iOwners[CLIP_OWN_PRIMARY] = stuff->window;

#if 0
      ErrorF ("winProcSetSelectionOwner - PRIMARY - Now owned by: %d\n",
	      stuff->window);
#endif
    }
  else if (MakeAtom ("CLIPBOARD", 9, TRUE) == stuff->selection)
    {
      /* Look for owned -> not owned transition */
      if (None == stuff->window
	  && None != s_iOwners[CLIP_OWN_CLIPBOARD])
	{
	  fOwnedToNotOwned = TRUE;
	  
#if 0
	  ErrorF ("winProcSetSelectionOwner - CLIPBOARD - Going from "
		  "owned to not owned.\n");
#endif

	  /* Adjust last owned selection */
	  if (None != s_iOwners[CLIP_OWN_PRIMARY])
	    g_atomLastOwnedSelection = XA_PRIMARY;
	  else
	    g_atomLastOwnedSelection = None;
	}
      
      /* Save new selection owner or None */
      s_iOwners[CLIP_OWN_CLIPBOARD] = stuff->window;

#if 0
      ErrorF ("winProcSetSelectionOwner - CLIPBOARD - Now owned by: %d\n",
	      stuff->window);
#endif
    }
  else
    goto winProcSetSelectionOwner_Done;

  /*
   * At this point, if one of the selections is still owned by the 
   * clipboard manager then it should be marked as unowned since
   * we will be taking ownership of the Win32 clipboard.
   */
  if (g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
    s_iOwners[CLIP_OWN_PRIMARY] = None;
  if (g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
    s_iOwners[CLIP_OWN_CLIPBOARD] = None;

  /*
   * Handle case when selection is being disowned,
   * WM_DRAWCLIPBOARD did not do the disowning,
   * both monitored selections are no longer owned,
   * an owned to not owned transition was detected,
   * and we currently own the Win32 clipboard.
   */
  if (None == stuff->window
      && g_iClipboardWindow != client->lastDrawableID
      && (None == s_iOwners[CLIP_OWN_PRIMARY]
	  || g_iClipboardWindow == s_iOwners[CLIP_OWN_PRIMARY])
      && (None == s_iOwners[CLIP_OWN_CLIPBOARD]
	  || g_iClipboardWindow == s_iOwners[CLIP_OWN_CLIPBOARD])
      && fOwnedToNotOwned
      && g_hwndClipboard != NULL
      && g_hwndClipboard == GetClipboardOwner ())
    {
#if 0
      ErrorF ("winProcSetSelectionOwner - We currently own the "
	      "clipboard and neither the PRIMARY nor the CLIPBOARD "
	      "selections are owned, releasing ownership of Win32 "
	      "clipboard.\n");
#endif
      
      /* Release ownership of the Windows clipboard */
      OpenClipboard (NULL);
      EmptyClipboard ();
      CloseClipboard ();

      /* Clear X selection ownership (might still be marked as us owning) */
      s_iOwners[CLIP_OWN_PRIMARY] = None;
      s_iOwners[CLIP_OWN_CLIPBOARD] = None;
      
      goto winProcSetSelectionOwner_Done;
    }

  /* Abort if no window at this point */
  if (None == stuff->window)
    {
#if 0
      ErrorF ("winProcSetSelectionOwner - No window, returning.\n");
#endif
      goto winProcSetSelectionOwner_Done;
    }

  /* Abort if invalid selection */
  if (!ValidAtom (stuff->selection))
    {
      ErrorF ("winProcSetSelectionOwner - Found BadAtom, aborting.\n");
      goto winProcSetSelectionOwner_Done;
    }

  /* Cast Window to Drawable */
  pDrawable = (DrawablePtr) pWindow;
  
  /* Abort if clipboard manager is owning the selection */
  if (pDrawable->id == g_iClipboardWindow)
    {
#if 0
      ErrorF ("winProcSetSelectionOwner - We changed ownership, "
	      "aborting.\n");
#endif
      goto winProcSetSelectionOwner_Done;
    }

  /* Abort if root window is taking ownership */
  if (pDrawable->id == 0)
    {
      ErrorF ("winProcSetSelectionOwner - Root window taking ownership, "
	      "aborting\n");
      goto winProcSetSelectionOwner_Done;
    }

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

  /* Access the Windows clipboard */
  if (!OpenClipboard (g_hwndClipboard))
    {
      ErrorF ("winProcSetSelectionOwner - OpenClipboard () failed: %08x\n",
	      (int) GetLastError ());
      goto winProcSetSelectionOwner_Done;
    }

  /* Take ownership of the Windows clipboard */
  if (!EmptyClipboard ())
    {
      ErrorF ("winProcSetSelectionOwner - EmptyClipboard () failed: %08x\n",
	      (int) GetLastError ());
      goto winProcSetSelectionOwner_Done;
    }

  /* Advertise Unicode if we support it */
  if (g_fUnicodeSupport)
    SetClipboardData (CF_UNICODETEXT, NULL);

  /* Always advertise regular text */
  SetClipboardData (CF_TEXT, NULL);

  /* Save handle to last owned selection */
  g_atomLastOwnedSelection = stuff->selection;

  /* Release the clipboard */
  if (!CloseClipboard ())
    {
      ErrorF ("winProcSetSelectionOwner - CloseClipboard () failed: "
	      "%08x\n",
	      (int) GetLastError ());
      goto winProcSetSelectionOwner_Done;
    }

 winProcSetSelectionOwner_Done:
  return (*winProcSetSelectionOwnerOrig) (client);
}
int
winClipboardFlushXEvents (HWND hwnd,
			  int iWindow,
			  Display *pDisplay,
			  Bool fUseUnicode)
{
  static Atom atomLocalProperty;
  static Atom atomCompoundText;
  static Atom atomUTF8String;
  static Atom atomTargets;
  static int generation;

  if (generation != serverGeneration)
    {
      generation = serverGeneration;
      atomLocalProperty = XInternAtom (pDisplay, WIN_LOCAL_PROPERTY, False);
      atomUTF8String = XInternAtom (pDisplay, "UTF8_STRING", False);
      atomCompoundText = XInternAtom (pDisplay, "COMPOUND_TEXT", False);
      atomTargets = XInternAtom (pDisplay, "TARGETS", False);
    }

  /* Process all pending events */
  while (XPending (pDisplay))
    {
      XTextProperty		xtpText = {0};
      XEvent			event;
      XSelectionEvent		eventSelection;
      unsigned long		ulReturnBytesLeft;
      char			*pszReturnData = NULL;
      char			*pszGlobalData = NULL;
      int			iReturn;
      HGLOBAL			hGlobal = NULL;
      XICCEncodingStyle		xiccesStyle;
      int			iConvertDataLen = 0;
      char			*pszConvertData = NULL;
      char			*pszTextList[2] = {NULL};
      int			iCount;
      char			**ppszTextList = NULL;
      wchar_t			*pwszUnicodeStr = NULL;
      int			iUnicodeLen = 0;
      int			iReturnDataLen = 0;
      int			i;
      Bool			fAbort = FALSE;
      Bool			fCloseClipboard = FALSE;
      Bool			fSetClipboardData = TRUE;

      /* Get the next event - will not block because one is ready */
      XNextEvent (pDisplay, &event);

      /* Branch on the event type */
      switch (event.type)
	{
	  /*
	   * SelectionRequest
	   */

	case SelectionRequest:
	  {
	    char			*pszAtomName = NULL;
	    winDebug("SelectionRequest - target %d\n",
                     event.xselectionrequest.target);

	    pszAtomName = XGetAtomName (pDisplay,
					event.xselectionrequest.target);
	    winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
	    XFree (pszAtomName);
	    pszAtomName = NULL;
	  }

	  /* Abort if invalid target type */
	  if (event.xselectionrequest.target != XA_STRING
	      && event.xselectionrequest.target != atomUTF8String
	      && event.xselectionrequest.target != atomCompoundText
	      && event.xselectionrequest.target != atomTargets)
	    {
	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Handle targets type of request */
	  if (event.xselectionrequest.target == atomTargets)
	    {
	      Atom atomTargetArr[] = {atomTargets,
				      atomCompoundText,
				      atomUTF8String,
				      XA_STRING};

	      /* Try to change the property */
	      iReturn = XChangeProperty (pDisplay,
					 event.xselectionrequest.requestor,
					 event.xselectionrequest.property,
					 XA_ATOM,
					 32,
					 PropModeReplace,
					 (unsigned char *) atomTargetArr,
					 (sizeof (atomTargetArr)
					  / sizeof (atomTargetArr[0])));
	      if (iReturn == BadAlloc
		  || iReturn == BadAtom
		  || iReturn == BadMatch
		  || iReturn == BadValue
		  || iReturn == BadWindow)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XChangeProperty failed: %d\n",
			  iReturn);
		}

	      /* Setup selection notify xevent */
	      eventSelection.type	= SelectionNotify;
	      eventSelection.send_event	= True;
	      eventSelection.display	= pDisplay;
	      eventSelection.requestor	= event.xselectionrequest.requestor;
	      eventSelection.selection	= event.xselectionrequest.selection;
	      eventSelection.target	= event.xselectionrequest.target;
	      eventSelection.property	= event.xselectionrequest.property;
	      eventSelection.time	= event.xselectionrequest.time;

	      /*
	       * Notify the requesting window that
	       * the operation has completed
	       */
	      iReturn = XSendEvent (pDisplay,
				    eventSelection.requestor,
				    False,
				    0L,
				    (XEvent *) &eventSelection);
	      if (iReturn == BadValue || iReturn == BadWindow)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XSendEvent () failed\n");
		}
	      break;
	    }

	  /* Check that clipboard format is available */
	  if (fUseUnicode
	      && !IsClipboardFormatAvailable (CF_UNICODETEXT))
	    {
	      static int count; /* Hack to stop acroread spamming the log */
	      static HWND lasthwnd; /* I've not seen any other client get here repeatedly? */
	      if (hwnd != lasthwnd) count = 0;
	      count++;
	      if (count < 6) ErrorF ("winClipboardFlushXEvents - CF_UNICODETEXT is not "
		      "available from Win32 clipboard.  Aborting %d.\n", count);
	      lasthwnd = hwnd;

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  else if (!fUseUnicode
		   && !IsClipboardFormatAvailable (CF_TEXT))
	    {
	      ErrorF ("winClipboardFlushXEvents - CF_TEXT is not "
		      "available from Win32 clipboard.  Aborting.\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

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

	  /* Access the clipboard */
	  if (!OpenClipboard (hwnd))
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "OpenClipboard () failed: %08lx\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  
	  /* Indicate that clipboard was opened */
	  fCloseClipboard = TRUE;

	  /* Setup the string style */
	  if (event.xselectionrequest.target == XA_STRING)
	    xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
	  else if (event.xselectionrequest.target == atomUTF8String)
	    xiccesStyle = XUTF8StringStyle;
#endif
	  else if (event.xselectionrequest.target == atomCompoundText)
	    xiccesStyle = XCompoundTextStyle;
	  else
	    xiccesStyle = XStringStyle;

	  /*
	   * FIXME: Can't pass CF_UNICODETEXT on Windows 95/98/Me
	   */
	  
	  /* Get a pointer to the clipboard text, in desired format */
	  if (fUseUnicode)
	    {
	      /* Retrieve clipboard data */
	      hGlobal = GetClipboardData (CF_UNICODETEXT);
	    }
	  else
	    {
	      /* Retrieve clipboard data */
	      hGlobal = GetClipboardData (CF_TEXT);
	    }
	  if (!hGlobal)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "GetClipboardData () failed: %08lx\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  pszGlobalData = (char *) GlobalLock (hGlobal);

	  /* Convert the Unicode string to UTF8 (MBCS) */
	  if (fUseUnicode)
	    {
	      iConvertDataLen = WideCharToMultiByte (CP_UTF8,
						     0,
						     (LPCWSTR)pszGlobalData,
						     -1,
						     NULL,
						     0,
						     NULL,
						     NULL);
	      /* NOTE: iConvertDataLen includes space for null terminator */
	      pszConvertData = (char *) malloc (iConvertDataLen);
	      WideCharToMultiByte (CP_UTF8,
				   0,
				   (LPCWSTR)pszGlobalData,
				   -1,
				   pszConvertData,
				   iConvertDataLen,
				   NULL,
				   NULL);
	    }
	  else
	    {
	      pszConvertData = strdup (pszGlobalData);
	      iConvertDataLen = strlen (pszConvertData) + 1;
	    }

	  /* Convert DOS string to UNIX string */
	  winClipboardDOStoUNIX (pszConvertData, strlen (pszConvertData));

	  /* Setup our text list */
	  pszTextList[0] = pszConvertData;
	  pszTextList[1] = NULL;

	  /* Initialize the text property */
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Create the text property from the text list */
	  if (fUseUnicode)
	    {
#ifdef X_HAVE_UTF8_STRING
	      iReturn = Xutf8TextListToTextProperty (pDisplay,
						     pszTextList,
						     1,
						     xiccesStyle,
						     &xtpText);
#endif
	    }
	  else
	    {
	      iReturn = XmbTextListToTextProperty (pDisplay,
						   pszTextList,
						   1,
						   xiccesStyle,
						   &xtpText);
	    }
	  if (iReturn == XNoMemory || iReturn == XLocaleNotSupported)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "X*TextListToTextProperty failed: %d\n",
		      iReturn);

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }
	  
	  /* Free the converted string */
	  free (pszConvertData);
	  pszConvertData = NULL;

	  /* Copy the clipboard text to the requesting window */
	  iReturn = XChangeProperty (pDisplay,
				     event.xselectionrequest.requestor,
				     event.xselectionrequest.property,
				     event.xselectionrequest.target,
				     8,
				     PropModeReplace,
				     xtpText.value,
				     xtpText.nitems);
	  if (iReturn == BadAlloc || iReturn == BadAtom
	      || iReturn == BadMatch || iReturn == BadValue
	      || iReturn == BadWindow)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "XChangeProperty failed: %d\n",
		      iReturn);

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	  /* Release the clipboard data */
	  GlobalUnlock (hGlobal);
	  pszGlobalData = NULL;
	  fCloseClipboard = FALSE;
	  CloseClipboard ();

	  /* Clean up */
	  XFree (xtpText.value);
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Setup selection notify event */
	  eventSelection.type = SelectionNotify;
	  eventSelection.send_event = True;
	  eventSelection.display = pDisplay;
	  eventSelection.requestor = event.xselectionrequest.requestor;
	  eventSelection.selection = event.xselectionrequest.selection;
	  eventSelection.target = event.xselectionrequest.target;
	  eventSelection.property = event.xselectionrequest.property;
	  eventSelection.time = event.xselectionrequest.time;

	  /* Notify the requesting window that the operation has completed */
	  iReturn = XSendEvent (pDisplay,
				eventSelection.requestor,
				False,
				0L,
				(XEvent *) &eventSelection);
	  if (iReturn == BadValue || iReturn == BadWindow)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
		      "XSendEvent () failed\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionRequest_Done;
	    }

	winClipboardFlushXEvents_SelectionRequest_Done:
	  /* Free allocated resources */
	  if (xtpText.value)
	  {
	    XFree (xtpText.value);
	    xtpText.value = NULL;
	    xtpText.nitems = 0;
	  }
	  free(pszConvertData);
	  if (hGlobal && pszGlobalData)
	    GlobalUnlock (hGlobal);
	  
	  /*
	   * Send a SelectionNotify event to the requesting
	   * client when we abort.
	   */
	  if (fAbort)
	    {
	      /* Setup selection notify event */
	      eventSelection.type = SelectionNotify;
	      eventSelection.send_event = True;
	      eventSelection.display = pDisplay;
	      eventSelection.requestor = event.xselectionrequest.requestor;
	      eventSelection.selection = event.xselectionrequest.selection;
	      eventSelection.target = event.xselectionrequest.target;
	      eventSelection.property = None;
	      eventSelection.time = event.xselectionrequest.time;

	      /* Notify the requesting window that the operation is complete */
	      iReturn = XSendEvent (pDisplay,
				    eventSelection.requestor,
				    False,
				    0L,
				    (XEvent *) &eventSelection);
	      if (iReturn == BadValue || iReturn == BadWindow)
		{
		  /*
		   * Should not be a problem if XSendEvent fails because
		   * the client may simply have exited.
		   */
		  ErrorF ("winClipboardFlushXEvents - SelectionRequest - "
			  "XSendEvent () failed for abort event.\n");
		}
	    }

	  /* Close clipboard if it was opened */
	  if (fCloseClipboard)
	  {
	    fCloseClipboard = FALSE;
	    CloseClipboard ();
	  }
	  break;


	  /*
	   * SelectionNotify
	   */ 

	case SelectionNotify:

	  winDebug ("winClipboardFlushXEvents - SelectionNotify\n");
	  {
	    char		*pszAtomName;
	    pszAtomName = XGetAtomName (pDisplay,
					event.xselection.selection);

	    winDebug("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
                     pszAtomName);
	    XFree (pszAtomName);
	  }

	  /*
	   * Request conversion of UTF8 and CompoundText targets.
	   */
	  if (event.xselection.property == None)
	    {
	      if (event.xselection.target == XA_STRING)
		{
		  winDebug ("winClipboardFlushXEvents - SelectionNotify - "
                            "XA_STRING\n");

		  return WIN_XEVENTS_CONVERT;
		}
	      else if (event.xselection.target == atomUTF8String)
		{
		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
                           "Requesting conversion of UTF8 target.\n");

		  XConvertSelection (pDisplay,
				     event.xselection.selection,
				     XA_STRING,
				     atomLocalProperty,
				     iWindow,
				     CurrentTime);

		  /* Process the ConvertSelection event */
		  XFlush (pDisplay);
		  return WIN_XEVENTS_CONVERT;
		}
#ifdef X_HAVE_UTF8_STRING
	      else if (event.xselection.target == atomCompoundText)
		{
		  winDebug("winClipboardFlushXEvents - SelectionNotify - "
                           "Requesting conversion of CompoundText target.\n");

		  XConvertSelection (pDisplay,
				     event.xselection.selection,
				     atomUTF8String,
				     atomLocalProperty,
				     iWindow,
				     CurrentTime);

		  /* Process the ConvertSelection event */
		  XFlush (pDisplay);
		  return WIN_XEVENTS_CONVERT;
		}
#endif
	      else
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
			  "Unknown format.  Cannot request conversion, "
			  "aborting.\n");
		  break;
		}
	    }

	  /* Retrieve the size of the stored data */
	  iReturn = XGetWindowProperty (pDisplay,
					iWindow,
					atomLocalProperty,
					0,
					0, /* Don't get data, just size */
					False,
					AnyPropertyType,
					&xtpText.encoding,
					&xtpText.format,
					&xtpText.nitems,
					&ulReturnBytesLeft,
					&xtpText.value);
	  if (iReturn != Success)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "XGetWindowProperty () failed, aborting: %d\n",
		      iReturn);
	      break;
	    }

	  winDebug("SelectionNotify - returned data %d left %d\n",
                   xtpText.nitems, ulReturnBytesLeft);

	  /* Request the selection data */
	  iReturn = XGetWindowProperty (pDisplay,
					iWindow,
					atomLocalProperty,
					0,
					ulReturnBytesLeft,
					False,
					AnyPropertyType,
					&xtpText.encoding,
					&xtpText.format,
					&xtpText.nitems,
					&ulReturnBytesLeft,
					&xtpText.value);
	  if (iReturn != Success)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "XGetWindowProperty () failed, aborting: %d\n",
		      iReturn);
	      break;
	    }

	    {
	      char		*pszAtomName = NULL;

	      winDebug("SelectionNotify - returned data %d left %d\n",
                       xtpText.nitems, ulReturnBytesLeft);
	      pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
	      winDebug("Notify atom name %s\n", pszAtomName);
	      XFree (pszAtomName);
	      pszAtomName = NULL;
	    }

	  if (fUseUnicode)
	    {
#ifdef X_HAVE_UTF8_STRING
	      /* Convert the text property to a text list */
	      iReturn = Xutf8TextPropertyToTextList (pDisplay,
						     &xtpText,
						     &ppszTextList,
						     &iCount);
#endif
	    }
	  else
	    {
	      iReturn = XmbTextPropertyToTextList (pDisplay,
						   &xtpText,
						   &ppszTextList,
						   &iCount);
	    }
	  if (iReturn == Success || iReturn > 0)
	    {
	      /* Conversion succeeded or some unconvertible characters */
	      if (ppszTextList != NULL)
		{
		  iReturnDataLen = 0;
		  for (i = 0; i < iCount; i++)
		    {
		      iReturnDataLen += strlen(ppszTextList[i]);
		    }
		  pszReturnData = malloc (iReturnDataLen + 1);
		  pszReturnData[0] = '\0';
		  for (i = 0; i < iCount; i++)
		    {
		      strcat (pszReturnData, ppszTextList[i]);
		    }
		}
	      else
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
			  "X*TextPropertyToTextList list_return is NULL.\n");
		  pszReturnData = malloc (1);
		  pszReturnData[0] = '\0';
		}
	    }
	  else
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify - "
		      "X*TextPropertyToTextList returned: ");
	      switch (iReturn)
		{
		case XNoMemory:
		  ErrorF ("XNoMemory\n");
		  break;
		case XConverterNotFound:
		  ErrorF ("XConverterNotFound\n");
		  break;
		default:
		  ErrorF ("%d", iReturn);
		  break;
		}
	      pszReturnData = malloc (1);
	      pszReturnData[0] = '\0';
	    }

	  /* Free the data returned from XGetWindowProperty */
	  if (ppszTextList)
	    XFreeStringList (ppszTextList);
	  ppszTextList = NULL;
	  XFree (xtpText.value);
	  xtpText.value = NULL;
	  xtpText.nitems = 0;

	  /* Convert the X clipboard string to DOS format */
	  winClipboardUNIXtoDOS (&pszReturnData, strlen (pszReturnData));

	  if (fUseUnicode)
	    {
	      /* Find out how much space needed to convert MBCS to Unicode */
	      iUnicodeLen = MultiByteToWideChar (CP_UTF8,
						 0,
						 pszReturnData,
						 -1,
						 NULL,
						 0);

	      /* Allocate memory for the Unicode string */
	      pwszUnicodeStr
		= (wchar_t*) malloc (sizeof (wchar_t) * (iUnicodeLen + 1));
	      if (!pwszUnicodeStr)
		{
		  ErrorF ("winClipboardFlushXEvents - SelectionNotify "
			  "malloc failed for pwszUnicodeStr, aborting.\n");

		  /* Abort */
		  fAbort = TRUE;
		  goto winClipboardFlushXEvents_SelectionNotify_Done;
		}

	      /* Do the actual conversion */
	      MultiByteToWideChar (CP_UTF8,
				   0,
				   pszReturnData,
				   -1,
				   pwszUnicodeStr,
				   iUnicodeLen);
	      
	      /* Allocate global memory for the X clipboard data */
	      hGlobal = GlobalAlloc (GMEM_MOVEABLE,
				     sizeof (wchar_t) * (iUnicodeLen + 1));
	    }
	  else
	    {
	      pszConvertData = strdup (pszReturnData);
	      iConvertDataLen = strlen (pszConvertData) + 1;

	      /* Allocate global memory for the X clipboard data */
	      hGlobal = GlobalAlloc (GMEM_MOVEABLE, iConvertDataLen);
	    }

	  free (pszReturnData);

	  /* Check that global memory was allocated */
	  if (!hGlobal)
	    {
	      ErrorF ("winClipboardFlushXEvents - SelectionNotify "
		      "GlobalAlloc failed, aborting: %ld\n",
		      GetLastError ());

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionNotify_Done;
	    }

	  /* Obtain a pointer to the global memory */
	  pszGlobalData = GlobalLock (hGlobal);
	  if (pszGlobalData == NULL)
	    {
	      ErrorF ("winClipboardFlushXEvents - Could not lock global "
		      "memory for clipboard transfer\n");

	      /* Abort */
	      fAbort = TRUE;
	      goto winClipboardFlushXEvents_SelectionNotify_Done;
	    }

	  /* Copy the returned string into the global memory */
	  if (fUseUnicode)
	    {
	      memcpy (pszGlobalData,
		      pwszUnicodeStr,
		      sizeof (wchar_t) * (iUnicodeLen + 1));
	      free (pwszUnicodeStr);
	      pwszUnicodeStr = NULL;
	    }
	  else
	    {
	      strcpy (pszGlobalData, pszConvertData);
	      free (pszConvertData);
	      pszConvertData = NULL;
	    }

	  /* Release the pointer to the global memory */
	  GlobalUnlock (hGlobal);
	  pszGlobalData = NULL;

	  /* Push the selection data to the Windows clipboard */
	  if (fUseUnicode)
	    SetClipboardData (CF_UNICODETEXT, hGlobal);
	  else
	    SetClipboardData (CF_TEXT, hGlobal);

	  /* Flag that SetClipboardData has been called */
	  fSetClipboardData = FALSE;

	  /*
	   * NOTE: Do not try to free pszGlobalData, it is owned by
	   * Windows after the call to SetClipboardData ().
	   */

	winClipboardFlushXEvents_SelectionNotify_Done:
	  /* Free allocated resources */
	  if (ppszTextList)
	    XFreeStringList (ppszTextList);
	  if (xtpText.value)
	  {
	    XFree (xtpText.value);
	    xtpText.value = NULL;
	    xtpText.nitems = 0;
	  }
	  free(pszConvertData);
	  free(pwszUnicodeStr);
	  if (hGlobal && pszGlobalData)
	    GlobalUnlock (hGlobal);
	  if (fSetClipboardData && g_fUnicodeSupport)
	    SetClipboardData (CF_UNICODETEXT, NULL);
	  if (fSetClipboardData)
	    SetClipboardData (CF_TEXT, NULL);
	  return WIN_XEVENTS_NOTIFY;

        case SelectionClear:
          winDebug("SelectionClear - doing nothing\n");
          break;

	case PropertyNotify:
	  break;

	case MappingNotify:
	  break;

	default:
          ErrorF ("winClipboardFlushXEvents - unexpected event type %d\n", event.type);
	  break;
	}
    }

  return WIN_XEVENTS_SUCCESS;
}
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 fastPoll( void )
	{
	static BOOLEAN addedFixedItems = FALSE, hasHardwareRNG = FALSE;
	static CEGENRANDOM pCeGenRandom = NULL;
	static GETSYSTEMPOWERSTATUS pGetSystemPowerStatusEx2 = NULL;
	FILETIME  creationTime, exitTime, kernelTime, userTime;
	LARGE_INTEGER performanceCount;
	SYSTEM_POWER_STATUS_EX2 powerStatus;
	MEMORYSTATUS memoryStatus;
	HANDLE handle;
	POINT point;
	RANDOM_STATE randomState;
	BYTE buffer[ RANDOM_BUFSIZE ];
	int length;

	if( krnlIsExiting() )
		return;

	/* Initialize the native function pointers if necessary.  CeGetRandom()
	   is only available in relatively new versions of WinCE, so we have to
	   link it dynamically */
	if( pCeGenRandom == NULL )
		{
		HANDLE hCoreDLL;

		if( ( hCoreDLL = GetModuleHandle( TEXT( "Coredll.dll" ) ) ) != NULL )
			pCeGenRandom = ( CEGENRANDOM ) GetProcAddress( hCoreDLL, TEXT( "CeGenRandom" ) );
		}
	if( pGetSystemPowerStatusEx2 == NULL )
		{
		HANDLE hGetpower;

		if( ( hGetpower = GetModuleHandle( TEXT( "Getpower.dll" ) ) ) != NULL )
			pGetSystemPowerStatusEx2 = ( GETSYSTEMPOWERSTATUS ) \
							GetProcAddress( hGetpower, TEXT( "GetSystemPowerStatusEx2" ) );
		}

	initRandomData( randomState, buffer, RANDOM_BUFSIZE );

	/* 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 */
	addRandomValue( randomState, GetActiveWindow() );
	addRandomValue( randomState, GetCapture() );
	addRandomValue( randomState, GetCaretBlinkTime() );
	addRandomValue( randomState, GetClipboardOwner() );
	addRandomValue( randomState, GetCurrentProcess() );
	addRandomValue( randomState, GetCurrentProcessId() );
	addRandomValue( randomState, GetCurrentThread() );
	addRandomValue( randomState, GetCurrentThreadId() );
	addRandomValue( randomState, GetDesktopWindow() );
	addRandomValue( randomState, GetDC( NULL ) );
	addRandomValue( randomState, GetDoubleClickTime() );
	addRandomValue( randomState, GetFocus() );
	addRandomValue( randomState, GetForegroundWindow() );
	addRandomValue( randomState, GetMessagePos() );
	addRandomValue( randomState, GetOpenClipboardWindow() );
	addRandomValue( randomState, GetProcessHeap() );
	addRandomValue( randomState, GetQueueStatus( QS_ALLINPUT ) );
	addRandomValue( randomState, GetTickCount() );
	if( krnlIsExiting() )
		return;

	/* Get multiword system information: Current caret position, current
	   mouse cursor position */
	GetCaretPos( &point );
	addRandomData( randomState, &point, sizeof( POINT ) );
	GetCursorPos( &point );
	addRandomData( randomState, &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 );
	addRandomData( randomState, &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 );
	addRandomData( randomState, &creationTime, sizeof( FILETIME ) );
	addRandomData( randomState, &exitTime, sizeof( FILETIME ) );
	addRandomData( randomState, &kernelTime, sizeof( FILETIME ) );
	addRandomData( randomState, &userTime, sizeof( FILETIME ) );

	/* Get extended battery/power status information.  We set the fUpdate
	   flag to force a re-read of fresh data rather than a re-use of cached
	   information */
	if( pGetSystemPowerStatusEx2 != NULL && \
		( length = \
				pGetSystemPowerStatusEx2( &powerStatus,
										  sizeof( SYSTEM_POWER_STATUS_EX2 ),
										  TRUE ) ) > 0 )
		addRandomData( randomState, &powerStatus, length );

	/* Get random data provided by the OS.  Since this is expected to be
	   provided by the system vendor, it's quite likely to be the usual
	   process ID + time */
	if( pCeGenRandom != NULL )
		{
		BYTE randomBuffer[ 32 ];

		if( pCeGenRandom( 32, randomBuffer ) )
			addRandomData( randomState, randomBuffer, 32 );
		}

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

		GetSystemInfo( &systemInfo );
		addRandomData( randomState, &systemInfo, sizeof( SYSTEM_INFO ) );
		addedFixedItems = TRUE;
		}

	/* The performance of QPC varies depending on the architecture it's
	   running on, and is completely platform-dependant.  If there's no
	   hardware performance counter available, it uses the 1ms system timer,
	   although usually there's some form of hardware timer available.
	   Since there may be no correlation, or only a weak correlation,
	   between the performance counter and the system clock, we get the
	   time from both sources */
	if( QueryPerformanceCounter( &performanceCount ) )
		addRandomData( randomState, &performanceCount,
					   sizeof( LARGE_INTEGER ) );
	addRandomValue( randomState, GetTickCount() );

	/* Flush any remaining data through.  Quality = int( 33 1/3 % ) */
	endRandomData( randomState, 34 );
	}
Example #9
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);
}
Example #10
0
int
winClipboardFlushXEvents(HWND hwnd,
                         Window iWindow, Display * pDisplay, ClipboardConversionData *data, ClipboardAtoms *atoms)
{
    Atom atomClipboard = atoms->atomClipboard;
    Atom atomLocalProperty = atoms->atomLocalProperty;
    Atom atomUTF8String = atoms->atomUTF8String;
    Atom atomCompoundText = atoms->atomCompoundText;
    Atom atomTargets = atoms->atomTargets;

    /* Process all pending events */
    while (XPending(pDisplay)) {
        XTextProperty xtpText = { 0 };
        XEvent event;
        XSelectionEvent eventSelection;
        unsigned long ulReturnBytesLeft;
        char *pszReturnData = NULL;
        char *pszGlobalData = NULL;
        int iReturn;
        HGLOBAL hGlobal = NULL;
        XICCEncodingStyle xiccesStyle;
        char *pszConvertData = NULL;
        char *pszTextList[2] = { NULL };
        int iCount;
        char **ppszTextList = NULL;
        wchar_t *pwszUnicodeStr = NULL;
        Bool fAbort = FALSE;
        Bool fCloseClipboard = FALSE;
        Bool fSetClipboardData = TRUE;

        /* Get the next event - will not block because one is ready */
        XNextEvent(pDisplay, &event);

        /* Branch on the event type */
        switch (event.type) {
            /*
             * SelectionRequest
             */

        case SelectionRequest:
        {
            char *pszAtomName = NULL;

            winDebug("SelectionRequest - target %ld\n",
                     event.xselectionrequest.target);

            pszAtomName = XGetAtomName(pDisplay,
                                       event.xselectionrequest.target);
            winDebug("SelectionRequest - Target atom name %s\n", pszAtomName);
            XFree(pszAtomName);
            pszAtomName = NULL;
        }

            /* Abort if invalid target type */
            if (event.xselectionrequest.target != XA_STRING
                && event.xselectionrequest.target != atomUTF8String
                && event.xselectionrequest.target != atomCompoundText
                && event.xselectionrequest.target != atomTargets) {
                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Handle targets type of request */
            if (event.xselectionrequest.target == atomTargets) {
                Atom atomTargetArr[] = { atomTargets,
                    atomCompoundText,
                    atomUTF8String,
                    XA_STRING
                };

                /* Try to change the property */
                iReturn = XChangeProperty(pDisplay,
                                          event.xselectionrequest.requestor,
                                          event.xselectionrequest.property,
                                          XA_ATOM,
                                          32,
                                          PropModeReplace,
                                          (unsigned char *) atomTargetArr,
                                          ARRAY_SIZE(atomTargetArr));
                if (iReturn == BadAlloc
                    || iReturn == BadAtom
                    || iReturn == BadMatch
                    || iReturn == BadValue || iReturn == BadWindow) {
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XChangeProperty failed: %d\n", iReturn);
                }

                /* Setup selection notify xevent */
                eventSelection.type = SelectionNotify;
                eventSelection.send_event = True;
                eventSelection.display = pDisplay;
                eventSelection.requestor = event.xselectionrequest.requestor;
                eventSelection.selection = event.xselectionrequest.selection;
                eventSelection.target = event.xselectionrequest.target;
                eventSelection.property = event.xselectionrequest.property;
                eventSelection.time = event.xselectionrequest.time;

                /*
                 * Notify the requesting window that
                 * the operation has completed
                 */
                iReturn = XSendEvent(pDisplay,
                                     eventSelection.requestor,
                                     False, 0L, (XEvent *) &eventSelection);
                if (iReturn == BadValue || iReturn == BadWindow) {
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XSendEvent () failed\n");
                }
                break;
            }

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

            /* Access the clipboard */
            if (!OpenClipboard(hwnd)) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "OpenClipboard () failed: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Indicate that clipboard was opened */
            fCloseClipboard = TRUE;

            /* Check that clipboard format is available */
            if (data->fUseUnicode && !IsClipboardFormatAvailable(CF_UNICODETEXT)) {
                static int count;       /* Hack to stop acroread spamming the log */
                static HWND lasthwnd;   /* I've not seen any other client get here repeatedly? */

                if (hwnd != lasthwnd)
                    count = 0;
                count++;
                if (count < 6)
                    ErrorF("winClipboardFlushXEvents - CF_UNICODETEXT is not "
                           "available from Win32 clipboard.  Aborting %d.\n",
                           count);
                lasthwnd = hwnd;

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }
            else if (!data->fUseUnicode && !IsClipboardFormatAvailable(CF_TEXT)) {
                ErrorF("winClipboardFlushXEvents - CF_TEXT is not "
                       "available from Win32 clipboard.  Aborting.\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Setup the string style */
            if (event.xselectionrequest.target == XA_STRING)
                xiccesStyle = XStringStyle;
#ifdef X_HAVE_UTF8_STRING
            else if (event.xselectionrequest.target == atomUTF8String)
                xiccesStyle = XUTF8StringStyle;
#endif
            else if (event.xselectionrequest.target == atomCompoundText)
                xiccesStyle = XCompoundTextStyle;
            else
                xiccesStyle = XStringStyle;

            /* Get a pointer to the clipboard text, in desired format */
            if (data->fUseUnicode) {
                /* Retrieve clipboard data */
                hGlobal = GetClipboardData(CF_UNICODETEXT);
            }
            else {
                /* Retrieve clipboard data */
                hGlobal = GetClipboardData(CF_TEXT);
            }
            if (!hGlobal) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "GetClipboardData () failed: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }
            pszGlobalData = (char *) GlobalLock(hGlobal);

            /* Convert the Unicode string to UTF8 (MBCS) */
            if (data->fUseUnicode) {
                int iConvertDataLen = WideCharToMultiByte(CP_UTF8,
                                                      0,
                                                      (LPCWSTR) pszGlobalData,
                                                      -1, NULL, 0, NULL, NULL);
                /* NOTE: iConvertDataLen includes space for null terminator */
                pszConvertData = malloc(iConvertDataLen);
                WideCharToMultiByte(CP_UTF8,
                                    0,
                                    (LPCWSTR) pszGlobalData,
                                    -1,
                                    pszConvertData,
                                    iConvertDataLen, NULL, NULL);
            }
            else {
                pszConvertData = strdup(pszGlobalData);
            }

            /* Convert DOS string to UNIX string */
            winClipboardDOStoUNIX(pszConvertData, strlen(pszConvertData));

            /* Setup our text list */
            pszTextList[0] = pszConvertData;
            pszTextList[1] = NULL;

            /* Initialize the text property */
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Create the text property from the text list */
            if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
                iReturn = Xutf8TextListToTextProperty(pDisplay,
                                                      pszTextList,
                                                      1, xiccesStyle, &xtpText);
#endif
            }
            else {
                iReturn = XmbTextListToTextProperty(pDisplay,
                                                    pszTextList,
                                                    1, xiccesStyle, &xtpText);
            }
            if (iReturn == XNoMemory || iReturn == XLocaleNotSupported) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "X*TextListToTextProperty failed: %d\n", iReturn);

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Free the converted string */
            free(pszConvertData);
            pszConvertData = NULL;

            /* Copy the clipboard text to the requesting window */
            iReturn = XChangeProperty(pDisplay,
                                      event.xselectionrequest.requestor,
                                      event.xselectionrequest.property,
                                      event.xselectionrequest.target,
                                      8,
                                      PropModeReplace,
                                      xtpText.value, xtpText.nitems);
            if (iReturn == BadAlloc || iReturn == BadAtom
                || iReturn == BadMatch || iReturn == BadValue
                || iReturn == BadWindow) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "XChangeProperty failed: %d\n", iReturn);

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

            /* Release the clipboard data */
            GlobalUnlock(hGlobal);
            pszGlobalData = NULL;
            fCloseClipboard = FALSE;
            CloseClipboard();

            /* Clean up */
            XFree(xtpText.value);
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Setup selection notify event */
            eventSelection.type = SelectionNotify;
            eventSelection.send_event = True;
            eventSelection.display = pDisplay;
            eventSelection.requestor = event.xselectionrequest.requestor;
            eventSelection.selection = event.xselectionrequest.selection;
            eventSelection.target = event.xselectionrequest.target;
            eventSelection.property = event.xselectionrequest.property;
            eventSelection.time = event.xselectionrequest.time;

            /* Notify the requesting window that the operation has completed */
            iReturn = XSendEvent(pDisplay,
                                 eventSelection.requestor,
                                 False, 0L, (XEvent *) &eventSelection);
            if (iReturn == BadValue || iReturn == BadWindow) {
                ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                       "XSendEvent () failed\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionRequest_Done;
            }

 winClipboardFlushXEvents_SelectionRequest_Done:
            /* Free allocated resources */
            if (xtpText.value) {
                XFree(xtpText.value);
                xtpText.value = NULL;
                xtpText.nitems = 0;
            }
            free(pszConvertData);
            if (hGlobal && pszGlobalData)
                GlobalUnlock(hGlobal);

            /*
             * Send a SelectionNotify event to the requesting
             * client when we abort.
             */
            if (fAbort) {
                /* Setup selection notify event */
                eventSelection.type = SelectionNotify;
                eventSelection.send_event = True;
                eventSelection.display = pDisplay;
                eventSelection.requestor = event.xselectionrequest.requestor;
                eventSelection.selection = event.xselectionrequest.selection;
                eventSelection.target = event.xselectionrequest.target;
                eventSelection.property = None;
                eventSelection.time = event.xselectionrequest.time;

                /* Notify the requesting window that the operation is complete */
                iReturn = XSendEvent(pDisplay,
                                     eventSelection.requestor,
                                     False, 0L, (XEvent *) &eventSelection);
                if (iReturn == BadValue || iReturn == BadWindow) {
                    /*
                     * Should not be a problem if XSendEvent fails because
                     * the client may simply have exited.
                     */
                    ErrorF("winClipboardFlushXEvents - SelectionRequest - "
                           "XSendEvent () failed for abort event.\n");
                }
            }

            /* Close clipboard if it was opened */
            if (fCloseClipboard) {
                fCloseClipboard = FALSE;
                CloseClipboard();
            }
            break;

            /*
             * SelectionNotify
             */

        case SelectionNotify:
            winDebug("winClipboardFlushXEvents - SelectionNotify\n");
            {
                char *pszAtomName;

                pszAtomName = XGetAtomName(pDisplay,
                                           event.xselection.selection);

                winDebug
                    ("winClipboardFlushXEvents - SelectionNotify - ATOM: %s\n",
                     pszAtomName);
                XFree(pszAtomName);
            }

            /*
              SelectionNotify with property of None indicates either:

              (i) Generated by the X server if no owner for the specified selection exists
                  (perhaps it's disappeared on us mid-transaction), or
              (ii) Sent by the selection owner when the requested selection conversion could
                   not be performed or server errors prevented the conversion data being returned
            */
            if (event.xselection.property == None) {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                           "Conversion to format %ld refused.\n",
                           event.xselection.target);
                    return WIN_XEVENTS_FAILED;
                }

            if (event.xselection.target == atomTargets) {
              return winClipboardSelectionNotifyTargets(hwnd, iWindow, pDisplay, data, atoms);
            }

            /* Retrieve the selection data and delete the property */
            iReturn = XGetWindowProperty(pDisplay,
                                         iWindow,
                                         atomLocalProperty,
                                         0,
                                         INT_MAX,
                                         True,
                                         AnyPropertyType,
                                         &xtpText.encoding,
                                         &xtpText.format,
                                         &xtpText.nitems,
                                         &ulReturnBytesLeft, &xtpText.value);
            if (iReturn != Success) {
                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                       "XGetWindowProperty () failed, aborting: %d\n", iReturn);
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            {
                char *pszAtomName = NULL;

                winDebug("SelectionNotify - returned data %lu left %lu\n",
                         xtpText.nitems, ulReturnBytesLeft);
                pszAtomName = XGetAtomName(pDisplay, xtpText.encoding);
                winDebug("Notify atom name %s\n", pszAtomName);
                XFree(pszAtomName);
                pszAtomName = NULL;
            }

            if (data->fUseUnicode) {
#ifdef X_HAVE_UTF8_STRING
                /* Convert the text property to a text list */
                iReturn = Xutf8TextPropertyToTextList(pDisplay,
                                                      &xtpText,
                                                      &ppszTextList, &iCount);
#endif
            }
            else {
                iReturn = XmbTextPropertyToTextList(pDisplay,
                                                    &xtpText,
                                                    &ppszTextList, &iCount);
            }
            if (iReturn == Success || iReturn > 0) {
                /* Conversion succeeded or some unconvertible characters */
                if (ppszTextList != NULL) {
                    int i;
                    int iReturnDataLen = 0;
                    for (i = 0; i < iCount; i++) {
                        iReturnDataLen += strlen(ppszTextList[i]);
                    }
                    pszReturnData = malloc(iReturnDataLen + 1);
                    pszReturnData[0] = '\0';
                    for (i = 0; i < iCount; i++) {
                        strcat(pszReturnData, ppszTextList[i]);
                    }
                }
                else {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                           "X*TextPropertyToTextList list_return is NULL.\n");
                    pszReturnData = malloc(1);
                    pszReturnData[0] = '\0';
                }
            }
            else {
                ErrorF("winClipboardFlushXEvents - SelectionNotify - "
                       "X*TextPropertyToTextList returned: ");
                switch (iReturn) {
                case XNoMemory:
                    ErrorF("XNoMemory\n");
                    break;
                case XLocaleNotSupported:
                    ErrorF("XLocaleNotSupported\n");
                    break;
                case XConverterNotFound:
                    ErrorF("XConverterNotFound\n");
                    break;
                default:
                    ErrorF("%d\n", iReturn);
                    break;
                }
                pszReturnData = malloc(1);
                pszReturnData[0] = '\0';
            }

            /* Free the data returned from XGetWindowProperty */
            if (ppszTextList)
                XFreeStringList(ppszTextList);
            ppszTextList = NULL;
            XFree(xtpText.value);
            xtpText.value = NULL;
            xtpText.nitems = 0;

            /* Convert the X clipboard string to DOS format */
            winClipboardUNIXtoDOS(&pszReturnData, strlen(pszReturnData));

            if (data->fUseUnicode) {
                /* Find out how much space needed to convert MBCS to Unicode */
                int iUnicodeLen = MultiByteToWideChar(CP_UTF8,
                                                  0,
                                                  pszReturnData, -1, NULL, 0);

                /* NOTE: iUnicodeLen includes space for null terminator */
                pwszUnicodeStr = malloc(sizeof(wchar_t) * iUnicodeLen);
                if (!pwszUnicodeStr) {
                    ErrorF("winClipboardFlushXEvents - SelectionNotify "
                           "malloc failed for pwszUnicodeStr, aborting.\n");

                    /* Abort */
                    fAbort = TRUE;
                    goto winClipboardFlushXEvents_SelectionNotify_Done;
                }

                /* Do the actual conversion */
                MultiByteToWideChar(CP_UTF8,
                                    0,
                                    pszReturnData,
                                    -1, pwszUnicodeStr, iUnicodeLen);

                /* Allocate global memory for the X clipboard data */
                hGlobal = GlobalAlloc(GMEM_MOVEABLE,
                                      sizeof(wchar_t) * iUnicodeLen);
            }
            else {
                int iConvertDataLen = 0;
                pszConvertData = strdup(pszReturnData);
                iConvertDataLen = strlen(pszConvertData) + 1;

                /* Allocate global memory for the X clipboard data */
                hGlobal = GlobalAlloc(GMEM_MOVEABLE, iConvertDataLen);
            }

            free(pszReturnData);

            /* Check that global memory was allocated */
            if (!hGlobal) {
                ErrorF("winClipboardFlushXEvents - SelectionNotify "
                       "GlobalAlloc failed, aborting: %08x\n", (unsigned int)GetLastError());

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            /* Obtain a pointer to the global memory */
            pszGlobalData = GlobalLock(hGlobal);
            if (pszGlobalData == NULL) {
                ErrorF("winClipboardFlushXEvents - Could not lock global "
                       "memory for clipboard transfer\n");

                /* Abort */
                fAbort = TRUE;
                goto winClipboardFlushXEvents_SelectionNotify_Done;
            }

            /* Copy the returned string into the global memory */
            if (data->fUseUnicode) {
                wcscpy((wchar_t *)pszGlobalData, pwszUnicodeStr);
                free(pwszUnicodeStr);
                pwszUnicodeStr = NULL;
            }
            else {
                strcpy(pszGlobalData, pszConvertData);
                free(pszConvertData);
                pszConvertData = NULL;
            }

            /* Release the pointer to the global memory */
            GlobalUnlock(hGlobal);
            pszGlobalData = NULL;

            /* Push the selection data to the Windows clipboard */
            if (data->fUseUnicode)
                SetClipboardData(CF_UNICODETEXT, hGlobal);
            else
                SetClipboardData(CF_TEXT, hGlobal);

            /* Flag that SetClipboardData has been called */
            fSetClipboardData = FALSE;

            /*
             * NOTE: Do not try to free pszGlobalData, it is owned by
             * Windows after the call to SetClipboardData ().
             */

 winClipboardFlushXEvents_SelectionNotify_Done:
            /* Free allocated resources */
            if (ppszTextList)
                XFreeStringList(ppszTextList);
            if (xtpText.value) {
                XFree(xtpText.value);
                xtpText.value = NULL;
                xtpText.nitems = 0;
            }
            free(pszConvertData);
            free(pwszUnicodeStr);
            if (hGlobal && pszGlobalData)
                GlobalUnlock(hGlobal);
            if (fSetClipboardData) {
                SetClipboardData(CF_UNICODETEXT, NULL);
                SetClipboardData(CF_TEXT, NULL);
            }
            return WIN_XEVENTS_NOTIFY_DATA;

        case SelectionClear:
            winDebug("SelectionClear - doing nothing\n");
            break;

        case PropertyNotify:
            break;

        case MappingNotify:
            break;

        default:
            if (event.type == XFixesSetSelectionOwnerNotify + xfixes_event_base) {
                XFixesSelectionNotifyEvent *e =
                    (XFixesSelectionNotifyEvent *) & event;

                winDebug("winClipboardFlushXEvents - XFixesSetSelectionOwnerNotify\n");

                /* Save selection owners for monitored selections, ignore other selections */
                if ((e->selection == XA_PRIMARY) && fPrimarySelection) {
                    MonitorSelection(e, CLIP_OWN_PRIMARY);
                }
                else if (e->selection == atomClipboard) {
                    MonitorSelection(e, CLIP_OWN_CLIPBOARD);
                }
                else
                    break;

                /* Selection is being disowned */
                if (e->owner == None) {
                    winDebug
                        ("winClipboardFlushXEvents - No window, returning.\n");
                    break;
                }

                /*
                   XXX: there are all kinds of wacky edge cases we might need here:
                   - we own windows clipboard, but neither PRIMARY nor CLIPBOARD have an owner, so we should disown it?
                   - root window is taking ownership?
                 */

                /* If we are the owner of the most recently owned selection, don't go all recursive :) */
                if ((lastOwnedSelectionIndex != CLIP_OWN_NONE) &&
                    (s_iOwners[lastOwnedSelectionIndex] == iWindow)) {
                    winDebug("winClipboardFlushXEvents - Ownership changed to us, aborting.\n");
                    break;
                }

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

                /* Access the Windows clipboard */
                if (!OpenClipboard(hwnd)) {
                    ErrorF("winClipboardFlushXEvents - OpenClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }

                /* Take ownership of the Windows clipboard */
                if (!EmptyClipboard()) {
                    ErrorF("winClipboardFlushXEvents - EmptyClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }

                /* Advertise regular text and unicode */
                SetClipboardData(CF_UNICODETEXT, NULL);
                SetClipboardData(CF_TEXT, NULL);

                /* Release the clipboard */
                if (!CloseClipboard()) {
                    ErrorF("winClipboardFlushXEvents - CloseClipboard () failed: %08x\n",
                           (int) GetLastError());
                    break;
                }
            }
            /* XFixesSelectionWindowDestroyNotifyMask */
            /* XFixesSelectionClientCloseNotifyMask */
            else {
                ErrorF("winClipboardFlushXEvents - unexpected event type %d\n",
                       event.type);
            }
            break;
        }
    }

    return WIN_XEVENTS_SUCCESS;
}
Example #11
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 );
        }
    }


}