Merge branch 'master' of github.com:FreeRDP/FreeRDP

This commit is contained in:
Marc-André Moreau 2014-02-27 13:58:29 -05:00
commit 951368a1ce
37 changed files with 1528 additions and 114 deletions

View File

@ -49,3 +49,7 @@ endif()
if(WITH_OPENSLES)
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "opensles" "")
endif()
if(WITH_WINMM)
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "winmm" "")
endif()

View File

@ -607,6 +607,15 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
}
#endif
#if defined(WITH_WINMM)
if (!audin->device)
{
audin_set_subsystem(audin, "winmm");
audin_set_device_name(audin, "default");
audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args);
}
#endif
if (audin->device == NULL)
{
DEBUG_WARN("no sound device.");

View File

@ -0,0 +1,41 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 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.
define_channel_client_subsystem("audin" "winmm" "")
set(${MODULE_PREFIX}_SRCS
audin_winmm.c)
include_directories(..)
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winmm.lib)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/winmm")

View File

@ -0,0 +1,309 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Audio Input Redirection Virtual Channel - WinMM implementation
*
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <MMSystem.h>
#include <winpr/crt.h>
#include <winpr/cmdline.h>
#include <freerdp/addin.h>
#include "audin_main.h"
typedef struct _AudinWinmmDevice
{
IAudinDevice iface;
char* device_name;
AudinReceive receive;
void* user_data;
HANDLE thread;
HANDLE stopEvent;
HWAVEIN hWaveIn;
PWAVEFORMATEX *ppwfx;
PWAVEFORMATEX pwfx_cur;
UINT32 ppwfx_size;
UINT32 cFormats;
UINT32 frames_per_packet;
} AudinWinmmDevice;
static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance,
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) dwInstance;
PWAVEHDR pWaveHdr;
switch(uMsg)
{
case WIM_CLOSE:
break;
case WIM_DATA:
pWaveHdr = (WAVEHDR *)dwParam1;
if (WHDR_DONE == (WHDR_DONE & pWaveHdr->dwFlags))
{
if (pWaveHdr->dwBytesRecorded
&& !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0))
{
winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data);
waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
}
}
break;
case WIM_OPEN:
break;
default:
break;
}
}
static DWORD audin_winmm_thread_func(void* arg)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) arg;
char *buffer;
int size, i;
WAVEHDR waveHdr[4];
if (!winmm->hWaveIn)
{
if (MMSYSERR_NOERROR != waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur,
(DWORD_PTR)waveInProc, (DWORD_PTR)winmm, CALLBACK_FUNCTION))
{
return 0;
}
}
size = (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet + 7) / 8;
for (i = 0; i < 4; i++)
{
buffer = (char *) malloc(size);
waveHdr[i].dwBufferLength = size;
waveHdr[i].dwFlags = 0;
waveHdr[i].lpData = buffer;
if (MMSYSERR_NOERROR != waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
{
DEBUG_DVC("waveInPrepareHeader failed.");
}
if (MMSYSERR_NOERROR != waveInAddBuffer(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
{
DEBUG_DVC("waveInAddBuffer failed.");
}
}
waveInStart(winmm->hWaveIn);
WaitForSingleObject(winmm->stopEvent, INFINITE);
waveInStop(winmm->hWaveIn);
for (i = 0; i < 4; i++)
{
if (MMSYSERR_NOERROR != waveInUnprepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
{
DEBUG_DVC("waveInUnprepareHeader failed.");
}
free(waveHdr[i].lpData);
}
waveInClose(winmm->hWaveIn);
winmm->hWaveIn = NULL;
return 0;
}
static void audin_winmm_free(IAudinDevice* device)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
int i;
for (i = 0; i < winmm->cFormats; i++)
{
free(winmm->ppwfx[i]);
}
free(winmm->ppwfx);
free(winmm->device_name);
free(winmm);
}
static void audin_winmm_close(IAudinDevice* device)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
DEBUG_DVC("");
SetEvent(winmm->stopEvent);
WaitForSingleObject(winmm->thread, INFINITE);
CloseHandle(winmm->thread);
CloseHandle(winmm->stopEvent);
winmm->thread = NULL;
winmm->stopEvent = NULL;
winmm->receive = NULL;
winmm->user_data = NULL;
}
static void audin_winmm_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
int i;
winmm->frames_per_packet = FramesPerPacket;
for (i = 0; i < winmm->cFormats; i++)
{
if (winmm->ppwfx[i]->wFormatTag == format->wFormatTag
&& winmm->ppwfx[i]->nChannels == format->nChannels
&& winmm->ppwfx[i]->wBitsPerSample == format->wBitsPerSample)
{
winmm->pwfx_cur = winmm->ppwfx[i];
break;
}
}
}
static BOOL audin_winmm_format_supported(IAudinDevice* device, audinFormat* format)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
PWAVEFORMATEX pwfx;
BYTE *data;
pwfx = (PWAVEFORMATEX)malloc(sizeof(WAVEFORMATEX) + format->cbSize);
pwfx->cbSize = format->cbSize;
pwfx->wFormatTag = format->wFormatTag;
pwfx->nChannels = format->nChannels;
pwfx->nSamplesPerSec = format->nSamplesPerSec;
pwfx->nBlockAlign = format->nBlockAlign;
pwfx->wBitsPerSample = format->wBitsPerSample;
data = (BYTE *)pwfx + sizeof(WAVEFORMATEX);
memcpy(data, format->data, format->cbSize);
if (pwfx->wFormatTag == WAVE_FORMAT_PCM)
{
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
if (MMSYSERR_NOERROR == waveInOpen(NULL, WAVE_MAPPER, pwfx, 0, 0, WAVE_FORMAT_QUERY))
{
if (winmm->cFormats >= winmm->ppwfx_size)
{
winmm->ppwfx_size *= 2;
winmm->ppwfx = realloc(winmm->ppwfx, sizeof(PWAVEFORMATEX) * winmm->ppwfx_size);
}
winmm->ppwfx[winmm->cFormats++] = pwfx;
return 1;
}
}
free(pwfx);
return 0;
}
static void audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data)
{
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
DEBUG_DVC("");
winmm->receive = receive;
winmm->user_data = user_data;
winmm->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
winmm->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL);
}
static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] =
{
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* args)
{
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_winmm_args, flags, winmm, NULL, NULL);
arg = audin_winmm_args;
do
{
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
continue;
CommandLineSwitchStart(arg)
CommandLineSwitchCase(arg, "audio-dev")
{
winmm->device_name = _strdup(arg->Value);
}
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
}
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry
#endif
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
{
ADDIN_ARGV* args;
AudinWinmmDevice* winmm;
winmm = (AudinWinmmDevice*) malloc(sizeof(AudinWinmmDevice));
ZeroMemory(winmm, sizeof(AudinWinmmDevice));
winmm->iface.Open = audin_winmm_open;
winmm->iface.FormatSupported = audin_winmm_format_supported;
winmm->iface.SetFormat = audin_winmm_set_format;
winmm->iface.Close = audin_winmm_close;
winmm->iface.Free = audin_winmm_free;
args = pEntryPoints->args;
audin_winmm_parse_addin_args(winmm, args);
if (!winmm->device_name)
winmm->device_name = _strdup("default");
winmm->ppwfx_size = 10;
winmm->ppwfx = malloc(sizeof(PWAVEFORMATEX) * winmm->ppwfx_size);
pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm);
return 0;
}

