aboutsummaryrefslogtreecommitdiff
path: root/nxcompshad/Win.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'nxcompshad/Win.cpp')
-rw-r--r--nxcompshad/Win.cpp1130
1 files changed, 1130 insertions, 0 deletions
diff --git a/nxcompshad/Win.cpp b/nxcompshad/Win.cpp
new file mode 100644
index 000000000..9f8cdc9dd
--- /dev/null
+++ b/nxcompshad/Win.cpp
@@ -0,0 +1,1130 @@
+/**************************************************************************/
+/* */
+/* Copyright (c) 2001, 2007 NoMachine, http://www.nomachine.com/. */
+/* */
+/* NXCOMPSHAD, NX protocol compression and NX extensions to this software */
+/* are copyright of NoMachine. Redistribution and use of the present */
+/* software is allowed according to terms specified in the file LICENSE */
+/* which comes in the source distribution. */
+/* */
+/* Check http://www.nomachine.com/licensing.html for applicability. */
+/* */
+/* NX and NoMachine are trademarks of Medialogic S.p.A. */
+/* */
+/* All rights reserved. */
+/* */
+/**************************************************************************/
+
+#if defined(__CYGWIN32__) || defined(WIN32)
+
+#include <X11/keysym.h>
+
+#define PANIC
+#define WARNING
+#undef TEST
+#undef DEBUG
+
+#include "Poller.h"
+#include "Logger.h"
+
+Poller::Poller(Input *input, Display *display, int depth) : CorePoller(input, display)
+{
+ logTrace("Poller::Poller");
+
+ screenDC_ = NULL;
+ screenBmp_ = NULL;
+ memoryDC_ = NULL;
+ pDIBbits_ = NULL;
+ DIBBuffer_ = NULL;
+ pKey_ = NULL;
+ pMouse_ = NULL;
+ path_ = NULL;
+ keymapName_ = input -> getKeymap();
+ keymap_ = NULL;
+ toggleButtonState_ = 0;
+ serverModifierState_ = 0;
+ display_ = display;
+ depth_ = DefaultDepth(display_, DefaultScreen(display_));
+ oldCursor_ = 0;
+ xCursor_ = 0;
+}
+
+Poller::~Poller()
+{
+ logTrace("Poller::~Poller");
+
+ if (screenDC_)
+ {
+ BOOL result = ReleaseDC(NULL, screenDC_);
+
+ logTest("Poller::~Poller", "ReleaseDC returned [%d].", result);
+
+ screenDC_ = NULL;
+ }
+
+ if (memoryDC_)
+ {
+ BOOL result = DeleteDC(memoryDC_);
+
+ logTest("Poller::~Poller", "DeleteDC returned [%d].", result);
+
+ memoryDC_ = NULL;
+ }
+
+ if (screenBmp_)
+ {
+ BOOL result = DeleteObject(screenBmp_);
+
+ logTest("Poller::~Poller", "DeleteObject returned [%d].", result);
+
+ screenBmp_ = NULL;
+ }
+
+ if (DIBBuffer_)
+ {
+ logDebug("Poller::~Poller", "Delete DIBBuffer_ [%p].", DIBBuffer_);
+
+ delete [] DIBBuffer_;
+ }
+
+ if (pKey_)
+ {
+ logDebug("Poller::~Poller", " pKey_[%p].", pKey_);
+
+ delete [] pKey_;
+ }
+
+ if (pMouse_)
+ {
+ logDebug("Poller::~Poller", " pMouse_[%p].", pMouse_);
+
+ delete [] pMouse_;
+ }
+
+ if (keymap_)
+ {
+ logDebug("Poller::~Poller", " keymap_[%p].", keymap_);
+
+ delete [] keymap_;
+ }
+}
+
+int Poller::init()
+{
+ logTrace("Poller::init");
+
+ int maxLengthArrayINPUT = 6;
+
+ platformOS();
+
+ pKey_ = new INPUT [maxLengthArrayINPUT];
+
+ if (pKey_ == NULL)
+ {
+ logError("Poller::init", ESET(ENOMEM));
+
+ return -1;
+ }
+
+ for (int i = 0; i < maxLengthArrayINPUT; i++)
+ {
+ pKey_[i].type = INPUT_KEYBOARD;
+ pKey_[i].ki.wVk = (WORD) 0;
+ pKey_[i].ki.time = (DWORD) 0;
+ pKey_[i].ki.dwExtraInfo = (DWORD) 0;
+ }
+
+ pMouse_ = new INPUT;
+
+ if (pMouse_ == NULL)
+ {
+ logError("Poller::init", ESET(ENOMEM));
+
+ return -1;
+ }
+
+ pMouse_ -> type = INPUT_MOUSE;
+
+ pMouse_ -> mi.dx = 0;
+ pMouse_ -> mi.dy = 0;
+ pMouse_ -> mi.mouseData = (DWORD) 0;
+ pMouse_ -> mi.time = 0;
+ pMouse_ -> mi.dwExtraInfo = (ULONG_PTR) NULL;
+
+ screenDC_ = GetDC(NULL);
+
+ if (screenDC_ == NULL)
+ {
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+
+ switch(depth_)
+ {
+ case 8:
+ {
+ depth_ = 16;
+ break;
+ }
+ case 16:
+ {
+ depth_ = 16;
+ break;
+ }
+ case 24:
+ {
+ depth_ = 32;
+ break;
+ }
+ default:
+ {
+ logError("Poller::init", ESET(EINVAL));
+
+ return -1;
+ }
+ }
+
+ width_ = GetDeviceCaps(screenDC_, HORZRES);
+ height_ = GetDeviceCaps(screenDC_, VERTRES);
+
+ bpl_ = width_ * (depth_ >> 3);
+ bpp_ = (depth_ >> 3);
+
+ logTest("Poller::init", "Screen geometry is [%d, %d] depth is [%d] bpl [%d] bpp [%d].",
+ width_, height_, depth_, bpl_, bpp_);
+
+ logTest("Poller::init", "Got device context at [%p] screen size is (%d,%d).",
+ screenDC_, width_, height_);
+
+ memoryDC_ = CreateCompatibleDC(screenDC_);
+
+ if (memoryDC_ == NULL)
+ {
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+
+ //
+ // Delete the old bitmap for the memory device.
+ //
+
+ HBITMAP bitmap = (HBITMAP) GetCurrentObject(memoryDC_, OBJ_BITMAP);
+
+ if (bitmap && DeleteObject(bitmap) == 0)
+ {
+ logError("Poller::init", ESET(ENOMSG));
+ }
+
+ //
+ // Bitmap header describing the bitmap we want to get from GetDIBits.
+ //
+
+ bmi_.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+ bmi_.bmiHeader.biWidth = width_;
+ bmi_.bmiHeader.biHeight = -height_;
+ bmi_.bmiHeader.biPlanes = 1;
+ bmi_.bmiHeader.biBitCount = depth_;
+ bmi_.bmiHeader.biCompression = BI_RGB;
+ bmi_.bmiHeader.biSizeImage = 0;
+ bmi_.bmiHeader.biXPelsPerMeter = 0;
+ bmi_.bmiHeader.biYPelsPerMeter = 0;
+ bmi_.bmiHeader.biClrUsed = 0;
+ bmi_.bmiHeader.biClrImportant = 0;
+
+ screenBmp_ = CreateDIBSection(memoryDC_, &bmi_, DIB_RGB_COLORS, &pDIBbits_, NULL, 0);
+ ReleaseDC(NULL,memoryDC_);
+
+ if (screenBmp_ == NULL)
+ {
+ logTest ("Poller::init", "This video device is not supporting DIB section");
+
+ pDIBbits_ = NULL;
+
+ screenBmp_ = CreateCompatibleBitmap(screenDC_, width_, height_);
+
+ if (screenBmp_ == NULL)
+ {
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+
+ if (SelectObject(memoryDC_, screenBmp_) == NULL)
+ {
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+ }
+ else
+ {
+ logTest ("Poller::init", "Enabled the DIB section");
+
+ if (SelectObject(memoryDC_, screenBmp_) == NULL)
+ {
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+ }
+
+ //
+ // Check if the screen device raster capabilities
+ // support the bitmap transfer.
+ //
+
+ if ((GetDeviceCaps(screenDC_, RASTERCAPS) & RC_BITBLT) == 0)
+ {
+ logTest("Poller::init", "This video device is not supporting the bitmap transfer.");
+
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+
+ //
+ // Check if the memory device raster capabilities
+ // support the GetDIBits and SetDIBits functions.
+ //
+
+ if ((GetDeviceCaps(memoryDC_, RASTERCAPS) & RC_DI_BITMAP) == 0)
+ {
+ logTest("Poller::init", "This memory device is not supporting the GetDIBits and SetDIBits "
+ "function.");
+
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+
+ if (GetDeviceCaps(screenDC_, PLANES) != 1)
+ {
+ logTest("Poller::init", "This video device has more than 1 color plane.");
+
+ logError("Poller::init", ESET(ENOMSG));
+
+ return -1;
+ }
+
+ return CorePoller::init();
+}
+
+//
+// FIXME: Remove me.
+//
+
+void ErrorExit(LPTSTR lpszFunction)
+{
+ LPVOID lpMsgBuf;
+ DWORD dw = GetLastError();
+
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL );
+
+ logTest(lpszFunction, " Failed with error [%ld]: %s", dw, (char*)lpMsgBuf);
+
+ LocalFree(lpMsgBuf);
+ ExitProcess(dw);
+}
+
+//
+// FIXME: End.
+//
+
+char *Poller::getRect(XRectangle r)
+{
+ logTrace("Poller::getRect");
+
+ logDebug("Poller::getRect", "Going to retrive rectangle [%d, %d, %d, %d].",
+ r.x, r.y, r.width, r.height);
+
+ //
+ // The CAPTUREBLT operation could be a very
+ // cpu-consuming task. We should make some
+ // test to see how much it is expensive.
+ // Anyway we get tooltip windows and any
+ // other special effect not included with
+ // only the SRCCOPY operation.
+ //
+
+ if (BitBlt(memoryDC_, r.x, r.y, r.width, r.height,
+ screenDC_, r.x, r.y, SRCCOPY | CAPTUREBLT) == 0)
+ {
+ logError("Poller::getRect", ESET(ENOMSG));
+
+ logTest("Poller::getRect", "Failed to perform a bit-block transfer.");
+ logTest("Poller::getRect", "bit-block error=%lu", GetLastError());
+
+ return NULL;
+ }
+
+ // bmi_.bmiHeader.biWidth = r.width;
+ // bmi_.bmiHeader.biHeight = -r.height;
+
+ if (pDIBbits_ == NULL)
+ {
+ static long nPixel = 0;
+
+ if (nPixel < r.width * r.height)
+ {
+
+ if (DIBBuffer_)
+ {
+ delete [] DIBBuffer_;
+ }
+
+ nPixel = r.width * r.height;
+
+ DIBBuffer_ = new char [nPixel * bpp_];
+
+ if (DIBBuffer_ == NULL)
+ {
+ logError("Poller::getRect", ESET(ENOMEM));
+
+ nPixel = 0;
+
+ return NULL;
+ }
+ }
+
+ if (GetDIBits(memoryDC_, screenBmp_, height_ - r.height - r.y, r.height,
+ DIBBuffer_, &bmi_, DIB_RGB_COLORS) == 0)
+ {
+ logError("Poller::getRect", ESET(ENOMSG));
+
+ logTest("Poller::getRect", "Failed to retrieve the screen bitmap.");
+
+ return NULL;
+ }
+
+ return DIBBuffer_;
+ }
+ else
+ {
+ return (char *) pDIBbits_ + r.y * bpl_ + r.x * bpp_;
+ }
+}
+
+void Poller::handleKeyboardEvent(Display *display, XEvent *event)
+{
+ KeySym keysym;
+ char *keyname = new char [31];
+ keyTranslation tr = {0, 0};
+ unsigned char scancode = 0;
+ int lengthArrayINPUT = 0;
+
+ if (XLookupString((XKeyEvent *) event, keyname, 30, &keysym, NULL) > 0)
+ {
+ logTest("Poller::handleKeyboardEvent", "keyname %s, keysym [%x]", keyname, (unsigned int)keysym);
+ }
+
+ if (specialKeys(keysym, event -> xkey.state, event -> type) == 1)
+ {
+ delete[] keyname;
+ return;
+ }
+
+ tr = xkeymapTranslateKey(keysym, event -> xkey.keycode, event -> xkey.state);
+ scancode = tr.scancode;
+
+ logTest("Poller::handleKeyboardEvent", "keyname [%s] scancode [0x%x], keycode[0x%x], keysym [%x]", keyname,
+ tr.scancode, event ->xkey.keycode, (unsigned int)keysym);
+
+ if (scancode == 0)
+ {
+ delete[] keyname;
+ return;
+ }
+
+ if (event -> type == KeyPress)
+ {
+ int test1 = MapVirtualKey(scancode, MAPVK_VSC_TO_VK_EX);
+ int test2 = MapVirtualKey(0x24, MAPVK_VSC_TO_VK_EX);
+
+ if (test1 == test2)
+ {
+ simulateCtrlAltDel();
+ }
+
+ if (isModifier(scancode) == 0)
+ {
+ savedServerModifierState_ = serverModifierState_;
+ }
+
+ ensureServerModifiers(tr, &lengthArrayINPUT);
+ if (sendInput(scancode, 1, &lengthArrayINPUT) == 0)
+ {
+ logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT);
+ }
+ restoreServerModifiers(scancode);
+ }
+ else if (event -> type == KeyRelease)
+ {
+ if (sendInput(scancode, 0, &lengthArrayINPUT) == 0)
+ {
+ logTest("Poller::handleKeyboardEvent", "lengthArrayINPUT [%d].", lengthArrayINPUT);
+ }
+ }
+
+ updateModifierState(scancode, (event -> type == KeyPress));
+
+ delete[] keyname;
+}
+
+void Poller::handleMouseEvent(Display *display, XEvent *event)
+{
+ DWORD flg = 0;
+ DWORD whl = 0;
+
+ if (event -> type == ButtonPress)
+ {
+ logTest("Poller::handleMouseEvent", "ButtonPress.\n");
+ switch (event -> xbutton.button)
+ {
+ case Button1:
+ {
+ flg = MOUSEEVENTF_LEFTDOWN;
+ break;
+ }
+ case Button2:
+ {
+ flg = MOUSEEVENTF_MIDDLEDOWN;
+ break;
+ }
+ case Button3:
+ {
+ flg = MOUSEEVENTF_RIGHTDOWN;
+ break;
+ }
+ case Button4:
+ {
+ flg = MOUSEEVENTF_WHEEL;
+ whl = WHEEL_DELTA;
+ pMouse_ -> mi.mouseData = whl;
+ break;
+ }
+ case Button5:
+ {
+ flg = MOUSEEVENTF_WHEEL;
+ whl = (DWORD) (-WHEEL_DELTA);
+ pMouse_ -> mi.mouseData = whl;
+ break;
+ }
+ }
+ }
+ else if (event -> type == ButtonRelease)
+ {
+ switch (event -> xbutton.button)
+ {
+ case Button1:
+ {
+ flg = MOUSEEVENTF_LEFTUP;
+ break;
+ }
+ case Button2:
+ {
+ flg = MOUSEEVENTF_MIDDLEUP;
+ break;
+ }
+ case Button3:
+ {
+ flg = MOUSEEVENTF_RIGHTUP;
+ break;
+ }
+ case Button4:
+ {
+ flg = MOUSEEVENTF_WHEEL;
+ whl = 0;
+ pMouse_ -> mi.mouseData = whl;
+ break;
+ }
+ case Button5:
+ {
+ flg = MOUSEEVENTF_WHEEL;
+ whl = 0;
+ pMouse_ -> mi.mouseData = whl;
+ break;
+ }
+ }
+ }
+ else if (event -> type == MotionNotify)
+ {
+ logTest("Poller::handleMouseEvent", "SetCursor - MotionNotify");
+
+ SetCursorPos(event -> xmotion.x, event -> xmotion.y);
+ }
+
+ if (flg > 0)
+ {
+ // logTest("Poller::handleMouseEvent", "SetCursor - flg > 0");
+ //
+ // FIXME: move the cursor to the pace the event occurred
+ //
+
+ SetCursorPos(event -> xbutton.x, event -> xbutton.y);
+
+ //
+ // FIXME: Remove me: send the click/release event
+ // mouse_event(flg, 0, 0, whl, (ULONG_PTR)NULL);
+ //
+
+ pMouse_ -> mi.dwFlags = flg;
+
+ if (SendInput(1, pMouse_, sizeof(INPUT)) == 0)
+ {
+ logTest("Poller::handleMouseEvent", "Failed SendInput");
+ }
+ }
+}
+
+int Poller::updateCursor(Window wnd, Visual* vis)
+{
+ BYTE *mBits, *andBits, *xorBits;
+
+ logTrace("Poller::Cursor");
+
+ //
+ // Retrieve mouse cursor handle.
+ //
+
+ CURSORINFO cursorInfo;
+ cursorInfo.cbSize = sizeof(CURSORINFO);
+
+ if (GetCursorInfo(&cursorInfo) == 0)
+ {
+ logTest("Poller::Cursor", "GetCursorInfo() failed [%u].\n", (unsigned int)GetLastError());
+ LocalFree(&cursorInfo);
+ return -1;
+ }
+
+ HCURSOR hCursor = cursorInfo.hCursor;
+
+ if (hCursor == 0)
+ {
+ logTest("Poller::Cursor","Cursor Handle is NULL. Error[%u].\n", (unsigned int)GetLastError());
+ return 1;
+ }
+
+ if (hCursor == oldCursor_)
+ {
+ LocalFree(&cursorInfo);
+ return 1;
+ }
+ else
+ {
+ oldCursor_ = hCursor;
+ }
+
+ //
+ // Get cursor info.
+ //
+
+ // logTest("Poller::Cursor","hCursor [%xH] GetCursor [%xH].\n", hCursor, GetCursor());
+
+ ICONINFO iconInfo;
+ if (GetIconInfo(hCursor, &iconInfo) == 0)
+ {
+ logTest("Poller::Cursor","GetIconInfo() failed. Error[%d].", (unsigned int)GetLastError());
+ LocalFree(&iconInfo);
+ // return -1;
+ }
+
+ BOOL isColorCursor = FALSE;
+ if (iconInfo.hbmColor != NULL)
+ {
+ isColorCursor = TRUE;
+ }
+
+ if (iconInfo.hbmMask == NULL)
+ {
+ logTest("Poller::Cursor","Cursor bitmap handle is NULL.\n");
+ return -1;
+ }
+
+ //
+ // Check bitmap info for the cursor
+ //
+
+ BITMAP bmMask;
+ if (!GetObject(iconInfo.hbmMask, sizeof(BITMAP), (LPVOID)&bmMask))
+ {
+ logTest("Poller::Cursor","GetObject() for bitmap failed.\n");
+ DeleteObject(iconInfo.hbmMask);
+ LocalFree(&bmMask);
+ return -1;
+ }
+
+ if (bmMask.bmPlanes != 1 || bmMask.bmBitsPixel != 1)
+ {
+ logTest("Poller::Cursor","Incorrect data in cursor bitmap.\n");
+ LocalFree(&bmMask);
+ DeleteObject(iconInfo.hbmMask);
+ return -1;
+ }
+
+ // Get monochrome bitmap data for cursor
+ // NOTE: they say we should use GetDIBits() instead of GetBitmapBits().
+ mBits = new BYTE[bmMask.bmWidthBytes * bmMask.bmHeight];
+
+ if (mBits == NULL)//Data bitmap
+ {
+ DeleteObject(iconInfo.hbmMask);
+ DestroyCursor(cursorInfo.hCursor);
+ LocalFree(&iconInfo);
+ LocalFree(&bmMask);
+ delete[] mBits;
+ return -1;
+ }
+
+ BOOL success = GetBitmapBits(iconInfo.hbmMask, bmMask.bmWidthBytes * bmMask.bmHeight, mBits);
+
+ if (!success)
+ {
+ logTest("Poller::Cursor","GetBitmapBits() failed.\n");
+ delete[] mBits;
+ return -1;
+ }
+
+ andBits = mBits;
+
+ long width = bmMask.bmWidth;
+ long height = (isColorCursor) ? bmMask.bmHeight : bmMask.bmHeight/2;
+
+ //
+ // The bitmask is formatted so that the upper half is
+ // the icon AND bitmask and the lower half is the icon XOR bitmask.
+ //
+
+ if (!isColorCursor)
+ {
+ xorBits = andBits + bmMask.bmWidthBytes * height;
+
+/* logTest("Poller::Cursor","no color widthB[%ld] width[%ld] height[%ld] totByte[%ld] mbits[%ld].\n",
+ bmMask.bmWidthBytes,width,height,success,bmMask.bmHeight * bmMask.bmWidthBytes);*/
+
+ if (xCursor_ > 0)
+ {
+ XFreeCursor(display_, xCursor_);
+ }
+
+ xCursor_ = createCursor(wnd, vis, (unsigned int)iconInfo.xHotspot, (unsigned int)iconInfo.yHotspot,
+ width, height, (unsigned char *)xorBits, (unsigned char *)andBits);
+
+ XDefineCursor(display_, wnd, xCursor_);
+ }
+
+ delete []mBits;
+ DeleteObject(iconInfo.hbmMask);
+ LocalFree(&bmMask);
+ DestroyCursor(cursorInfo.hCursor);
+ LocalFree(&iconInfo);
+
+ return success;
+}
+
+unsigned char Poller::specialKeys(unsigned int keysym, unsigned int state, int pressed)
+{
+ return 0;
+}
+
+void Poller::ensureServerModifiers(keyTranslation tr, int *lengthArrayINPUT)
+{
+ return;
+}
+
+void Poller::restoreServerModifiers(UINT scancode)
+{
+ keyTranslation dummy;
+ int lengthArrayINPUT = 0;
+
+ if (isModifier(scancode) == 1)
+ {
+ return;
+ }
+
+ dummy.scancode = 0;
+ dummy.modifiers = savedServerModifierState_;
+ ensureServerModifiers(dummy, &lengthArrayINPUT);
+ if (sendInput(0, 0, &lengthArrayINPUT) == 0)
+ {
+ logTest("Poller::restoreServerModifiers", "lengthArrayINPUT [%d]", lengthArrayINPUT);
+ }
+}
+
+int Poller::updateShadowFrameBuffer(void)
+{
+ return 1;
+}
+
+void Poller::addToKeymap(char *keyname, unsigned char scancode, unsigned short modifiers, char *mapname)
+{
+ return;
+}
+
+FILE *Poller::xkeymapOpen(char *filename)
+{
+ return NULL;
+}
+
+int Poller::xkeymapRead(char *mapname)
+{
+ return 1;
+}
+
+void Poller::xkeymapInit(char *keyMapName)
+{
+ return;
+}
+
+keyTranslation Poller::xkeymapTranslateKey(unsigned int keysym, unsigned int keycode,
+ unsigned int state)
+{
+ keyTranslation tr = { 0, 0 };
+
+ return tr;
+}
+
+unsigned char Poller::getKeyState(unsigned int state, unsigned int keysym)
+{
+ return 0;
+}
+
+char *Poller::getKsname(unsigned int keysym)
+{
+ char *ksname = NULL;
+
+ return ksname;
+}
+
+//
+// Routine used to fool Winlogon into thinking CtrlAltDel was pressed
+//
+char Poller::simulateCtrlAltDel(void)
+{
+ HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId());
+
+ //
+ // Switch into the Winlogon desktop.
+ //
+ if (selectDesktopByName("Winlogon") == 0)
+ {
+ logTest("SimulateCtrlAltDelThreadFn","Failed to select logon desktop.");
+ return 0;
+ }
+
+ logTest("SimulateCtrlAltDelThreadFn","Generating ctrl-alt-del.");
+
+ //
+ // Winlogon uses hotkeys to trap Ctrl-Alt-Del.
+ //
+ PostMessage(HWND_BROADCAST, WM_HOTKEY, 0, MAKELONG(MOD_ALT | MOD_CONTROL, VK_DELETE));
+
+ //
+ // Switch back to our original desktop.
+ //
+ if (oldDesktop != NULL)
+ {
+ selectDesktop(oldDesktop);
+ }
+
+ return 1;
+}
+
+// Switches the current thread into a different desktop by desktop handle
+// This call takes care of all the evil memory management involved
+char Poller::selectDesktop(HDESK newDesktop)
+{
+ //
+ // Only on NT.
+ //
+ if (isWinNT())
+ {
+ HDESK oldDesktop = GetThreadDesktop(GetCurrentThreadId());
+
+ DWORD dummy;
+ char newName[256];
+
+ if (GetUserObjectInformation(newDesktop, UOI_NAME, &newName, 256, &dummy) == 0)
+ {
+ logDebug("Poller::selectDesktop","GetUserObjectInformation() failed. Error[%lu].", GetLastError());
+ return 0;
+ }
+
+ logTest("Poller::selectDesktop","New Desktop to [%s] (%x) from (%x).",
+ newName, (unsigned int)newDesktop, (unsigned int)oldDesktop);
+
+ //
+ // Switch the desktop.
+ //
+ if(SetThreadDesktop(newDesktop) == 0)
+ {
+ logDebug("Poller::SelectDesktop","Unable to SetThreadDesktop(), Error=%lu.", GetLastError());
+ return 0;
+ }
+
+ //
+ // Switched successfully - destroy the old desktop.
+ //
+ if (CloseDesktop(oldDesktop) == 0)
+ {
+ logDebug("Poller::selectHdesk","Failed to close old desktop (%x), Error=%lu.",
+ (unsigned int)oldDesktop, GetLastError());
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+//
+// Switches the current thread into a different desktop, by name
+// Calling with a valid desktop name will place the thread in that desktop.
+// Calling with a NULL name will place the thread in the current input desktop.
+//
+
+char Poller::selectDesktopByName(char *name)
+{
+ //
+ // Only on NT.
+ //
+ if (isWinNT())
+ {
+ HDESK desktop;
+
+ if (name != NULL)
+ {
+ //
+ // Attempt to open the named desktop.
+ //
+ desktop = OpenDesktop(name, 0, FALSE,
+ DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
+ DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
+ DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
+ DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
+ }
+ else
+ {
+ //
+ // Open the input desktop.
+ //
+ desktop = OpenInputDesktop(0, FALSE,
+ DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
+ DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
+ DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
+ DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
+ }
+
+ if (desktop == NULL)
+ {
+ logDebug("Poller::selectDesktopByName","Unable to open desktop, Error=%lu.", GetLastError());
+ return 0;
+ }
+
+ //
+ // Switch to the new desktop
+ //
+ if (selectDesktop(desktop) == 0)
+ {
+ //
+ // Failed to enter the new desktop, so free it!
+ //
+ logDebug("Poller::selectDesktopByName","Failed to select desktop.");
+
+ if (CloseDesktop(desktop) == 0)
+ {
+ logDebug("Poller::selectDesktopByName","Failed to close desktop, Error=%lu.", GetLastError());
+ return 0;
+ }
+ }
+
+ return 1;
+ }
+
+ return (name == NULL);
+}
+
+void Poller::platformOS()
+{
+ OSVERSIONINFO osversioninfo;
+ osversioninfo.dwOSVersionInfoSize = sizeof(osversioninfo);
+
+ //
+ // Get the current OS version.
+ //
+ if (GetVersionEx(&osversioninfo) == 0)
+ {
+ platformID_ = 0;
+ }
+ platformID_ = osversioninfo.dwPlatformId;
+
+//
+// versionMajor = osversioninfo.dwMajorVersion;
+// versionMinor = osversioninfo.dwMinorVersion;
+//
+}
+
+char Poller::checkDesktop()
+{
+ //
+ // Only on NT.
+ //
+ if (isWinNT())
+ {
+ //
+ // Get the input and thread desktops.
+ //
+ HDESK desktop = GetThreadDesktop(GetCurrentThreadId());
+ HDESK inputDesktop = OpenInputDesktop(0, FALSE,
+ DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW |
+ DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL |
+ DESKTOP_WRITEOBJECTS | DESKTOP_READOBJECTS |
+ DESKTOP_SWITCHDESKTOP | GENERIC_WRITE);
+
+ if (inputDesktop == NULL)
+ {
+ return 0;
+ }
+
+ DWORD dummy;
+ char desktopName[256];
+ char inputName[256];
+
+ if (GetUserObjectInformation(desktop, UOI_NAME, &desktopName, 256, &dummy) == 0)
+ {
+ if (CloseDesktop(inputDesktop) == 0)
+ {
+ logDebug("Poller::checkDesktop", "Failed to close desktop, Error[%d].", (unsigned int)GetLastError());
+ return 0;
+ }
+ }
+
+ if (GetUserObjectInformation(inputDesktop, UOI_NAME, &inputName, 256, &dummy) == 0)
+ {
+ if (CloseDesktop(inputDesktop) == 0)
+ {
+ logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError());
+ return 0;
+ }
+ }
+
+ if (strcmp(desktopName, inputName) != 0)
+ {
+ //
+ // Switch to new desktop.
+ //
+ selectDesktop(inputDesktop);
+ }
+
+ if (CloseDesktop(desktop) == 0)
+ {
+ logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError());
+ return 0;
+ }
+
+ if (CloseDesktop(inputDesktop) == 0)
+ {
+ logDebug("Poller::checkDesktop", "Failed to close input desktop, Error[%d].", (unsigned int)GetLastError());
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+unsigned char Poller::isModifier(UINT scancode)
+{
+ return 0;
+}
+
+void Poller::updateModifierState(UINT scancode, unsigned char pressed)
+{
+ return;
+}
+
+Cursor Poller::createCursor(Window wnd, Visual *vis,unsigned int x, unsigned int y,
+ int width, int height, unsigned char *xormask, unsigned char *andmask)
+{
+ Pixmap maskglyph, cursorglyph;
+ XColor bg, fg;
+ Cursor xcursor;
+ unsigned char *cursor;
+ unsigned char *mask, *pmask, *pcursor, tmp;
+ int scanline, offset;
+
+ scanline = (width + 7) / 8;
+ offset = scanline * height;
+
+ pmask = andmask;
+ pcursor = xormask;
+ for (int i = 0; i < offset; i++)
+ {
+ //
+ // The pixel is black if both the bit of andmask and xormask is one.
+ //
+
+ tmp = *pcursor & *pmask;
+ *pcursor ^= tmp;
+ *pmask ^= tmp;
+
+ *pmask = ~(*pmask);
+
+ pmask++;
+ pcursor++;
+ }
+
+ cursor = new unsigned char[offset];
+ memcpy(cursor, xormask, offset);
+
+ mask = new unsigned char[offset];
+ memcpy(mask, andmask, offset);
+
+ fg.red = fg.blue = fg.green = 0xffff;
+ bg.red = bg.blue = bg.green = 0x0000;
+ fg.flags = bg.flags = DoRed | DoBlue | DoGreen;
+
+ cursorglyph = createGlyph(wnd, vis, width, height, cursor);
+ maskglyph = createGlyph(wnd, vis, width, height, mask);
+
+ xcursor = XCreatePixmapCursor(display_, cursorglyph, maskglyph, &fg, &bg, x, y);
+
+ XFreePixmap(display_, maskglyph);
+ XFreePixmap(display_, cursorglyph);
+ delete[]mask;
+ delete[]cursor;
+
+ return xcursor;
+}
+
+Pixmap Poller::createGlyph(Window wnd, Visual *visual, int width, int height, unsigned char *data)
+{
+ XImage *image;
+ Pixmap bitmap;
+ int scanline;
+ GC glyphGC;
+
+ scanline = (width + 7) / 8;
+
+ bitmap = XCreatePixmap(display_, wnd, width, height, 1);
+ glyphGC = XCreateGC(display_, bitmap, 0, NULL);
+
+ image = XCreateImage(display_, visual, 1, ZPixmap, 0, (char *)data, width, height, 8, scanline);
+ image->byte_order = 1; // MSBFirst -- LSBFirst = 0
+ image->bitmap_bit_order = 1;
+ XInitImage(image);
+
+/* logTest("Poller::createGlyph","XPutImage on pixmap %d,%d,%d,%d.\n",
+ 0, 0, width, height);*/
+ XPutImage(display_, bitmap, glyphGC, image, 0, 0, 0, 0, width, height);
+ XFree(image);
+
+ return bitmap;
+}
+#endif /* defined(__CYGWIN32__) || defined(WIN32) */