# limitations under the License.
add_executable(wfreerdp WIN32
+ wf_gdi.c
+ wf_gdi.h
+ wf_event.c
+ wf_event.h
wfreerdp.c
wfreerdp.h)
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Event Handling
+ *
+ * Copyright 2009-2011 Jay Sorg
+ * Copyright 2010-2011 Vic Lee
+ * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <freerdp/freerdp.h>
+#include "wfreerdp.h"
+
+#include "wf_event.h"
+
+static HWND g_focus_hWnd;
+extern HCURSOR g_default_cursor;
+
+#define X_POS(lParam) (lParam & 0xffff)
+#define Y_POS(lParam) ((lParam >> 16) & 0xffff)
+
+LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam)
+{
+ DWORD flags;
+ wfInfo* wfi;
+ uint8 scanCode;
+ rdpInput* input;
+ uint16 kbdFlags;
+ PKBDLLHOOKSTRUCT p;
+
+ DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X\n", g_focus_hWnd, nCode, wParam);
+
+ if (g_focus_hWnd && (nCode == HC_ACTION))
+ {
+ switch (wParam)
+ {
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ case WM_KEYUP:
+ case WM_SYSKEYUP:
+ wfi = (wfInfo*) GetWindowLongPtr(g_focus_hWnd, GWLP_USERDATA);
+ p = (PKBDLLHOOKSTRUCT) lParam;
+ scanCode = (uint8) p->scanCode;
+ input = wfi->instance->input;
+ flags = p->flags;
+ kbdFlags = 0;
+
+ DEBUG_KBD("keydown %d scanCode %04X flags %02X vkCode %02X\n",
+ (wParam == WM_KEYDOWN), scanCode, flags, p->vkCode);
+
+ if (wfi->fs_toggle &&
+ ((p->vkCode == VK_RETURN) || (p->vkCode == VK_CANCEL)) &&
+ (GetAsyncKeyState(VK_CONTROL) & 0x8000) &&
+ (GetAsyncKeyState(VK_MENU) & 0x8000)) /* could also use flags & LLKHF_ALTDOWN */
+ {
+ if (wParam == WM_KEYDOWN)
+ //wf_toggle_fullscreen(wfi);
+ return 1;
+ }
+
+ if (scanCode == 0x45) /* NumLock-ish */
+ {
+ if (flags & LLKHF_EXTENDED)
+ {
+ /* Windows sends NumLock as extended - rdp doesn't */
+ DEBUG_KBD("hack: NumLock (x45) should not be extended\n");
+ flags &= ~LLKHF_EXTENDED;
+ }
+ else
+ {
+ /* Windows sends Pause as if it was a RDP NumLock (handled above).
+ * It must however be sent as a one-shot Ctrl+NumLock */
+ if (wParam == WM_KEYDOWN)
+ {
+ DEBUG_KBD("Pause, sent as Ctrl+NumLock\n");
+ input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x1D); /* Ctrl down */
+ input->KeyboardEvent(input, KBD_FLAGS_DOWN, 0x45); /* NumLock down */
+ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x1D); /* Ctrl up */
+ input->KeyboardEvent(input, KBD_FLAGS_RELEASE, 0x45); /* NumLock up */
+ }
+ else
+ {
+ DEBUG_KBD("Pause up\n");
+ }
+
+ return 1;
+ }
+ }
+
+ if ((scanCode == 0x36) && (flags & LLKHF_EXTENDED))
+ {
+ DEBUG_KBD("hack: right shift (x36) should not be extended\n");
+ flags &= ~LLKHF_EXTENDED;
+ }
+
+ kbdFlags |= (flags & LLKHF_UP) ? KBD_FLAGS_RELEASE : KBD_FLAGS_DOWN;
+ kbdFlags |= (flags & LLKHF_EXTENDED) ? KBD_FLAGS_EXTENDED : 0;
+ input->KeyboardEvent(input, kbdFlags, scanCode);
+
+ if (p->vkCode == VK_CAPITAL)
+ DEBUG_KBD("caps lock is processed on client side too to toggle caps lock indicator\n");
+ else
+ return 1;
+
+ break;
+ }
+ }
+
+ return CallNextHookEx(NULL, nCode, wParam, lParam);
+}
+
+LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
+{
+ HDC hdc;
+ LONG ptr;
+ wfInfo* wfi;
+ PAINTSTRUCT ps;
+ rdpInput* input;
+
+ ptr = GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ wfi = (wfInfo*) ptr;
+ input = wfi->instance->input;
+
+ switch (Msg)
+ {
+ case WM_DESTROY:
+ PostQuitMessage(WM_QUIT);
+ break;
+
+ case WM_PAINT:
+ if (wfi != NULL)
+ {
+ hdc = BeginPaint(hWnd, &ps);
+ BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
+ ps.rcPaint.right - ps.rcPaint.left,
+ ps.rcPaint.bottom - ps.rcPaint.top,
+ wfi->primary->hdc, ps.rcPaint.left, ps.rcPaint.top,
+ SRCCOPY);
+ EndPaint(hWnd, &ps);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ if (wfi != NULL)
+ input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam));
+ break;
+
+ case WM_LBUTTONUP:
+ if (wfi != NULL)
+ input->MouseEvent(input, PTR_FLAGS_BUTTON1, X_POS(lParam), Y_POS(lParam));
+ break;
+
+ case WM_RBUTTONDOWN:
+ if (wfi != NULL)
+ input->MouseEvent(input, PTR_FLAGS_DOWN | PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam));
+ break;
+
+ case WM_RBUTTONUP:
+ if (wfi != NULL)
+ input->MouseEvent(input, PTR_FLAGS_BUTTON2, X_POS(lParam), Y_POS(lParam));
+ break;
+
+ case WM_MOUSEMOVE:
+ if (wfi != NULL)
+ input->MouseEvent(input, PTR_FLAGS_MOVE, X_POS(lParam), Y_POS(lParam));
+ break;
+
+ case WM_SETCURSOR:
+ if (wfi != NULL)
+ SetCursor(wfi->cursor);
+ else
+ SetCursor(g_default_cursor);
+ break;
+
+ case WM_SETFOCUS:
+ DEBUG_KBD("getting focus %X\n", hWnd);
+ g_focus_hWnd = hWnd;
+ break;
+
+ case WM_KILLFOCUS:
+ DEBUG_KBD("loosing focus %X\n", hWnd);
+ if (g_focus_hWnd == hWnd)
+ g_focus_hWnd = NULL;
+ break;
+
+ default:
+ return DefWindowProc(hWnd, Msg, wParam, lParam);
+ break;
+ }
+
+ return 0;
+}
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Event Handling
+ *
+ * Copyright 2009-2011 Jay Sorg
+ * Copyright 2010-2011 Vic Lee
+ * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WF_EVENT_H
+#define __WF_EVENT_H
+
+#include "wfreerdp.h"
+
+LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam);
+LRESULT CALLBACK wf_event_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
+
+#ifdef WITH_DEBUG_KBD
+#define DEBUG_KBD(fmt, ...) DEBUG_CLASS(KBD, fmt, ## __VA_ARGS__)
+#else
+#define DEBUG_KBD(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
+#endif
+
+#endif
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Windows GDI
+ *
+ * Copyright 2009-2011 Jay Sorg
+ * Copyright 2010-2011 Vic Lee
+ * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <conio.h>
+
+#include <freerdp/gdi/gdi.h>
+#include <freerdp/common/color.h>
+
+#include "wfreerdp.h"
+
+HBITMAP wf_create_dib(wfInfo* wfi, int width, int height, int bpp, uint8* data)
+{
+ HDC hdc;
+ int negHeight;
+ HBITMAP bitmap;
+ BITMAPINFO bmi;
+ uint8* cdata = NULL;
+
+ /**
+ * See: http://msdn.microsoft.com/en-us/library/dd183376
+ * if biHeight is positive, the bitmap is bottom-up
+ * if biHeight is negative, the bitmap is top-down
+ * Since we get top-down bitmaps, let's keep it that way
+ */
+
+ negHeight = (height < 0) ? height : height * (-1);
+
+ hdc = GetDC(NULL);
+ bmi.bmiHeader.biSize = sizeof(BITMAPINFO);
+ bmi.bmiHeader.biWidth = width;
+ bmi.bmiHeader.biHeight = negHeight;
+ bmi.bmiHeader.biPlanes = 1;
+ bmi.bmiHeader.biBitCount = 24;
+ bmi.bmiHeader.biCompression = BI_RGB;
+ bitmap = CreateDIBSection (hdc, &bmi, DIB_RGB_COLORS, (void**) &cdata, NULL, 0);
+
+ if (data != NULL)
+ freerdp_image_convert(data, cdata, width, height, bpp, 24, wfi->clrconv);
+
+ ReleaseDC(NULL, hdc);
+ GdiFlush();
+
+ return bitmap;
+}
+
+WF_IMAGE* wf_image_new(wfInfo* wfi, int width, int height, int bpp, uint8* data)
+{
+ HDC hdc;
+ WF_IMAGE* image;
+
+ hdc = GetDC(NULL);
+ image = (WF_IMAGE*) malloc(sizeof(WF_IMAGE));
+ image->hdc = CreateCompatibleDC(hdc);
+
+ if (data == NULL)
+ image->bitmap = CreateCompatibleBitmap(hdc, width, height);
+ else
+ image->bitmap = wf_create_dib(wfi, width, height, bpp, data);
+
+ image->org_bitmap = (HBITMAP) SelectObject(image->hdc, image->bitmap);
+ ReleaseDC(NULL, hdc);
+
+ return image;
+}
+
+void wf_image_free(WF_IMAGE* image)
+{
+ if (image != 0)
+ {
+ SelectObject(image->hdc, image->org_bitmap);
+ DeleteObject(image->bitmap);
+ DeleteDC(image->hdc);
+ free(image);
+ }
+}
+
+void wf_toggle_fullscreen(wfInfo* wfi)
+{
+ ShowWindow(wfi->hwnd, SW_HIDE);
+ wfi->fullscreen = !wfi->fullscreen;
+ SetForegroundWindow(wfi->hwnd);
+}
--- /dev/null
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Windows GDI
+ *
+ * Copyright 2009-2011 Jay Sorg
+ * Copyright 2010-2011 Vic Lee
+ * Copyright 2010-2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __WF_GDI_H
+#define __WF_GDI_H
+
+#include "wfreerdp.h"
+
+WF_IMAGE* wf_image_new(wfInfo* wfi, int width, int height, int bpp, uint8* data);
+void wf_image_free(WF_IMAGE* image);
+void wf_toggle_fullscreen(wfInfo* wfi);
+
+#endif /* __WF_GDI_H */
#include <freerdp/utils/event.h>
#include <freerdp/chanman/chanman.h>
+#include "wf_gdi.h"
+
#include "wfreerdp.h"
struct _thread_data
boolean wf_pre_connect(freerdp* instance)
{
+ int i1;
wfInfo* wfi;
rdpSettings* settings;
settings->order_support[NEG_ELLIPSE_SC_INDEX] = False;
settings->order_support[NEG_ELLIPSE_CB_INDEX] = False;
+ wfi->cursor = g_default_cursor;
+
+ wfi->fullscreen = settings->fullscreen;
+ wfi->fs_toggle = wfi->fullscreen;
+
+ if (wfi->percentscreen > 0)
+ {
+ i1 = (GetSystemMetrics(SM_CXSCREEN) * wfi->percentscreen) / 100;
+ settings->width = i1;
+
+ i1 = (GetSystemMetrics(SM_CYSCREEN) * wfi->percentscreen) / 100;
+ settings->height = i1;
+ }
+
+ if (wfi->fs_toggle)
+ {
+ settings->width = GetSystemMetrics(SM_CXSCREEN);
+ settings->height = GetSystemMetrics(SM_CYSCREEN);
+ }
+
+ i1 = settings->width;
+ i1 = (i1 + 3) & (~3);
+ settings->width = i1;
+
+ if ((settings->width < 64) || (settings->height < 64) ||
+ (settings->width > 4096) || (settings->height > 4096))
+ {
+ printf("wf_pre_connect: invalid dimensions %d %d\n", settings->width, settings->height);
+ return 1;
+ }
+
settings->kbd_layout = (int) GetKeyboardLayout(0) & 0x0000FFFF;
freerdp_chanman_pre_connect(GET_CHANMAN(instance), instance);
{
GDI* gdi;
wfInfo* wfi;
+ int width, height;
+ wchar_t win_title[64];
+ rdpSettings* settings;
wfi = GET_WFI(instance);
SET_WFI(instance->update, wfi);
+ settings = instance->settings;
gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP);
gdi = GET_GDI(instance->update);
+ width = settings->width;
+ height = settings->height;
+
+ if (strlen(wfi->window_title) > 0)
+ _snwprintf(win_title, sizeof(win_title), L"%S", wfi->window_title);
+ else if (settings->port == 3389)
+ _snwprintf(win_title, sizeof(win_title) / sizeof(win_title[0]), L"%S - FreeRDP", settings->hostname);
+ else
+ _snwprintf(win_title, sizeof(win_title) / sizeof(win_title[0]), L"%S:%d - FreeRDP", settings->hostname, settings->port);
+
+ if (wfi->hwnd == 0)
+ {
+ wfi->hwnd = CreateWindowEx((DWORD) NULL, g_wnd_class_name, win_title,
+ 0, 0, 0, 0, 0, NULL, NULL, g_hInstance, NULL);
+
+ SetWindowLongPtr(wfi->hwnd, GWLP_USERDATA, (LONG_PTR) wfi);
+ }
+
+ if (wfi->fullscreen)
+ {
+ SetWindowLongPtr(wfi->hwnd, GWL_STYLE, WS_POPUP);
+ SetWindowPos(wfi->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
+ }
+ else
+ {
+ POINT diff;
+ RECT rc_client, rc_wnd;
+
+ SetWindowLongPtr(wfi->hwnd, GWL_STYLE, WS_CAPTION | WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX);
+ /* Now resize to get full canvas size and room for caption and borders */
+ SetWindowPos(wfi->hwnd, HWND_TOP, 10, 10, width, height, SWP_FRAMECHANGED);
+ GetClientRect(wfi->hwnd, &rc_client);
+ GetWindowRect(wfi->hwnd, &rc_wnd);
+ diff.x = (rc_wnd.right - rc_wnd.left) - rc_client.right;
+ diff.y = (rc_wnd.bottom - rc_wnd.top) - rc_client.bottom;
+ SetWindowPos(wfi->hwnd, HWND_TOP, -1, -1, width + diff.x, height + diff.y, SWP_NOMOVE | SWP_FRAMECHANGED);
+ }
+
+ if (wfi->primary == NULL)
+ {
+ wfi->primary = wf_image_new(wfi, width, height, 0, NULL);
+ BitBlt(wfi->primary->hdc, 0, 0, width, height, NULL, 0, 0, BLACKNESS);
+ }
+ wfi->drawing = wfi->primary;
+
+ ShowWindow(wfi->hwnd, SW_SHOWNORMAL);
+ UpdateWindow(wfi->hwnd);
+
freerdp_chanman_post_connect(GET_CHANMAN(instance), instance);
return True;
wfi->clrconv->alpha = 1;
wfi->clrconv->palette = NULL;
SET_WFI(instance, wfi);
+ wfi->instance = instance;
wfreerdp_run(instance);
static DWORD WINAPI kbd_thread_func(LPVOID lpParam)
{
-#if 0
MSG msg;
- BOOL bRet;
+ BOOL status;
HHOOK hook_handle;
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, g_hInstance, 0);
if (hook_handle)
{
- while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
+ while( (status = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
- if (bRet == -1)
+ if (status == -1)
{
printf("keyboard thread error getting message\n");
break;
}
else
printf("failed to install keyboard hook\n");
-#endif
return (DWORD) NULL;
}
wnd_cls.cbSize = sizeof(WNDCLASSEX);
wnd_cls.style = CS_HREDRAW | CS_VREDRAW;
- //wnd_cls.lpfnWndProc = wf_event_proc;
+ wnd_cls.lpfnWndProc = wf_event_proc;
wnd_cls.cbClsExtra = 0;
wnd_cls.cbWndExtra = 0;
wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
if (!CreateThread(NULL, 0, kbd_thread_func, NULL, 0, NULL))
printf("error creating keyboard handler thread");
- while (1)
+ //while (1)
{
data = (thread_data*) xzalloc(sizeof(thread_data));
data->instance = instance;
WSACleanup();
+#ifdef _DEBUG
+ system("pause");
+#endif
+
return 0;
}
#include <freerdp/utils/debug.h>
#include <freerdp/chanman/chanman.h>
+#include "wf_event.h"
+
#define SET_WFI(_instance, _wfi) (_instance)->param1 = _wfi
#define GET_WFI(_instance) ((wfInfo*) ((_instance)->param1))
#define SET_CHANMAN(_instance, _chanman) (_instance)->param2 = _chanman
#define GET_CHANMAN(_instance) ((rdpChanMan*) ((_instance)->param2))
-struct wf_bitmap
+struct _WF_IMAGE
{
HDC hdc;
HBITMAP bitmap;
HBITMAP org_bitmap;
};
+typedef struct _WF_IMAGE WF_IMAGE;
struct wf_info
{
char window_title[64];
HWND hwnd;
- struct wf_bitmap* primary;
- struct wf_bitmap* drawing;
+ freerdp* instance;
+ WF_IMAGE* primary;
+ WF_IMAGE* drawing;
HCLRCONV clrconv;
HCURSOR cursor;
HBRUSH brush;
int tls_verify_certificate(CryptoCert cert, char* hostname)
{
- boolean ret;
+ boolean status;
rdpCertstore* certstore;
- ret = x509_verify_cert(cert);
+ status = x509_verify_cert(cert);
- if (!ret)
+ if (status != True)
{
rdpCertdata* certdata;
certdata = crypto_get_certdata(cert->px509, hostname);
char answer;
crypto_cert_printinfo(cert->px509);
+#ifndef _WIN32
while (1)
{
printf("Do you trust the above certificate? (Y/N) ");
return 1;
}
}
+#endif
}
else if (certstore->match == -1)
{
#ifndef _WIN32
mkdir(certloc, S_IRUSR | S_IWUSR | S_IXUSR);
#else
- CreateDirectory(certloc, 0);
+ CreateDirectoryA(certloc, 0);
#endif
}
#ifndef _WIN32
mkdir(certstore->path, S_IRUSR | S_IWUSR | S_IXUSR);
#else
- CreateDirectory(certstore->path, 0);
+ CreateDirectoryA(certstore->path, 0);
#endif
printf("creating directory %s\n", certstore->path);
}
#ifndef _WIN32
mkdir(registry->path, S_IRUSR | S_IWUSR | S_IXUSR);
#else
- CreateDirectory(registry->path, 0);
+ CreateDirectoryA(registry->path, 0);
#endif
printf("creating directory %s\n", registry->path);
}