View File

@ -413,13 +413,13 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
free(channel->channel_name);
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
ichannel = (IWTSVirtualChannel*) channel;
ichannel->Close(ichannel);
}
free(channel->channel_name);
return 0;
}

View File

@ -177,9 +177,9 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat
struct STAT st;
BOOL exists;
#ifdef WIN32
const static int mode = _S_IREAD | _S_IWRITE ;
const static int mode = _S_IREAD | _S_IWRITE ;
#else
const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
const static int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH;
BOOL largeFile = FALSE;
#endif
int oflag = 0;
@ -265,8 +265,10 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat
#ifndef WIN32
if (largeFile)
{
oflag |= O_LARGEFILE;
oflag |= O_LARGEFILE;
}
#else
oflag |= O_BINARY;
#endif
file->fd = OPEN(file->fullpath, oflag, mode);
@ -426,7 +428,7 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input)
{
char* s = NULL;
mode_t m;
mode_t m;
UINT64 size;
int status;
char* fullpath;
@ -456,7 +458,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
tv[1].tv_usec = 0;
#ifndef WIN32
/* TODO on win32 */
/* TODO on win32 */
#ifdef ANDROID
utimes(file->fullpath, tv);
#else
@ -474,15 +476,17 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
fchmod(file->fd, st.st_mode);
}
#endif
break;
break;
case FileEndOfFileInformation:
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
case FileAllocationInformation:
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
#ifndef _WIN32
Stream_Read_UINT64(input, size);
if (ftruncate(file->fd, size) != 0)
return FALSE;
#endif
break;
case FileDispositionInformation:
@ -509,10 +513,16 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
fullpath = drive_file_combine_fullpath(file->basepath, s);
free(s);
/* TODO rename does not work on win32 */
if (rename(file->fullpath, fullpath) == 0)
#ifdef _WIN32
if (file->fd)
close(file->fd);
#endif
if (rename(file->fullpath, fullpath) == 0)
{
drive_file_set_fullpath(file, fullpath);
#ifdef _WIN32
file->fd = OPEN(fullpath, O_RDWR | O_BINARY);
#endif
}
else
{

View File

@ -40,13 +40,13 @@
#endif
#ifdef _WIN32
#define STAT stat
#define STAT __stat64
#define OPEN _open
#define close _close
#define read _read
#define write _write
#define LSEEK _lseek
#define FSTAT fstat
#define LSEEK _lseeki64
#define FSTAT _fstat64
#define STATVFS statvfs
#define mkdir(a,b) _mkdir(a)
#define rmdir _rmdir

View File

@ -576,29 +576,29 @@ static void drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
static void* drive_thread_func(void* arg)
{
IRP* irp;
wMessage message;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
IRP* irp;
wMessage message;
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
while (1)
{
if (!MessageQueue_Wait(drive->IrpQueue))
break;
while (1)
{
if (!MessageQueue_Wait(drive->IrpQueue))
break;
if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
break;
if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
break;
if (message.id == WMQ_QUIT)
break;
if (message.id == WMQ_QUIT)
break;
irp = (IRP*) message.wParam;
irp = (IRP*) message.wParam;
if (irp)
drive_process_irp(drive, irp);
}
if (irp)
drive_process_irp(drive, irp);
}
ExitThread(0);
return NULL;
ExitThread(0);
return NULL;
}
static void drive_irp_request(DEVICE* device, IRP* irp)
@ -712,13 +712,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
drive->Path = _strdup("/");
}
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
#else
sys_code_page = GetACP();
/* Special case: path[0] == '*' -> export all drives */
/* Special case: path[0] == '*' -> export all drives */
/* Special case: path[0] == '%' -> user home dir */
if (strcmp(drive->Path, "%") == 0)
if (strcmp(drive->Path, "%") == 0)
{
_snprintf(buf, sizeof(buf), "%s\\", getenv("USERPROFILE"));
drive_register_drive_path(pEntryPoints, drive->Name, _strdup(buf));
@ -733,7 +733,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
for (dev = devlist, i = 0; *dev; dev += 4, i++)
{
if (*dev > 'B')
{
{
/* Suppress disk drives A and B to avoid pesty messages */
len = _snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
buf[len] = '_';
@ -744,11 +744,11 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
}
}
}
else
{
else
{
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
}
#endif
return 0;
}
return 0;
}

View File

@ -67,6 +67,15 @@ void devman_free(DEVMAN* devman)
free(devman);
}
void devman_unregister_device(DEVMAN* devman, void* key)
{
DEVICE* device;
device = (DEVICE *)ListDictionary_Remove(devman->devices, key);
if (device)
devman_device_free(device);
}
static void devman_register_device(DEVMAN* devman, DEVICE* device)
{
void* key = NULL;

View File

@ -23,6 +23,7 @@
#include "rdpdr_main.h"
void devman_unregister_device(DEVMAN* devman, void* key);
BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device);
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);

View File

@ -33,6 +33,15 @@
#include <freerdp/constants.h>
#include <freerdp/channels/rdpdr.h>
#ifdef _WIN32
#include <windows.h>
#include <dbt.h>
#else
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -44,6 +53,432 @@
#include "rdpdr_main.h"
typedef struct _DEVICE_DRIVE_EXT DEVICE_DRIVE_EXT;
struct _DEVICE_DRIVE_EXT
{
DEVICE device;
char* path;
};
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn);
static void rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 count, UINT32 ids[])
{
wStream* s;
int i;
s = Stream_New(NULL, 256);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_REMOVE);
Stream_Write_UINT32(s, count);
for (i = 0; i < count; i++)
Stream_Write_UINT32(s, ids[i]);
Stream_SealLength(s);
rdpdr_send(rdpdr, s);
}
#ifdef _WIN32
LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
rdpdrPlugin *rdpdr;
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
rdpdr = (rdpdrPlugin *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
switch(Msg)
{
case WM_DEVICECHANGE:
switch (wParam)
{
case DBT_DEVICEARRIVAL:
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
DWORD unitmask = lpdbv->dbcv_unitmask;
int i;
char drive_path[4] = { 'c', ':', '/', '\0'};
for (i = 0; i < 26; i++)
{
if (unitmask & 0x01)
{
RDPDR_DRIVE* drive;
drive_path[0] = 'A' + i;
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive);
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
}
unitmask = unitmask >> 1;
}
}
break;
case DBT_DEVICEREMOVECOMPLETE:
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
{
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
DWORD unitmask = lpdbv->dbcv_unitmask;
int i, j, count;
char drive_name_upper, drive_name_lower;
ULONG_PTR *keys;
DEVICE_DRIVE_EXT *device_ext;
UINT32 ids[1];
for (i = 0; i < 26; i++)
{
if (unitmask & 0x01)
{
drive_name_upper = 'A' + i;
drive_name_lower = 'a' + i;
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
for (j = 0; j < count; j++)
{
device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]);
if (device_ext->path[0] == drive_name_upper || device_ext->path[0] == drive_name_lower)
{
devman_unregister_device(rdpdr->devman, (void *)keys[j]);
ids[0] = keys[j];
rdpdr_send_device_list_remove_request(rdpdr, 1, ids);
break;
}
}
}
unitmask = unitmask >> 1;
}
}
break;
default:
break;
}
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
static void* drive_hotplug_thread_func(void* arg)
{
rdpdrPlugin *rdpdr;
WNDCLASSEX wnd_cls;
HWND hwnd;
MSG msg;
BOOL bRet;
DEV_BROADCAST_HANDLE NotificationFilter;
HDEVNOTIFY hDevNotify;
rdpdr = (rdpdrPlugin *)arg;
/* init windows class */
wnd_cls.cbSize = sizeof(WNDCLASSEX);
wnd_cls.style = CS_HREDRAW | CS_VREDRAW;
wnd_cls.lpfnWndProc = hotplug_proc;
wnd_cls.cbClsExtra = 0;
wnd_cls.cbWndExtra = 0;
wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wnd_cls.hCursor = NULL;
wnd_cls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wnd_cls.lpszMenuName = NULL;
wnd_cls.lpszClassName = L"DRIVE_HOTPLUG";
wnd_cls.hInstance = NULL;
wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wnd_cls);
/* create window */
hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL,
0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL);
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)rdpdr);
rdpdr->hotplug_wnd = hwnd;
/* register device interface to hwnd */
NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
/* message loop */
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
{
if (bRet == -1)
{
break;
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnregisterDeviceNotification(hDevNotify);
return NULL;
}
static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
{
if (rdpdr->hotplug_wnd)
PostMessage(rdpdr->hotplug_wnd, WM_QUIT, 0, 0);
}
#else
#define MAX_USB_DEVICES 100
typedef struct _hotplug_dev {
char* path;
BOOL to_add;
} hotplug_dev;
static char* next_line(FILE* fd, size_t* len)
{
size_t newsiz;
int c;
char* newbuf;
char* lrbuf;
int lrsiz;
*len = 0;
lrsiz = 0;
lrbuf = NULL;
newbuf = NULL;
for (;;)
{
c = fgetc(fd);
if (ferror(fd))
return NULL;
if (c == EOF)
{
if (*len == 0)
return NULL;
else
{
lrbuf[(*len)] = '\0';
return lrbuf;
}
}
else
{
if (*len == lrsiz)
{
newsiz = lrsiz + 4096;
newbuf = realloc(lrbuf, newsiz);
if (newbuf == NULL)
return NULL;
lrbuf = newbuf;
lrsiz = newsiz;
}
lrbuf[(*len)] = c;
if (c == '\n')
{
lrbuf[(*len)] = '\0';
return lrbuf;
}
(*len)++;
}
}
}
static char* get_word(char* str, unsigned int* offset)
{
char* p;
char* tmp;
int wlen;
if (*offset >= strlen(str))
return NULL;
p = str + *offset;
tmp = p;
while (*tmp != ' ' && *tmp != '\0')
tmp++;
wlen = tmp - p;
*offset += wlen;
/* in case there are more than one space between words */
while (*(str + *offset) == ' ')
(*offset)++;
return strndup(p, wlen);
}
static void handle_hotplug(rdpdrPlugin* rdpdr)
{
FILE *f;
size_t len;
char *line;
char *word;
unsigned int wlen;
hotplug_dev dev_array[MAX_USB_DEVICES];
int i, j;
int size = 0;
int count;
DEVICE_DRIVE_EXT *device_ext;
ULONG_PTR *keys;
UINT32 ids[1];
f = fopen("/proc/mounts", "r");
if (f == NULL)
{
return;
}
while ((line = next_line(f, &len)))
{
wlen = 0;
while ((word = get_word(line, &wlen)))
{
/* copy hotpluged device mount point to the dev_array */
if (strstr(word, "/mnt/") != NULL || strstr(word, "/media/") != NULL)
{
dev_array[size].path = strdup(word);
dev_array[size++].to_add = TRUE;
}
free(word);
}
free(line);
}
fclose(f);
/* delete removed devices */
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
for (j = 0; j < count; j++)
{
BOOL dev_found = FALSE;
device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]);
/* not plugable device */
if (strstr(device_ext->path, "/mnt/") == NULL && strstr(device_ext->path, "/media/") == NULL)
continue;
for (i = 0; i < size; i++)
{
if (strstr(device_ext->path, dev_array[i].path) != NULL)
{
dev_found = TRUE;
dev_array[i].to_add = FALSE;
break;
}
}
if (!dev_found)
{
devman_unregister_device(rdpdr->devman, (void *)keys[j]);
ids[0] = keys[j];
rdpdr_send_device_list_remove_request(rdpdr, 1, ids);
}
}
/* add new devices */
for (i = 0; i < size; i++)
{
RDPDR_DRIVE* drive;
if (dev_array[i].to_add)
{
char* name;
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = _strdup(dev_array[i].path);
name = strrchr(drive->Path, '/') + 1;
drive->Name = _strdup(name);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive);
}
free(dev_array[i].path);
dev_array[i].path = NULL;
}
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
}
static void* drive_hotplug_thread_func(void* arg)
{
rdpdrPlugin* rdpdr;
int mfd;
fd_set rfds;
struct timeval tv;
int rv;
rdpdr = (rdpdrPlugin *)arg;
rdpdr->stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
mfd = open("/proc/mounts", O_RDONLY, 0);
if (mfd < 0)
{
fprintf(stderr, "ERROR: Unable to open /proc/mounts.");
return NULL;
}
FD_ZERO(&rfds);
FD_SET(mfd, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0)
{
if (WaitForSingleObject(rdpdr->stop_event, 0) == WAIT_OBJECT_0)
break;
if (FD_ISSET(mfd, &rfds))
{
/* file /proc/mounts changed, handle this */
handle_hotplug(rdpdr);
}
FD_ZERO(&rfds);
FD_SET(mfd, &rfds);
tv.tv_sec = 1;
tv.tv_usec = 0;
}
return NULL;
}
static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
{
if (rdpdr->stop_event)
SetEvent(rdpdr->stop_event);
}
#endif
static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
{
UINT32 index;
@ -58,6 +493,11 @@ static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
for (index = 0; index < settings->DeviceCount; index++)
{
device = settings->DeviceArray[index];
if (strcmp(device->Name, "*") == 0)
{
rdpdr->hotplug_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)drive_hotplug_thread_func, rdpdr, 0, NULL);
continue;
}
devman_load_device_service(rdpdr->devman, device);
}
}
@ -497,6 +937,10 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
MessagePipe_Free(rdpdr->MsgPipe);
CloseHandle(rdpdr->thread);
drive_hotplug_thread_terminate(rdpdr);
WaitForSingleObject(rdpdr->hotplug_thread, INFINITE);
rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle);
if (rdpdr->data_in)

View File

@ -52,6 +52,14 @@ struct rdpdr_plugin
UINT16 versionMinor;
UINT16 clientID;
char computerName[256];
/* hotplug support */
HANDLE hotplug_thread;
#ifdef _WIN32
HWND hotplug_wnd;
#else
HANDLE stop_event;
#endif
};
int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);

View File

@ -201,12 +201,7 @@ static void* rdpsnd_server_thread(void* arg)
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
{
if (!BytesReturned)
break;

View File

@ -33,6 +33,8 @@ set(${MODULE_PREFIX}_SRCS
wf_rail.h
wf_interface.c
wf_interface.h
wf_floatbar.c
wf_floatbar.h
wfreerdp.rc
resource.h)

View File

@ -1,2 +1,13 @@
#define IDI_ICON1 101
#define IDI_ICON1 101
#define IDB_BACKGROUND 102
#define IDB_MINIMIZE 103
#define IDB_MINIMIZE_ACT 104
#define IDB_LOCK 105
#define IDB_LOCK_ACT 106
#define IDB_UNLOCK 107
#define IDB_UNLOCK_ACT 108
#define IDB_CLOSE 109
#define IDB_CLOSE_ACT 100
#define IDB_RESTORE 111
#define IDB_RESTORE_ACT 112

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -0,0 +1,466 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Windows Float Bar
*
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.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 <Windows.h>
#include <stdlib.h>
#include "wf_interface.h"
#include "wf_floatbar.h"
#include "wf_window.h"
#include "wf_gdi.h"
#include "resource.h"
typedef struct _Button Button;
/* TIMERs */
#define TIMER_HIDE 1
#define TIMER_ANIMAT_SHOW 2
#define TIMER_ANIMAT_HIDE 3
/* Button Type */
#define BUTTON_LOCKPIN 0
#define BUTTON_MINIMIZE 1
#define BUTTON_RESTORE 2
#define BUTTON_CLOSE 3
#define BTN_MAX 4
/* bmp size */
#define BACKGROUND_W 581
#define BACKGROUND_H 29
#define LOCK_X 13
#define MINIMIZE_X (BACKGROUND_W - 91)
#define CLOSE_X (BACKGROUND_W - 37)
#define RESTORE_X (BACKGROUND_W - 64)
#define BUTTON_Y 2
#define BUTTON_WIDTH 24
#define BUTTON_HEIGHT 24
struct _Button {
FloatBar* floatbar;
int type;
int x, y, h, w;
int active;
HBITMAP bmp;
HBITMAP bmp_act;
/* Lock Specified */
HBITMAP locked_bmp;
HBITMAP locked_bmp_act;
HBITMAP unlocked_bmp;
HBITMAP unlocked_bmp_act;
};
struct _FloatBar {
HWND parent;
HWND hwnd;
RECT rect;
LONG width;
LONG height;
wfContext* wfc;
Button* buttons[BTN_MAX];
BOOL shown;
BOOL locked;
HDC hdcmem;
HBITMAP background;
};
static int button_hit(Button* button)
{
FloatBar* floatbar = button->floatbar;
switch (button->type)
{
case BUTTON_LOCKPIN:
if (!floatbar->locked)
{
button->bmp = button->locked_bmp;
button->bmp_act = button->locked_bmp_act;
}
else
{
button->bmp = button->unlocked_bmp;
button->bmp_act = button->unlocked_bmp_act;
}
floatbar->locked = ~floatbar->locked;
InvalidateRect(button->floatbar->hwnd, NULL, FALSE);
UpdateWindow(button->floatbar->hwnd);
break;
case BUTTON_MINIMIZE:
ShowWindow(floatbar->parent, SW_MINIMIZE);
break;
case BUTTON_RESTORE:
wf_toggle_fullscreen(floatbar->wfc);
break;
case BUTTON_CLOSE:
SendMessage(floatbar->parent, WM_DESTROY, 0 , 0);
break;
default:
return 0;
}
return 0;
}
static int button_paint(Button* button, HDC hdc)
{
FloatBar* floatbar = button->floatbar;
SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp);
StretchBlt(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0, button->w, button->h, SRCCOPY);
return 0;
}
static Button* floatbar_create_button(FloatBar* floatbar, int type, int resid, int resid_act, int x, int y, int h, int w)
{
Button *button;
HDC hDC;
HDC hMemDC;
HBITMAP hBitmap;
HBITMAP hOldBitmap;
BITMAP bm;
button = (Button *)malloc(sizeof(Button));
if (!button)
return NULL;
button->floatbar = floatbar;
button->type = type;
button->x = x;
button->y = y;
button->w = w;
button->h = h;
button->active = FALSE;
button->bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(resid), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
button->bmp_act = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(resid_act), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
return button;
}
static Button* floatbar_create_lock_button(FloatBar* floatbar,
int unlock_resid, int unlock_resid_act,
int lock_resid, int lock_resid_act,
int x, int y, int h, int w)
{
Button* button;
button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid, unlock_resid_act, x, y, h, w);
if (!button)
return NULL;
button->unlocked_bmp = button->bmp;
button->unlocked_bmp_act = button->bmp_act;
button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
button->locked_bmp_act = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
return button;
}
static Button* floatbar_get_button(FloatBar* floatbar, int x, int y)
{
int i;
if (y > BUTTON_Y && y < BUTTON_Y + BUTTON_HEIGHT)
for (i = 0; i < BTN_MAX; i++)
if (x > floatbar->buttons[i]->x && x < floatbar->buttons[i]->x + floatbar->buttons[i]->w)
return floatbar->buttons[i];
return NULL;
}
static int floatbar_paint(FloatBar* floatbar, HDC hdc)
{
int i;
if (!floatbar->wfc->fullscreen)
return -1;
/* paint background */
SelectObject(floatbar->hdcmem, floatbar->background);
StretchBlt(hdc, 0, 0, BACKGROUND_W, BACKGROUND_H, floatbar->hdcmem, 0, 0, BACKGROUND_W, BACKGROUND_H, SRCCOPY);
/* paint buttons */
for (i = 0; i < BTN_MAX; i++)
button_paint(floatbar->buttons[i], hdc);
return 0;
}
static int floatbar_animation(FloatBar* floatbar, BOOL show)
{
SetTimer(floatbar->hwnd, show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE, 10, NULL);
floatbar->shown = show;
return 0;
}
LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
static int dragging = FALSE;
static int lbtn_dwn = FALSE;
static int btn_dwn_x = 0;
static FloatBar* floatbar;
static TRACKMOUSEEVENT tme;
PAINTSTRUCT ps;
Button* button;
HDC hdc;
int pos_x;
int pos_y;
int xScreen = GetSystemMetrics(SM_CXSCREEN);
switch(Msg)
{
case WM_CREATE:
floatbar = (FloatBar *)((CREATESTRUCT *)lParam)->lpCreateParams;
floatbar->hwnd = hWnd;
floatbar->parent = GetParent(hWnd);
GetWindowRect(floatbar->hwnd, &floatbar->rect);
floatbar->width = floatbar->rect.right - floatbar->rect.left;
floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
hdc = GetDC(hWnd);
floatbar->hdcmem = CreateCompatibleDC(hdc);
ReleaseDC(hWnd, hdc);
tme.cbSize = sizeof(TRACKMOUSEEVENT);
tme.dwFlags = TME_LEAVE;
tme.hwndTrack = hWnd;
tme.dwHoverTime = HOVER_DEFAULT;
SetTimer(hWnd, TIMER_HIDE, 3000, NULL);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
floatbar_paint(floatbar, hdc);
EndPaint(hWnd, &ps);
break;
case WM_LBUTTONDOWN:
pos_x = lParam & 0xffff;
pos_y = (lParam >> 16) & 0xffff;
button = floatbar_get_button(floatbar, pos_x, pos_y);
if (!button)
{
SetCapture(hWnd);
dragging = TRUE;
btn_dwn_x = lParam & 0xffff;
}
else
lbtn_dwn = TRUE;
break;
case WM_LBUTTONUP:
pos_x = lParam & 0xffff;
pos_y = (lParam >> 16) & 0xffff;
ReleaseCapture();
dragging = FALSE;
if (lbtn_dwn)
{
button = floatbar_get_button(floatbar, pos_x, pos_y);
if (button)
button_hit(button);
lbtn_dwn = FALSE;
}
break;
case WM_MOUSEMOVE:
KillTimer(hWnd, TIMER_HIDE);
pos_x = lParam & 0xffff;
pos_y = (lParam >> 16) & 0xffff;
if (!floatbar->shown)
floatbar_animation(floatbar, TRUE);
if (dragging)
{
floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x;
if (floatbar->rect.left < 0)
floatbar->rect.left = 0;
else if (floatbar->rect.left > xScreen - floatbar->width)
floatbar->rect.left = xScreen - floatbar->width;
MoveWindow(hWnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE);
}
else
{
int i;
for (i = 0; i < BTN_MAX; i++)
floatbar->buttons[i]->active = FALSE;
button = floatbar_get_button(floatbar, pos_x, pos_y);
if (button)
button->active = TRUE;
InvalidateRect(hWnd, NULL, FALSE);
UpdateWindow(hWnd);
}
TrackMouseEvent(&tme);
break;
case WM_CAPTURECHANGED:
dragging = FALSE;
break;
case WM_MOUSELEAVE:
{
int i;
for (i = 0; i < BTN_MAX; i++)
floatbar->buttons[i]->active = FALSE;
InvalidateRect(hWnd, NULL, FALSE);
UpdateWindow(hWnd);
SetTimer(hWnd, TIMER_HIDE, 3000, NULL);
break;
}
case WM_TIMER:
switch (wParam)
{
case TIMER_HIDE:
{
KillTimer(hWnd, TIMER_HIDE);
if (!floatbar->locked)
floatbar_animation(floatbar, FALSE);
break;
}
case TIMER_ANIMAT_SHOW:
{
static int y = 0;
MoveWindow(floatbar->hwnd, floatbar->rect.left, (y++ - floatbar->height), floatbar->width, floatbar->height, TRUE);
if (y == floatbar->height)
{
y = 0;
KillTimer(hWnd, wParam);
}
break;
}
case TIMER_ANIMAT_HIDE:
{
static int y = 0;
MoveWindow(floatbar->hwnd, floatbar->rect.left, -y++, floatbar->width, floatbar->height, TRUE);
if (y == floatbar->height)
{
y = 0;
KillTimer(hWnd, wParam);
}
break;
}
default:
break;
}
break;
case WM_DESTROY:
DeleteDC(floatbar->hdcmem);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, Msg, wParam, lParam);
}
return 0;
}
static FloatBar* floatbar_create(wfContext* wfc)
{
FloatBar* floatbar;
floatbar = (FloatBar *)malloc(sizeof(FloatBar));
if (!floatbar)
return NULL;
floatbar->locked = FALSE;
floatbar->shown = TRUE;
floatbar->hwnd = NULL;
floatbar->parent = wfc->hwnd;
floatbar->wfc = wfc;
floatbar->hdcmem = NULL;
floatbar->background = (HBITMAP)LoadImage(wfc->hInstance, MAKEINTRESOURCE(IDB_BACKGROUND), IMAGE_BITMAP, BACKGROUND_W, BACKGROUND_H, LR_DEFAULTCOLOR);
floatbar->buttons[0] = floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT, MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
floatbar->buttons[1] = floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT, RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT, CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
floatbar->buttons[3] = floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT, LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
return floatbar;
}
int floatbar_hide(FloatBar* floatbar)
{
MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->height, floatbar->width, floatbar->height, TRUE);
return 0;
}
int floatbar_show(FloatBar* floatbar)
{
MoveWindow(floatbar->hwnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE);
return 0;
}
void floatbar_window_create(wfContext *wfc)
{
WNDCLASSEX wnd_cls;
HWND barWnd;
int x = (GetSystemMetrics(SM_CXSCREEN) - BACKGROUND_W) / 2;
wnd_cls.cbSize = sizeof(WNDCLASSEX);
wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
wnd_cls.lpfnWndProc = floatbar_proc;
wnd_cls.cbClsExtra = 0;
wnd_cls.cbWndExtra = 0;
wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wnd_cls.hCursor = LoadCursor(wfc->hInstance, IDC_ARROW);
wnd_cls.hbrBackground = NULL;
wnd_cls.lpszMenuName = NULL;
wnd_cls.lpszClassName = L"floatbar";
wnd_cls.hInstance = wfc->hInstance;
wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
RegisterClassEx(&wnd_cls);
wfc->floatbar = floatbar_create(wfc);
barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W, BACKGROUND_H, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar);
if (barWnd == NULL)
return;
ShowWindow(barWnd, SW_SHOWNORMAL);
}

View File

@ -0,0 +1,30 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Windows Float Bar
*
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.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_FLOATBAR_H__
#define __WF_FLOATBAR_H__
typedef struct _FloatBar FloatBar;
typedef struct wf_context wfContext;
void floatbar_window_create(wfContext* wfc);
int floatbar_show(FloatBar* floatbar);
int floatbar_hide(FloatBar* floatbar);
#endif

View File

@ -322,6 +322,11 @@ void wf_toggle_fullscreen(wfContext* wfc)
wfc->disablewindowtracking = TRUE;
}
if (wfc->fullscreen)
floatbar_show(wfc->floatbar);
else
floatbar_hide(wfc->floatbar);
SetParent(wfc->hwnd, wfc->fullscreen ? NULL : wfc->hWndParent);
wf_resize_window(wfc);
ShowWindow(wfc->hwnd, SW_SHOW);
@ -515,12 +520,18 @@ void wf_gdi_polyline(wfContext* wfc, POLYLINE_ORDER* polyline)
if (polyline->numPoints > 0)
{
POINT temp;
temp.x = polyline->xStart;
temp.y = polyline->yStart;
pts = (POINT*) malloc(sizeof(POINT) * polyline->numPoints);
for (i = 0; i < (int) polyline->numPoints; i++)
{
pts[i].x = polyline->points[i].x;
pts[i].y = polyline->points[i].y;
temp.x += polyline->points[i].x;
temp.y += polyline->points[i].y;
pts[i].x = temp.x;
pts[i].y = temp.y;
if (wfc->drawing == wfc->primary)
wf_invalidate_region(wfc, pts[i].x, pts[i].y, pts[i].x + 1, pts[i].y + 1);

View File

@ -263,18 +263,16 @@ BOOL wf_pre_connect(freerdp* instance)
{
if (settings->UseMultimon)
{
settings->DesktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
settings->DesktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
desktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
desktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
}
else
{
settings->DesktopWidth = GetSystemMetrics(SM_CXSCREEN);
settings->DesktopHeight = GetSystemMetrics(SM_CYSCREEN);
desktopWidth = GetSystemMetrics(SM_CXSCREEN);
desktopHeight = GetSystemMetrics(SM_CYSCREEN);
}
}
desktopWidth = (desktopWidth + 3) & (~3);
if (desktopWidth != settings->DesktopWidth)
{
freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, desktopWidth);
@ -446,6 +444,7 @@ BOOL wf_post_connect(freerdp* instance)
freerdp_channels_post_connect(instance->context->channels, instance);
wf_cliprdr_init(wfc, instance->context->channels);
floatbar_window_create(wfc);
return TRUE;
}

View File

@ -37,6 +37,7 @@
#include <freerdp/codec/nsc.h>
#include <freerdp/client/file.h>
#include "wf_floatbar.h"
#include "wf_event.h"
#ifdef __cplusplus
@ -132,6 +133,7 @@ struct wf_context
int yCurrentScroll; // current vertical scroll value
int yMaxScroll; // maximum vertical scroll value
cliprdrContext *cliprdr_context;
FloatBar* floatbar;
};
typedef struct wf_context wfContext;

Binary file not shown.

View File

@ -539,8 +539,7 @@ xfWindow* xf_CreateWindow(xfContext* xfc, rdpWindow* wnd, int x, int y, int widt
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual,
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
CWBorderPixel | CWWinGravity | CWBitGravity, &xfc->attribs);
0, &xfc->attribs);
DEBUG_X11_LMS("Create window=0x%X rc={l=%d t=%d r=%d b=%d} w=%d h=%d rdp=0x%X",
(UINT32) window->handle, window->left, window->top, window->right, window->bottom,

View File

@ -866,8 +866,7 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name
int index;
assert(NULL != hostname);
assert(NULL != common_name);
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
fprintf(stderr, "@ WARNING: CERTIFICATE NAME MISMATCH! @\n");
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
@ -875,17 +874,14 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name
fprintf(stderr, "does not match %s given in the certificate:\n", alt_names_count < 1 ? "the name" : "any of the names");
fprintf(stderr, "Common Name (CN):\n");
fprintf(stderr, "\t%s\n", common_name ? common_name : "no CN found in certificate");
if (alt_names_count > 1)
if (alt_names_count > 0)
{
assert(NULL != alt_names);
fprintf(stderr, "Alternative names:\n");
if (alt_names_count > 1)
for (index = 0; index < alt_names_count; index++)
{
for (index = 0; index < alt_names_count; index++)
{
assert(alt_names[index]);
fprintf(stderr, "\t %s\n", alt_names[index]);
}
assert(alt_names[index]);
fprintf(stderr, "\t %s\n", alt_names[index]);
}
}
fprintf(stderr, "A valid certificate for the wrong name should NOT be trusted!\n");

View File

@ -165,48 +165,57 @@ DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
{
int length;
int vLength = 0;
char* env = NULL;
const char * penvb = envBlock;
char *foundEquals;
int nLength, fLength, lpNameLength;
if (!lpName || NULL == envBlock)
return 0;
lpNameLength = strlen(lpName);
if (0 == lpNameLength)
return 0;
while (*penvb && *(penvb+1))
{
length = strlen(penvb);
fLength = strlen(penvb);
foundEquals = strstr(penvb,"=");
if (foundEquals == NULL) {
if (foundEquals == NULL)
{
/* if no = sign is found the envBlock is broken */
return 0;
}
nLength = foundEquals - penvb;
if (nLength != lpNameLength)
{
penvb += (fLength +1);
continue;
}
#ifdef _WIN32
if (strnicmp(penvb,lpName,foundEquals - penvb) == 0) {
if (strnicmp(penvb,lpName,nLength) == 0)
#else
if (strncmp(penvb,lpName,foundEquals - penvb) == 0) {
if (strncmp(penvb,lpName,nLength) == 0)
#endif
if (*(penvb + (foundEquals - penvb)) == '=') {
// found variable ...
if (foundEquals == NULL) {
return 0;
} else {
env = foundEquals + 1;
break;
}
}
{
env = foundEquals + 1;
break;
}
penvb += (length +1);
penvb += (fLength +1);
}
if (!env)
return 0;
length = strlen(env);
vLength = strlen(env);
if ((length + 1 > nSize) || (!lpBuffer))
return length + 1;
if ((vLength + 1 > nSize) || (!lpBuffer))
return vLength + 1;
CopyMemory(lpBuffer, env, length + 1);
CopyMemory(lpBuffer, env, vLength + 1);
return length;
return vLength;
}
@ -252,33 +261,23 @@ BOOL SetEnvironmentVariableEBA(LPSTR * envBlock,LPCSTR lpName, LPCSTR lpValue)
if (lpValue)
{
length = strlen(lpName) + strlen(lpValue) + 1;
envstr = (char*) malloc(length + 1);
sprintf_s(envstr, length + 1, "%s=%s", lpName, lpValue);
envstr[length] = '\0';
newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr);
free(envstr);
if (*envBlock != NULL)
free(*envBlock);
*envBlock = newEB;
return TRUE;
length = strlen(lpName) + strlen(lpValue) + 2; /* +2 because of = and \0 */
envstr = (char*) malloc(length + 1); /* +1 because of closing \0 */
sprintf_s(envstr, length, "%s=%s", lpName, lpValue);
}
else
{
length = strlen(lpName) + 1;
envstr = (char*) malloc(length + 1);
sprintf_s(envstr, length + 1, "%s=", lpName);
envstr[length] = '\0';
newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr);
free(envstr);
if (*envBlock != NULL)
free(*envBlock);
*envBlock = newEB;
return TRUE;
length = strlen(lpName) + 2; /* +2 because of = and \0 */
envstr = (char*) malloc(length + 1); /* +1 because of closing \0 */
sprintf_s(envstr, length, "%s=", lpName);
}
envstr[length] = '\0';
newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr);
free(envstr);
if (*envBlock != NULL)
free(*envBlock);
*envBlock = newEB;
return TRUE;
}
@ -364,6 +363,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
// first build an char ** of the merge env strings
mergeStrings = (LPCSTR*) malloc(mergeArraySize * sizeof(char *));
ZeroMemory(mergeStrings,mergeArraySize * sizeof(char *));
mergeStringLenth = 0;
cp = merge;

View File

@ -13,8 +13,12 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
LPTCH lpszEnvironmentBlock = "SHELL=123\0test=1\0test1=2\0DISPLAY=WINPR_TEST_VALUE\0\0";
LPTCH lpszEnvironmentBlockNew = NULL;
/* Get length of an variable */
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", NULL, 0);
if (0 == length)
return -1;
/* Get the variable itself */
p = (LPSTR) malloc(length);
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", p, length);
@ -22,14 +26,47 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
if (strcmp(p, "WINPR_TEST_VALUE") != 0)
{
free(p);
return -1;
}
free(p);
lpszEnvironmentBlockNew = (LPTCH) malloc(1024);
memcpy(lpszEnvironmentBlockNew,lpszEnvironmentBlock,56);
/* Get length of an non-existing variable */
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"BLA", NULL, 0);
if (0 != length)
{
printf("Unset variable returned\n");
return -1;
}
/* Get length of an similar called variables */
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"XDISPLAY", NULL, 0);
if (0 != length)
{
printf("Similar named variable returned (XDISPLAY, length %d)\n", length);
return -1;
}
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAYX", NULL, 0);
if (0 != length)
{
printf("Similar named variable returned (DISPLAYX, length %d)\n", length);
return -1;
}
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLA", NULL, 0);
if (0 != length)
{
printf("Similar named variable returned (DISPLA, length %d)\n", length);
return -1;
}
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"ISPLAY", NULL, 0);
if (0 != length)
{
printf("Similar named variable returned (ISPLAY, length %d)\n", length);
return -1;
}
/* Set variable in empty environment block */
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5"))
{
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
@ -44,13 +81,12 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
return -1;
}
}
//free(lpszEnvironmentBlockNew);
/* Clear variable */
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", NULL))
{
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
{
free(lpszEnvironmentBlockNew);
return -1;
}
else
@ -58,6 +94,34 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
// not found .. this is expected
}
}
free(lpszEnvironmentBlockNew);
lpszEnvironmentBlockNew = (LPTCH) malloc(1024);
memcpy(lpszEnvironmentBlockNew,lpszEnvironmentBlock,56);
/* Set variable in empty environment block */
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5"))
{
if (0 != GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"testr", test, 1023))
{
printf("GetEnvironmentVariableEBA returned unset variable\n");
free(lpszEnvironmentBlockNew);
return -1;
}
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
{
if (strcmp(test,"5") != 0)
{
free(lpszEnvironmentBlockNew);
return -1;
}
}
else
{
free(lpszEnvironmentBlockNew);
return -1;
}
}
free(lpszEnvironmentBlockNew);
#endif

View File

@ -251,6 +251,10 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
if (token->UserId)
setuid((uid_t) token->UserId);
/* TODO: add better cwd handling and error checking */
if (lpCurrentDirectory && strlen(lpCurrentDirectory) > 0)
chdir(lpCurrentDirectory);
}
if (execve(filename, pArgs, envp) < 0)