From 600fa04bec03bb192408b766c9869c7ab274ec5c Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Mon, 10 Feb 2014 14:43:58 +0800 Subject: [PATCH 01/28] wfreerdp: fix gdi polyline mistake. --- client/Windows/wf_gdi.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index 16359d858..b9cba56d5 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -521,12 +521,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); From 1404532d702ccd4f84dbf0ae7c10860b517c64cd Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Tue, 11 Feb 2014 17:28:12 +0800 Subject: [PATCH 02/28] drdynvc: fix free invalid pointer. --- channels/drdynvc/client/dvcman.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/channels/drdynvc/client/dvcman.c b/channels/drdynvc/client/dvcman.c index 954247d02..c1faed175 100644 --- a/channels/drdynvc/client/dvcman.c +++ b/channels/drdynvc/client/dvcman.c @@ -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; } From c9a9f5b4382a1a3efb2bea2964d8408bf6236304 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Tue, 11 Feb 2014 17:30:57 +0800 Subject: [PATCH 03/28] wfreerdp: add winmm audin subsystem. --- channels/audin/client/CMakeLists.txt | 4 + channels/audin/client/audin_main.c | 9 + channels/audin/client/winmm/CMakeLists.txt | 41 +++ channels/audin/client/winmm/audin_winmm.c | 309 +++++++++++++++++++++ 4 files changed, 363 insertions(+) create mode 100644 channels/audin/client/winmm/CMakeLists.txt create mode 100644 channels/audin/client/winmm/audin_winmm.c diff --git a/channels/audin/client/CMakeLists.txt b/channels/audin/client/CMakeLists.txt index 2a370743c..e126eab0d 100644 --- a/channels/audin/client/CMakeLists.txt +++ b/channels/audin/client/CMakeLists.txt @@ -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() diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index b620126a7..2e545fb59 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -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."); diff --git a/channels/audin/client/winmm/CMakeLists.txt b/channels/audin/client/winmm/CMakeLists.txt new file mode 100644 index 000000000..10db102ad --- /dev/null +++ b/channels/audin/client/winmm/CMakeLists.txt @@ -0,0 +1,41 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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") diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c new file mode 100644 index 000000000..8881c04b0 --- /dev/null +++ b/channels/audin/client/winmm/audin_winmm.c @@ -0,0 +1,309 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Audio Input Redirection Virtual Channel - WinMM implementation + * + * Copyright 2013 Zhang Zhaolong + * + * 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 +#include +#include + +#include +#include + +#include +#include +#include + +#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, "", 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; +} From 5157555d5bb9ab55b6f449e9afb5e128d59fc89b Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Wed, 12 Feb 2014 11:34:33 +0800 Subject: [PATCH 04/28] drive: minor code formatting. --- channels/drive/client/drive_file.c | 14 ++++---- channels/drive/client/drive_main.c | 52 +++++++++++++++--------------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index edab10a45..b3f106a9f 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -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,7 +265,7 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat #ifndef WIN32 if (largeFile) { - oflag |= O_LARGEFILE; + oflag |= O_LARGEFILE; } #endif file->fd = OPEN(file->fullpath, oflag, mode); @@ -426,7 +426,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 +456,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,7 +474,7 @@ 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 */ @@ -510,7 +510,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN free(s); /* TODO rename does not work on win32 */ - if (rename(file->fullpath, fullpath) == 0) + if (rename(file->fullpath, fullpath) == 0) { drive_file_set_fullpath(file, fullpath); } diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index e81992764..c7e9afb72 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -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; +} From f67fa723869006d5a8d989c1744b3e6b4333b1b6 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Wed, 12 Feb 2014 17:45:17 +0800 Subject: [PATCH 05/28] drive: win: fix file open flag. --- channels/drive/client/drive_file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index b3f106a9f..48e0a1794 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -267,6 +267,8 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat { oflag |= O_LARGEFILE; } +#else + oflag |= O_BINARY; #endif file->fd = OPEN(file->fullpath, oflag, mode); From 0adb22f3058cad26a1ffc506489d1b8575b75b09 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Wed, 12 Feb 2014 17:52:28 +0800 Subject: [PATCH 06/28] drive: win: add 64 bits support. --- channels/drive/client/drive_file.c | 2 ++ channels/drive/client/drive_file.h | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 48e0a1794..9423c522e 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -482,9 +482,11 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN /* 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: diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h index 769a18def..28ac5780a 100644 --- a/channels/drive/client/drive_file.h +++ b/channels/drive/client/drive_file.h @@ -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 From b1fe93bf4b52665f2bb35ff0c1ec28f5431d98b6 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Wed, 12 Feb 2014 18:13:42 +0800 Subject: [PATCH 07/28] drive: win: add file rename support. --- channels/drive/client/drive_file.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 9423c522e..ec5ee0a45 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -513,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 */ +#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 { From dd88d7194e701a8dac76ef8023894c9b6ed355c4 Mon Sep 17 00:00:00 2001 From: Dan Bungert Date: Wed, 12 Feb 2014 16:01:50 -0700 Subject: [PATCH 08/28] xfreerdp: Fix disappearing rail windows. Rail windows currently disappear on resize and on implicit resize (calc changing view type from standard to scientific). The bitmask that we send to XCreateWindow() must match the actual attributes that we are sending (see xf_create_window()). Because of this we were unintentionally zeroing out some of the window attributes rather than using their default values. --- client/X11/xf_window.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c index b428048a5..5b7c96b17 100644 --- a/client/X11/xf_window.c +++ b/client/X11/xf_window.c @@ -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, From 909800eca0afccd46f91888ff354d6cf58e3de24 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 13 Feb 2014 12:24:09 +0100 Subject: [PATCH 09/28] winpr: fixed problems Set/GetEnvironmentVariableEBA * valgrind: fixed invalid read * invalid or damaged environment blocked caused endless loop * envblock created in SetEnvironmentVariableEBA lacked a trailing '\0' which could lead to a damaged environment block --- winpr/libwinpr/environment/environment.c | 43 ++++++++++-------------- 1 file changed, 18 insertions(+), 25 deletions(-) diff --git a/winpr/libwinpr/environment/environment.c b/winpr/libwinpr/environment/environment.c index 7e998e998..2be5fcd80 100644 --- a/winpr/libwinpr/environment/environment.c +++ b/winpr/libwinpr/environment/environment.c @@ -165,17 +165,19 @@ DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) { - int length; + int length = 0; char* env = NULL; const char * penvb = envBlock; char *foundEquals; while (*penvb && *(penvb+1)) { + length = strlen(penvb); foundEquals = strstr(penvb,"="); if (foundEquals == NULL) { - continue; + /* if no = sign is found the envBlock is broken */ + return 0; } #ifdef _WIN32 if (strnicmp(penvb,lpName,foundEquals - penvb) == 0) { @@ -252,33 +254,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 +356,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; From 24c67267a3dbb8e454fda39e71372dc973ae0196 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 13 Feb 2014 14:26:26 +0100 Subject: [PATCH 10/28] winpr: add cwd support in CreateProcess* --- winpr/libwinpr/thread/process.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/winpr/libwinpr/thread/process.c b/winpr/libwinpr/thread/process.c index d3945f28e..f6cdb24f6 100644 --- a/winpr/libwinpr/thread/process.c +++ b/winpr/libwinpr/thread/process.c @@ -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) From 7205e348eb7275bce34ca9f611f4fc09bd5f5725 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Fri, 14 Feb 2014 15:09:55 +0800 Subject: [PATCH 11/28] drive: win: add hotplug support. --- channels/rdpdr/client/devman.c | 9 ++ channels/rdpdr/client/devman.h | 1 + channels/rdpdr/client/rdpdr_main.c | 207 +++++++++++++++++++++++++++++ channels/rdpdr/client/rdpdr_main.h | 6 + 4 files changed, 223 insertions(+) diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 7ff21273f..8ecaf4dd1 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -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; diff --git a/channels/rdpdr/client/devman.h b/channels/rdpdr/client/devman.h index dd2126d91..9164052cd 100644 --- a/channels/rdpdr/client/devman.h +++ b/channels/rdpdr/client/devman.h @@ -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); diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index af21f5a26..229a3b8c4 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -33,6 +33,11 @@ #include #include +#ifdef _WIN32 +#include +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif @@ -44,6 +49,201 @@ #include "rdpdr_main.h" +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 *dev; + 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++) + { + dev = (DEVICE *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); + if (dev->name[0] == drive_name_upper || dev->name[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 + +static void* drive_hotplug_thread_func(void *arg) +{ + +} + +static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) +{ + +} + +#endif + + static void rdpdr_process_connect(rdpdrPlugin* rdpdr) { int index; @@ -58,6 +258,11 @@ static void rdpdr_process_connect(rdpdrPlugin* rdpdr) for (index = 0; index < settings->DeviceCount; index++) { device = settings->DeviceArray[index]; + if (strcmp(device->Name, "*") == 0) + { + CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)drive_hotplug_thread_func, rdpdr, 0, NULL); + continue; + } devman_load_device_service(rdpdr->devman, device); } } @@ -493,6 +698,8 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr) MessagePipe_Free(rdpdr->MsgPipe); CloseHandle(rdpdr->thread); + drive_hotplug_thread_terminate(rdpdr); + rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle); if (rdpdr->data_in) diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index f0699fce9..c66621547 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -52,6 +52,12 @@ struct rdpdr_plugin UINT16 versionMinor; UINT16 clientID; char computerName[256]; + + /* hotplug support */ +#ifdef _WIN32 + HWND hotplug_wnd; +#else +#endif }; int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s); From e82d2f9e14e6347b95fc660375ea13980e79e984 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Fri, 14 Feb 2014 16:35:44 +0800 Subject: [PATCH 12/28] drive: win: fix use drive name(path) to find out the device plugged out. --- channels/rdpdr/client/rdpdr_main.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 229a3b8c4..78ab0741e 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -49,6 +49,14 @@ #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[]) @@ -125,7 +133,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) char drive_name_upper, drive_name_lower; ULONG_PTR *keys; - DEVICE *dev; + DEVICE_DRIVE_EXT *device_ext; UINT32 ids[1]; for (i = 0; i < 26; i++) @@ -139,8 +147,8 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) for (j = 0; j < count; j++) { - dev = (DEVICE *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]); - if (dev->name[0] == drive_name_upper || dev->name[0] == drive_name_lower) + 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]; @@ -165,7 +173,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) return DefWindowProc(hWnd, Msg, wParam, lParam); } -static void* drive_hotplug_thread_func(void *arg) +static void* drive_hotplug_thread_func(void* arg) { rdpdrPlugin *rdpdr; WNDCLASSEX wnd_cls; @@ -231,7 +239,7 @@ static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) #else -static void* drive_hotplug_thread_func(void *arg) +static void* drive_hotplug_thread_func(void* arg) { } From ee5814cbc28731b110b15e51830648e231b65782 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Fri, 14 Feb 2014 10:59:10 +0100 Subject: [PATCH 13/28] winpr-env: extended GetSetEB ctest Check if Get function only returns values for the exact variable name --- .../test/TestEnvironmentGetSetEB.c | 74 +++++++++++++++++-- 1 file changed, 69 insertions(+), 5 deletions(-) diff --git a/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c b/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c index dbf248a6a..4e27f8e41 100644 --- a/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c +++ b/winpr/libwinpr/environment/test/TestEnvironmentGetSetEB.c @@ -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 From 591a8192e00b4e4f51613fb6c58824a42354d888 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Fri, 14 Feb 2014 11:00:13 +0100 Subject: [PATCH 14/28] winpr-env: fix in GetEnvironmentVariableEBA GetEnvironmentVariableEBA didn't do exact matching of the requested variable name. If a variable with similar but shorter name was set in the environment block it was returned. For example if HOME was set in the environment block and HOMEX was requested the value of HOME was returned. --- winpr/libwinpr/environment/environment.c | 57 +++++++++++++----------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/winpr/libwinpr/environment/environment.c b/winpr/libwinpr/environment/environment.c index 2be5fcd80..5c45ccb02 100644 --- a/winpr/libwinpr/environment/environment.c +++ b/winpr/libwinpr/environment/environment.c @@ -165,50 +165,57 @@ DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize) { - int length = 0; + int vLength = 0; char* env = NULL; const char * penvb = envBlock; char *foundEquals; + int nLength, fLength, lpNameLength; + + if (!lpName) + 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; } -#ifdef _WIN32 - if (strnicmp(penvb,lpName,foundEquals - penvb) == 0) { -#else - if (strncmp(penvb,lpName,foundEquals - penvb) == 0) { -#endif - if (*(penvb + (foundEquals - penvb)) == '=') { - // found variable ... - if (foundEquals == NULL) { - return 0; - } else { - env = foundEquals + 1; - break; - } - } + nLength = foundEquals - penvb; + if (nLength != lpNameLength) + { + penvb += (fLength +1); + continue; } - penvb += (length +1); +#ifdef _WIN32 + if (strnicmp(penvb,lpName,nLength) == 0) +#else + if (strncmp(penvb,lpName,nLength) == 0) +#endif + { + env = foundEquals + 1; + break; + } + 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; } From 5a74bd7bdb7ddc181ebaf456263c9706620a6f98 Mon Sep 17 00:00:00 2001 From: Christian Hofstaedtler Date: Fri, 14 Feb 2014 15:25:48 +0100 Subject: [PATCH 15/28] Fix assertion abort when no CN is present in certificate Triggered by Windows Server 2012 Admin-Mode with MS-recommended AD CA Certificate setup, which would cause the CN to be absent, and a single subjectAltName to be present. --- libfreerdp/crypto/tls.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index 4fe93ee94..cd78e2d99 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -865,8 +865,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"); @@ -874,17 +873,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"); From f924190d8b43d226167a220abf058813ad475cbf Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 20 Feb 2014 17:42:02 +0800 Subject: [PATCH 16/28] drive: linux: add hotplug support. --- channels/rdpdr/client/rdpdr_main.c | 233 ++++++++++++++++++++++++++++- channels/rdpdr/client/rdpdr_main.h | 2 + 2 files changed, 233 insertions(+), 2 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 78ab0741e..ccae3f8dc 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -36,6 +36,10 @@ #ifdef _WIN32 #include #include +#else +#include +#include +#include #endif #ifdef HAVE_UNISTD_H @@ -239,14 +243,237 @@ static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) #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 @@ -268,7 +495,7 @@ static void rdpdr_process_connect(rdpdrPlugin* rdpdr) device = settings->DeviceArray[index]; if (strcmp(device->Name, "*") == 0) { - CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)drive_hotplug_thread_func, rdpdr, 0, NULL); + rdpdr->hotplug_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)drive_hotplug_thread_func, rdpdr, 0, NULL); continue; } devman_load_device_service(rdpdr->devman, device); @@ -708,6 +935,8 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr) drive_hotplug_thread_terminate(rdpdr); + WaitForSingleObject(rdpdr->hotplug_thread, INFINITE); + rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle); if (rdpdr->data_in) diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index c66621547..e3a56c1d7 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -54,9 +54,11 @@ struct rdpdr_plugin char computerName[256]; /* hotplug support */ + HANDLE hotplug_thread; #ifdef _WIN32 HWND hotplug_wnd; #else + HANDLE stop_event; #endif }; From 4fa2ca3062dcac947a251a1f6815e2b5fe1c1b54 Mon Sep 17 00:00:00 2001 From: Vic Lee Date: Thu, 20 Feb 2014 23:33:27 +0800 Subject: [PATCH 17/28] rdpsnd-server: fix broken message parsing. --- channels/rdpsnd/server/rdpsnd_main.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/channels/rdpsnd/server/rdpsnd_main.c b/channels/rdpsnd/server/rdpsnd_main.c index 4bc7107d5..f56d407e4 100644 --- a/channels/rdpsnd/server/rdpsnd_main.c +++ b/channels/rdpsnd/server/rdpsnd_main.c @@ -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; From 297247042d12bf86bba866b077b17fbb1ad279b6 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 20 Feb 2014 18:29:16 +0100 Subject: [PATCH 18/28] winpr-env: fix in GetEnvironmentVariableEBA * also fix cases where the provided env block is NULL --- winpr/libwinpr/environment/environment.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/environment/environment.c b/winpr/libwinpr/environment/environment.c index 5c45ccb02..e56c0b1e2 100644 --- a/winpr/libwinpr/environment/environment.c +++ b/winpr/libwinpr/environment/environment.c @@ -171,7 +171,7 @@ DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, char *foundEquals; int nLength, fLength, lpNameLength; - if (!lpName) + if (!lpName || NULL == envBlock) return 0; lpNameLength = strlen(lpName); From 07c0d8267195163d3fe8476c31abee1e5ec01640 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Wed, 26 Feb 2014 11:34:48 +0800 Subject: [PATCH 19/28] wfreerdp: fix fullscreen. --- client/Windows/wf_interface.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 6e1b341bd..a882ce99b 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -265,18 +265,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); From 131627fb2b05222cf82528898b417a978bf409d9 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 11:37:17 +0800 Subject: [PATCH 20/28] wfreerdp: floatbar: add bmp resources. --- client/Windows/resource/bg.bmp | Bin 0 -> 50630 bytes client/Windows/resource/close.bmp | Bin 0 -> 1782 bytes client/Windows/resource/close_active.bmp | Bin 0 -> 1782 bytes client/Windows/resource/lock.bmp | Bin 0 -> 1782 bytes client/Windows/resource/lock_active.bmp | Bin 0 -> 1782 bytes client/Windows/resource/minimize.bmp | Bin 0 -> 1782 bytes client/Windows/resource/minimize_active.bmp | Bin 0 -> 1782 bytes client/Windows/resource/restore.bmp | Bin 0 -> 1782 bytes client/Windows/resource/restore_active.bmp | Bin 0 -> 1782 bytes client/Windows/resource/unlock.bmp | Bin 0 -> 1782 bytes client/Windows/resource/unlock_active.bmp | Bin 0 -> 1782 bytes 11 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 client/Windows/resource/bg.bmp create mode 100644 client/Windows/resource/close.bmp create mode 100644 client/Windows/resource/close_active.bmp create mode 100644 client/Windows/resource/lock.bmp create mode 100644 client/Windows/resource/lock_active.bmp create mode 100644 client/Windows/resource/minimize.bmp create mode 100644 client/Windows/resource/minimize_active.bmp create mode 100644 client/Windows/resource/restore.bmp create mode 100644 client/Windows/resource/restore_active.bmp create mode 100644 client/Windows/resource/unlock.bmp create mode 100644 client/Windows/resource/unlock_active.bmp diff --git a/client/Windows/resource/bg.bmp b/client/Windows/resource/bg.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c97ef5d99e633dcec215dd3a09aa17d88e465914 GIT binary patch literal 50630 zcmeI!v28*@5Jk~7DWMY*aw?zzB!}*Tf?R@|!F74{DPf}bbP#+bkXEZR!JWtV-)kMO z`+nZ`=j*iAb$@@X%klfq{{Qp*{v1E-$Mg5*O@IIa0tC_p^i0kP5FkLHK|s$MrkK7} zxjz8{1m*&Ire_2Q5FpSXpl1zJobNSGAV7dXx`3YP836(W2s8-jS;G|5w<`B1K!Ctp zK+p7y009C78U*yLVT$v;#t8%n5J(r$Gd&|ffB=C80X=J&V)|C){sagRm<#Bco)I8G zfIx$Qo;6HyzSlT`009E&0(z!r1PBly&>)~^4O2|ts@$Id0RnRYJ<~G+1PBml5YV%R zDbDvAClDY&AYDMu^o#%j0t6Za^sHfu>06ci6CglfE}&<6Mt}eT0u2Is)-c8SUgHD; z1PG)H=$W1oAV7dXgMgkjOfh|{a(@B@2+RfaOwR}qAV8o&K+hVcINxiWK!5;&bOAln xGXew%5NHt4vxX_AZ&mJ3fB=EHfS&0Y0RjXFGzjQf!xZOxjS~nEAdoJw{sDGtDfR#W literal 0 HcmV?d00001 diff --git a/client/Windows/resource/close.bmp b/client/Windows/resource/close.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8fce91657de476490e19b7d06afb05defdcc5d60 GIT binary patch literal 1782 zcmZ?r{l>-s24+A~1BfM{m=VlkU^oDj7vhFsutFe_vOr@LjfMa`1pb4;v`Z;)5g;2P z2p1uS0nq{^Ax6Os0g4c#9j*phBN`j7hDZjoc8K$UB1Gy%Q-*95RSY59J!me0m;)q9 dbrqUMWMk3%j-QL^5x7zKHIB-Th5#8M004|51f2i? literal 0 HcmV?d00001 diff --git a/client/Windows/resource/close_active.bmp b/client/Windows/resource/close_active.bmp new file mode 100644 index 0000000000000000000000000000000000000000..2c58a3de6c700b807aefc811c882094c6995ddea GIT binary patch literal 1782 zcmZ?r{l>-s24+A~1BfM{m=VlkU^oDj7vhFsutFe_vOr@LjfMa`1Xh6ooC{%K6+}~m z#)W7Bl5lZM5x5k72C_zEHhx`LW#QT(46JI16oeZ^q-s24+A~1BfM{m=VlkU^oDjKf(vWV1+;;Wr4;h8fGEz|Nnog_-Htp1M~|n yKvG!YG6X12k~wh2a0B5Y-s24+A~1BfM{m=VlkU^oDjKf(vWV1+;;Wr4;h8fGD|YSk*L_-Htp1M~|n yKvG!YG6X12k~wh2a0B5Y-s24+A~1BfM{m=VlkU^oDj7vhFsutFe_vOr@LjfTKz2oMZ`|3m-s24+A~1BfM{m=VlkU^oDj7vhFsutFe_vOr@LjfTKz2oMZ`RYU-Sh5!{1 RVazIG%o$ZP8Umvs000gEx&Z(H literal 0 HcmV?d00001 diff --git a/client/Windows/resource/restore.bmp b/client/Windows/resource/restore.bmp new file mode 100644 index 0000000000000000000000000000000000000000..d74eddf23dd8773023580eda5c9479131de942bb GIT binary patch literal 1782 zcmZ?r{l>-s24+A~1BfM{m=VlkU^oDjKf(vWV1+;;Wr4;h8VvzR2>izYV<%I0?6cBnDhNoI#TI MQN^PnKx7C20Qofl%K!iX literal 0 HcmV?d00001 diff --git a/client/Windows/resource/restore_active.bmp b/client/Windows/resource/restore_active.bmp new file mode 100644 index 0000000000000000000000000000000000000000..f88bc4d9a013a411224d3749d6eb8f0dbe8332da GIT binary patch literal 1782 zcmZ?r{l>-s24+A~1BfM{m=VlkU^oDjKf(vWV1+;;Wr4;h8VvzR2&}>YV<%I0?6cBnDhNoI#TI MQN^PnKx7C204vJR?EnA( literal 0 HcmV?d00001 diff --git a/client/Windows/resource/unlock.bmp b/client/Windows/resource/unlock.bmp new file mode 100644 index 0000000000000000000000000000000000000000..8359ae7cc2846df3e472ba448caa27fa0534413a GIT binary patch literal 1782 zcmZ?r{l>-s24+A~1BfM{m=VlkU^oDjKf(vWV1+;;Wr4;h!W9B(^VD%k4R7)PU_iMa zX=D!B#zHirkwkhEO&2DYNOO>tVHyGyK~_K{8)6PzF&Y;xPLM&iMl_SDWe%FLqukLD HKnno?z$NlC literal 0 HcmV?d00001 diff --git a/client/Windows/resource/unlock_active.bmp b/client/Windows/resource/unlock_active.bmp new file mode 100644 index 0000000000000000000000000000000000000000..59d730d6e41ffb3ced25bfbac4ed19e17d0f3355 GIT binary patch literal 1782 zcmZ?r{l>-s24+A~1BfM{m=VlkU^oDjKf(vWV1+;;Wr4;h!W9B(^VD%k4R7&PU_iMa zX=D!B#zHirkwkhEO&2DYNOO>tVHyGyK~_K{8)6PzF&Y;xPLM&iMl_SDWe%FLqukLD HKnno?Ny5oo literal 0 HcmV?d00001 From 4a6c2ecfce6a27d731b9c230e5521d875e355d72 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 11:38:21 +0800 Subject: [PATCH 21/28] wfreerdp: floatbar: add bmp resources ids. --- client/Windows/resource.h | 13 ++++++++++++- client/Windows/wfreerdp.rc | Bin 180 -> 1804 bytes 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/client/Windows/resource.h b/client/Windows/resource.h index 5ee440fa5..89c1e79ba 100644 --- a/client/Windows/resource.h +++ b/client/Windows/resource.h @@ -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 diff --git a/client/Windows/wfreerdp.rc b/client/Windows/wfreerdp.rc index ef912b2d7b8a2c48d65c63e0f0d52ccd141f70ea..135f64104a0249fd38ff5706b36ee448e6540e72 100644 GIT binary patch literal 1804 zcmcJQ-A=+l5QWdRiSI!0-o!_spu{MY0NxmqhMz_off9ba;Nj6TiyJ82A-x#WOt#&f z_Iy3lo&Fqdaf3T#SYnDfc9y(4xis;$oP&&MZ<<-;p&u;BE#O*qzX~ud>USm{SQ%sF)Ott-?z&5%4$j7 z%HE&P*znEy)lBiF)XtNH9r84`Bvl-eZ`reXit=c~wd2me?$SAp?vy=E6{nicr-8cf zj;`6TNq@}Q6Qvi1_T7m^cd5p%WzmmLELB|U)1LvmV9ZXbbto&c<9}mIr{pZ`RFOw> M%f_i9&o#Gx0ibr_$N&HU delta 6 NcmeC-+rl_u3jhc^0+av% From 9f6dbed05ba384f2982edf72bc9581298a746668 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 11:40:21 +0800 Subject: [PATCH 22/28] wfreerdp: floatbar: add implementation. --- client/Windows/wf_floatbar.c | 490 +++++++++++++++++++++++++++++++++++ client/Windows/wf_floatbar.h | 30 +++ 2 files changed, 520 insertions(+) create mode 100644 client/Windows/wf_floatbar.c create mode 100644 client/Windows/wf_floatbar.h diff --git a/client/Windows/wf_floatbar.c b/client/Windows/wf_floatbar.c new file mode 100644 index 000000000..0f0512c48 --- /dev/null +++ b/client/Windows/wf_floatbar.c @@ -0,0 +1,490 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Windows Float Bar + * + * Copyright 2013 Zhang Zhaolong + * + * 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 +#include + +#include "wf_interface.h" +#include "wf_floatbar.h" +#include "wf_window.h" +#include "wf_gdi.h" +#include "resource.h" + +typedef struct _Button Button; + +/* Button Type */ +#define BUTTON_MINIMIZE 1 +#define BUTTON_RESTORE 2 +#define BUTTON_CLOSE 3 +#define BUTTON_LOCKPIN 4 +#define BTN_MAX 4 + +/* bmp size */ +#define BACKGROUND_X 581 +#define BACKGROUND_Y 29 +#define LOCK_X 13 +#define MINIMIZE_X (BACKGROUND_X - 91) +#define CLOSE_X (BACKGROUND_X - 37) +#define RESTORE_X (BACKGROUND_X - 64) + +#define BUTTON_Y 2 +#define BUTTON_WIDTH 24 +#define BUTTON_HEIGHT 24 + +struct _Button { + FloatBar* float_bar; + 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; + HBITMAP background; +}; + +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; +} + +static int button_hit(Button* button) +{ + FloatBar* floatbar = button->float_bar; + + 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->float_bar->hwnd, NULL, FALSE); + UpdateWindow(button->float_bar->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) +{ + FloatBar* floatbar = button->float_bar; + HDC hDC = GetDC(floatbar->hwnd); + HDC hMemDC = CreateCompatibleDC(hDC); + HBITMAP hOldBitmap; + BITMAP bm; + + hOldBitmap = (HBITMAP)SelectObject(hMemDC, button->active ? button->bmp_act : button->bmp); + + StretchBlt(hDC, button->x, button->y, button->w, button->h, hMemDC, 0, 0, button->w, button->h, SRCCOPY); + + SelectObject(hMemDC, hOldBitmap); + + DeleteDC(hMemDC); + ReleaseDC(floatbar->hwnd, hDC); + + return 0; +} + +static Button* float_bar_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->float_bar = 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* float_bar_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 = float_bar_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* float_bar_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 float_bar_paint(FloatBar* floatbar) +{ + int i; + HDC hDC; + HDC hMemDC; + HBITMAP hOldBitmap; + BITMAP bm; + + if (!floatbar->wfc->fullscreen) + return -1; + + /* paint background */ + hDC = GetDC(floatbar->hwnd); + hMemDC = CreateCompatibleDC(hDC); + GetObject(floatbar->background, sizeof(bm), &bm); + + hOldBitmap = (HBITMAP)SelectObject(hMemDC, floatbar->background); + StretchBlt(hDC, 0, 0, BACKGROUND_X, BACKGROUND_Y, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); + (HBITMAP)SelectObject(hMemDC, hOldBitmap); + + DeleteDC(hMemDC); + ReleaseDC(floatbar->hwnd, hDC); + + /* paint buttons */ + for (i = 0; i < BTN_MAX; i++) + button_paint(floatbar->buttons[i]); + + return 0; +} + +#define TIMER_HIDE 1 +#define TIMER_ANIMAT_SHOW 2 +#define TIMER_ANIMAT_HIDE 3 + +static int float_bar_animation(FloatBar* floatbar, BOOL show) +{ + LONG width, height, y; + + SetTimer(floatbar->hwnd, show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE, 10, NULL); + + floatbar->shown = show; + + return 0; +} + +LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +{ + PAINTSTRUCT ps; + RECT rect; + static int dragging = FALSE; + static int lbtn_dwn = FALSE; + static int btn_dwn_x = 0; + + int nWidth, nHeight; + int drag_left = 0; + int xScreen = GetSystemMetrics(SM_CXSCREEN); + HWND hParentWnd = GetParent(hWnd); + + static FloatBar* floatbar; + Button* button; + int pos_x; + int pos_y; + + TRACKMOUSEEVENT tme; + + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + + GetWindowRect(hWnd, &rect); + nWidth = rect.right - rect.left; + nHeight = rect.bottom - rect.top; + + switch(Msg) + { + case WM_CREATE: + floatbar = (FloatBar *)((CREATESTRUCT *)lParam)->lpCreateParams; + floatbar->hwnd = hWnd; + floatbar->parent = hParentWnd; + GetWindowRect(floatbar->hwnd, &floatbar->rect); + floatbar->width = floatbar->rect.right - floatbar->rect.left; + floatbar->height = floatbar->rect.bottom - floatbar->rect.top; + SetTimer(hWnd, TIMER_HIDE, 3000, NULL); + break; + + case WM_PAINT: + BeginPaint(hWnd, &ps); + float_bar_paint(floatbar); + EndPaint(hWnd, &ps); + break; + + case WM_LBUTTONDOWN: + pos_x = lParam & 0xffff; + pos_y = (lParam >> 16) & 0xffff; + + button = float_bar_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 = float_bar_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) + float_bar_animation(floatbar, TRUE); + + if (dragging) + { + drag_left = rect.left + (lParam & 0xffff) - btn_dwn_x; + + if (drag_left < 0) + drag_left = 0; + else if (drag_left > xScreen - floatbar->width) + drag_left = xScreen - floatbar->width; + + MoveWindow(hWnd, drag_left, rect.top, floatbar->width, floatbar->height, TRUE); + } + else + { + int i; + + for (i = 0; i < BTN_MAX; i++) + floatbar->buttons[i]->active = FALSE; + + button = float_bar_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); + float_bar_animation(floatbar, FALSE); + break; + } + case TIMER_ANIMAT_SHOW: + { + static int y = 0; + + MoveWindow(floatbar->hwnd, 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, rect.left, -y++, floatbar->width, floatbar->height, TRUE); + if (y == floatbar->height) + { + y = 0; + KillTimer(hWnd, wParam); + printf("kill timer hide\n"); + } + break; + } + default: + break; + } + break; + case WM_DESTROY: + PostQuitMessage(0); + break; + + default: + return DefWindowProc(hWnd, Msg, wParam, lParam); + } + return 0; +} + +static FloatBar* float_bar_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->background = (HBITMAP)LoadImage(wfc->hInstance, MAKEINTRESOURCE(IDB_BACKGROUND), IMAGE_BITMAP, BACKGROUND_X, BACKGROUND_Y, LR_DEFAULTCOLOR); + floatbar->buttons[0] = float_bar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT, MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + floatbar->buttons[1] = float_bar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT, RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + floatbar->buttons[2] = float_bar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT, CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + floatbar->buttons[3] = float_bar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT, LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + + return floatbar; +} + +void float_bar_window_create(wfContext *wfc) +{ + WNDCLASSEX wnd_cls; + HWND barWnd; + int x = (GetSystemMetrics(SM_CXSCREEN) - BACKGROUND_X) / 2; + + wnd_cls.cbSize = sizeof(WNDCLASSEX); + wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wnd_cls.lpfnWndProc = float_bar_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"float_bar"; + wnd_cls.hInstance = wfc->hInstance; + wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + + RegisterClassEx(&wnd_cls); + + wfc->floatbar = float_bar_create(wfc); + + barWnd = CreateWindowEx(WS_EX_TOPMOST, L"float_bar", L"float_bar", WS_CHILD, x, 0, BACKGROUND_X, BACKGROUND_Y, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar); + if (barWnd == NULL) + return; + ShowWindow(barWnd, SW_SHOWNORMAL); +} diff --git a/client/Windows/wf_floatbar.h b/client/Windows/wf_floatbar.h new file mode 100644 index 000000000..de043b434 --- /dev/null +++ b/client/Windows/wf_floatbar.h @@ -0,0 +1,30 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Windows Float Bar + * + * Copyright 2013 Zhang Zhaolong + * + * 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 float_bar_window_create(wfContext* wfc); +int floatbar_show(FloatBar* floatbar); +int floatbar_hide(FloatBar* floatbar); + +#endif From 96562e533fb99d088299f423ce68d196ef05b565 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 11:43:52 +0800 Subject: [PATCH 23/28] wfreerdp: floatbar: enabled. --- client/Windows/wf_gdi.c | 5 +++++ client/Windows/wf_interface.c | 1 + client/Windows/wf_interface.h | 2 ++ 3 files changed, 8 insertions(+) diff --git a/client/Windows/wf_gdi.c b/client/Windows/wf_gdi.c index b9cba56d5..5a26cd7e6 100644 --- a/client/Windows/wf_gdi.c +++ b/client/Windows/wf_gdi.c @@ -328,6 +328,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); diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 6e1b341bd..7efe0f27f 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -448,6 +448,7 @@ BOOL wf_post_connect(freerdp* instance) freerdp_channels_post_connect(instance->context->channels, instance); wf_cliprdr_init(wfc, instance->context->channels); + float_bar_window_create(wfc); return TRUE; } diff --git a/client/Windows/wf_interface.h b/client/Windows/wf_interface.h index f5e95cfb3..5eac88dc1 100644 --- a/client/Windows/wf_interface.h +++ b/client/Windows/wf_interface.h @@ -37,6 +37,7 @@ #include #include +#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; From 169a0cd6713e5b53c2807f6682fd68d0ff4cc556 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 11:45:11 +0800 Subject: [PATCH 24/28] wfreerdp: floatbar: add files to CMakeLists. --- client/Windows/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/Windows/CMakeLists.txt b/client/Windows/CMakeLists.txt index d01b6b07f..1e5cab1d8 100644 --- a/client/Windows/CMakeLists.txt +++ b/client/Windows/CMakeLists.txt @@ -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) From 53ed501d1416cd702f77304e6ebd1fada1c560a9 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 12:17:41 +0800 Subject: [PATCH 25/28] wfreerdp: floatbar: rename functions. --- client/Windows/wf_floatbar.c | 91 ++++++++++++++++++----------------- client/Windows/wf_floatbar.h | 2 +- client/Windows/wf_interface.c | 2 +- 3 files changed, 48 insertions(+), 47 deletions(-) diff --git a/client/Windows/wf_floatbar.c b/client/Windows/wf_floatbar.c index 0f0512c48..721357484 100644 --- a/client/Windows/wf_floatbar.c +++ b/client/Windows/wf_floatbar.c @@ -28,6 +28,11 @@ typedef struct _Button Button; +/* TIMERs */ +#define TIMER_HIDE 1 +#define TIMER_ANIMAT_SHOW 2 +#define TIMER_ANIMAT_HIDE 3 + /* Button Type */ #define BUTTON_MINIMIZE 1 #define BUTTON_RESTORE 2 @@ -48,7 +53,7 @@ typedef struct _Button Button; #define BUTTON_HEIGHT 24 struct _Button { - FloatBar* float_bar; + FloatBar* floatbar; int type; int x, y, h, w; int active; @@ -75,21 +80,9 @@ struct _FloatBar { HBITMAP background; }; -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; -} - static int button_hit(Button* button) { - FloatBar* floatbar = button->float_bar; + FloatBar* floatbar = button->floatbar; switch (button->type) { @@ -106,8 +99,8 @@ static int button_hit(Button* button) } floatbar->locked = ~floatbar->locked; - InvalidateRect(button->float_bar->hwnd, NULL, FALSE); - UpdateWindow(button->float_bar->hwnd); + InvalidateRect(button->floatbar->hwnd, NULL, FALSE); + UpdateWindow(button->floatbar->hwnd); break; case BUTTON_MINIMIZE: @@ -131,7 +124,7 @@ static int button_hit(Button* button) static int button_paint(Button* button) { - FloatBar* floatbar = button->float_bar; + FloatBar* floatbar = button->floatbar; HDC hDC = GetDC(floatbar->hwnd); HDC hMemDC = CreateCompatibleDC(hDC); HBITMAP hOldBitmap; @@ -149,7 +142,7 @@ static int button_paint(Button* button) return 0; } -static Button* float_bar_create_button(FloatBar* floatbar, int type, int resid, int resid_act, int x, int y, int h, int w) +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; @@ -163,7 +156,7 @@ static Button* float_bar_create_button(FloatBar* floatbar, int type, int resid, if (!button) return NULL; - button->float_bar = floatbar; + button->floatbar = floatbar; button->type = type; button->x = x; button->y = y; @@ -177,14 +170,14 @@ static Button* float_bar_create_button(FloatBar* floatbar, int type, int resid, return button; } -static Button* float_bar_create_lock_button(FloatBar* floatbar, +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 = float_bar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid, unlock_resid_act, x, y, h, w); + button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid, unlock_resid_act, x, y, h, w); if (!button) return NULL; @@ -197,7 +190,7 @@ static Button* float_bar_create_lock_button(FloatBar* floatbar, return button; } -static Button* float_bar_get_button(FloatBar* floatbar, int x, int y) +static Button* floatbar_get_button(FloatBar* floatbar, int x, int y) { int i; @@ -209,7 +202,7 @@ static Button* float_bar_get_button(FloatBar* floatbar, int x, int y) return NULL; } -static int float_bar_paint(FloatBar* floatbar) +static int floatbar_paint(FloatBar* floatbar) { int i; HDC hDC; @@ -239,11 +232,7 @@ static int float_bar_paint(FloatBar* floatbar) return 0; } -#define TIMER_HIDE 1 -#define TIMER_ANIMAT_SHOW 2 -#define TIMER_ANIMAT_HIDE 3 - -static int float_bar_animation(FloatBar* floatbar, BOOL show) +static int floatbar_animation(FloatBar* floatbar, BOOL show) { LONG width, height, y; @@ -254,7 +243,7 @@ static int float_bar_animation(FloatBar* floatbar, BOOL show) return 0; } -LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) +LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; RECT rect; @@ -297,7 +286,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara case WM_PAINT: BeginPaint(hWnd, &ps); - float_bar_paint(floatbar); + floatbar_paint(floatbar); EndPaint(hWnd, &ps); break; @@ -305,7 +294,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara pos_x = lParam & 0xffff; pos_y = (lParam >> 16) & 0xffff; - button = float_bar_get_button(floatbar, pos_x, pos_y); + button = floatbar_get_button(floatbar, pos_x, pos_y); if (!button) { SetCapture(hWnd); @@ -326,7 +315,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara if (lbtn_dwn) { - button = float_bar_get_button(floatbar, pos_x, pos_y); + button = floatbar_get_button(floatbar, pos_x, pos_y); if (button) button_hit(button); lbtn_dwn = FALSE; @@ -339,7 +328,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara pos_y = (lParam >> 16) & 0xffff; if (!floatbar->shown) - float_bar_animation(floatbar, TRUE); + floatbar_animation(floatbar, TRUE); if (dragging) { @@ -359,7 +348,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara for (i = 0; i < BTN_MAX; i++) floatbar->buttons[i]->active = FALSE; - button = float_bar_get_button(floatbar, pos_x, pos_y); + button = floatbar_get_button(floatbar, pos_x, pos_y); if (button) button->active = TRUE; @@ -393,7 +382,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara case TIMER_HIDE: { KillTimer(hWnd, TIMER_HIDE); - float_bar_animation(floatbar, FALSE); + floatbar_animation(floatbar, FALSE); break; } case TIMER_ANIMAT_SHOW: @@ -435,7 +424,7 @@ LRESULT CALLBACK float_bar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lPara return 0; } -static FloatBar* float_bar_create(wfContext* wfc) +static FloatBar* floatbar_create(wfContext* wfc) { FloatBar* floatbar; @@ -452,15 +441,27 @@ static FloatBar* float_bar_create(wfContext* wfc) floatbar->wfc = wfc; floatbar->background = (HBITMAP)LoadImage(wfc->hInstance, MAKEINTRESOURCE(IDB_BACKGROUND), IMAGE_BITMAP, BACKGROUND_X, BACKGROUND_Y, LR_DEFAULTCOLOR); - floatbar->buttons[0] = float_bar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT, MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); - floatbar->buttons[1] = float_bar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT, RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); - floatbar->buttons[2] = float_bar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT, CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); - floatbar->buttons[3] = float_bar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT, LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH); + 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; } -void float_bar_window_create(wfContext *wfc) +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; @@ -468,22 +469,22 @@ void float_bar_window_create(wfContext *wfc) wnd_cls.cbSize = sizeof(WNDCLASSEX); wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; - wnd_cls.lpfnWndProc = float_bar_proc; + 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"float_bar"; + wnd_cls.lpszClassName = L"floatbar"; wnd_cls.hInstance = wfc->hInstance; wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wnd_cls); - wfc->floatbar = float_bar_create(wfc); + wfc->floatbar = floatbar_create(wfc); - barWnd = CreateWindowEx(WS_EX_TOPMOST, L"float_bar", L"float_bar", WS_CHILD, x, 0, BACKGROUND_X, BACKGROUND_Y, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar); + barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_X, BACKGROUND_Y, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar); if (barWnd == NULL) return; ShowWindow(barWnd, SW_SHOWNORMAL); diff --git a/client/Windows/wf_floatbar.h b/client/Windows/wf_floatbar.h index de043b434..7b6f67dd0 100644 --- a/client/Windows/wf_floatbar.h +++ b/client/Windows/wf_floatbar.h @@ -23,7 +23,7 @@ typedef struct _FloatBar FloatBar; typedef struct wf_context wfContext; -void float_bar_window_create(wfContext* wfc); +void floatbar_window_create(wfContext* wfc); int floatbar_show(FloatBar* floatbar); int floatbar_hide(FloatBar* floatbar); diff --git a/client/Windows/wf_interface.c b/client/Windows/wf_interface.c index 7efe0f27f..a797da7a7 100644 --- a/client/Windows/wf_interface.c +++ b/client/Windows/wf_interface.c @@ -448,7 +448,7 @@ BOOL wf_post_connect(freerdp* instance) freerdp_channels_post_connect(instance->context->channels, instance); wf_cliprdr_init(wfc, instance->context->channels); - float_bar_window_create(wfc); + floatbar_window_create(wfc); return TRUE; } From 491490f505558522bd6704d469ed3e576a56a528 Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 12:21:59 +0800 Subject: [PATCH 26/28] wfreerdp: floatbar: fix lock behavior. --- client/Windows/wf_floatbar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/Windows/wf_floatbar.c b/client/Windows/wf_floatbar.c index 721357484..3f12a99c0 100644 --- a/client/Windows/wf_floatbar.c +++ b/client/Windows/wf_floatbar.c @@ -382,7 +382,8 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam case TIMER_HIDE: { KillTimer(hWnd, TIMER_HIDE); - floatbar_animation(floatbar, FALSE); + if (!floatbar->locked) + floatbar_animation(floatbar, FALSE); break; } case TIMER_ANIMAT_SHOW: From c0ac3ee9270eea7ab4340370db0ac59a87ff2e1f Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 13:44:49 +0800 Subject: [PATCH 27/28] wfreerdp: floatbar: fix lose position after fullscreen toggling. minor code cleanup. --- client/Windows/wf_floatbar.c | 83 +++++++++++++++--------------------- 1 file changed, 35 insertions(+), 48 deletions(-) diff --git a/client/Windows/wf_floatbar.c b/client/Windows/wf_floatbar.c index 3f12a99c0..715133309 100644 --- a/client/Windows/wf_floatbar.c +++ b/client/Windows/wf_floatbar.c @@ -29,28 +29,28 @@ typedef struct _Button Button; /* TIMERs */ -#define TIMER_HIDE 1 -#define TIMER_ANIMAT_SHOW 2 -#define TIMER_ANIMAT_HIDE 3 +#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 BUTTON_LOCKPIN 4 -#define BTN_MAX 4 +#define BTN_MAX 4 /* bmp size */ -#define BACKGROUND_X 581 -#define BACKGROUND_Y 29 -#define LOCK_X 13 -#define MINIMIZE_X (BACKGROUND_X - 91) -#define CLOSE_X (BACKGROUND_X - 37) -#define RESTORE_X (BACKGROUND_X - 64) +#define BACKGROUND_X 581 +#define BACKGROUND_Y 29 +#define LOCK_X 13 +#define MINIMIZE_X (BACKGROUND_X - 91) +#define CLOSE_X (BACKGROUND_X - 37) +#define RESTORE_X (BACKGROUND_X - 64) -#define BUTTON_Y 2 -#define BUTTON_WIDTH 24 -#define BUTTON_HEIGHT 24 +#define BUTTON_Y 2 +#define BUTTON_WIDTH 24 +#define BUTTON_HEIGHT 24 struct _Button { FloatBar* floatbar; @@ -234,53 +234,42 @@ static int floatbar_paint(FloatBar* floatbar) static int floatbar_animation(FloatBar* floatbar, BOOL show) { - LONG width, height, y; - 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) { - PAINTSTRUCT ps; - RECT rect; static int dragging = FALSE; static int lbtn_dwn = FALSE; static int btn_dwn_x = 0; - - int nWidth, nHeight; - int drag_left = 0; - int xScreen = GetSystemMetrics(SM_CXSCREEN); - HWND hParentWnd = GetParent(hWnd); - static FloatBar* floatbar; + static TRACKMOUSEEVENT tme; + + PAINTSTRUCT ps; Button* button; int pos_x; int pos_y; - TRACKMOUSEEVENT tme; - - tme.cbSize = sizeof(TRACKMOUSEEVENT); - tme.dwFlags = TME_LEAVE; - tme.hwndTrack = hWnd; - tme.dwHoverTime = HOVER_DEFAULT; - - GetWindowRect(hWnd, &rect); - nWidth = rect.right - rect.left; - nHeight = rect.bottom - rect.top; + int xScreen = GetSystemMetrics(SM_CXSCREEN); switch(Msg) { case WM_CREATE: floatbar = (FloatBar *)((CREATESTRUCT *)lParam)->lpCreateParams; floatbar->hwnd = hWnd; - floatbar->parent = hParentWnd; + 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; + + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + tme.hwndTrack = hWnd; + tme.dwHoverTime = HOVER_DEFAULT; + SetTimer(hWnd, TIMER_HIDE, 3000, NULL); break; @@ -328,18 +317,18 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam pos_y = (lParam >> 16) & 0xffff; if (!floatbar->shown) - floatbar_animation(floatbar, TRUE); + floatbar_animation(floatbar, TRUE); if (dragging) { - drag_left = rect.left + (lParam & 0xffff) - btn_dwn_x; + floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x; - if (drag_left < 0) - drag_left = 0; - else if (drag_left > xScreen - floatbar->width) - drag_left = xScreen - floatbar->width; + 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, drag_left, rect.top, floatbar->width, floatbar->height, TRUE); + MoveWindow(hWnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE); } else { @@ -390,7 +379,7 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam { static int y = 0; - MoveWindow(floatbar->hwnd, rect.left, (y++ - floatbar->height), floatbar->width, floatbar->height, TRUE); + MoveWindow(floatbar->hwnd, floatbar->rect.left, (y++ - floatbar->height), floatbar->width, floatbar->height, TRUE); if (y == floatbar->height) { y = 0; @@ -402,12 +391,11 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam { static int y = 0; - MoveWindow(floatbar->hwnd, rect.left, -y++, floatbar->width, floatbar->height, TRUE); + MoveWindow(floatbar->hwnd, floatbar->rect.left, -y++, floatbar->width, floatbar->height, TRUE); if (y == floatbar->height) { y = 0; KillTimer(hWnd, wParam); - printf("kill timer hide\n"); } break; } @@ -434,7 +422,6 @@ static FloatBar* floatbar_create(wfContext* wfc) if (!floatbar) return NULL; - floatbar->locked = FALSE; floatbar->shown = TRUE; floatbar->hwnd = NULL; From 4254100a101bdfd07ddb53fcf68712292f2ffa4d Mon Sep 17 00:00:00 2001 From: Zhang Zhaolong Date: Thu, 27 Feb 2014 14:30:58 +0800 Subject: [PATCH 28/28] wfreerdp: floatbar: code reduce. --- client/Windows/wf_floatbar.c | 65 +++++++++++++++--------------------- 1 file changed, 26 insertions(+), 39 deletions(-) diff --git a/client/Windows/wf_floatbar.c b/client/Windows/wf_floatbar.c index 715133309..b331dc5c0 100644 --- a/client/Windows/wf_floatbar.c +++ b/client/Windows/wf_floatbar.c @@ -41,12 +41,12 @@ typedef struct _Button Button; #define BTN_MAX 4 /* bmp size */ -#define BACKGROUND_X 581 -#define BACKGROUND_Y 29 +#define BACKGROUND_W 581 +#define BACKGROUND_H 29 #define LOCK_X 13 -#define MINIMIZE_X (BACKGROUND_X - 91) -#define CLOSE_X (BACKGROUND_X - 37) -#define RESTORE_X (BACKGROUND_X - 64) +#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 @@ -77,6 +77,7 @@ struct _FloatBar { Button* buttons[BTN_MAX]; BOOL shown; BOOL locked; + HDC hdcmem; HBITMAP background; }; @@ -122,22 +123,12 @@ static int button_hit(Button* button) return 0; } -static int button_paint(Button* button) +static int button_paint(Button* button, HDC hdc) { FloatBar* floatbar = button->floatbar; - HDC hDC = GetDC(floatbar->hwnd); - HDC hMemDC = CreateCompatibleDC(hDC); - HBITMAP hOldBitmap; - BITMAP bm; - hOldBitmap = (HBITMAP)SelectObject(hMemDC, button->active ? button->bmp_act : button->bmp); - - StretchBlt(hDC, button->x, button->y, button->w, button->h, hMemDC, 0, 0, button->w, button->h, SRCCOPY); - - SelectObject(hMemDC, hOldBitmap); - - DeleteDC(hMemDC); - ReleaseDC(floatbar->hwnd, hDC); + 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; } @@ -202,32 +193,20 @@ static Button* floatbar_get_button(FloatBar* floatbar, int x, int y) return NULL; } -static int floatbar_paint(FloatBar* floatbar) +static int floatbar_paint(FloatBar* floatbar, HDC hdc) { int i; - HDC hDC; - HDC hMemDC; - HBITMAP hOldBitmap; - BITMAP bm; if (!floatbar->wfc->fullscreen) return -1; /* paint background */ - hDC = GetDC(floatbar->hwnd); - hMemDC = CreateCompatibleDC(hDC); - GetObject(floatbar->background, sizeof(bm), &bm); - - hOldBitmap = (HBITMAP)SelectObject(hMemDC, floatbar->background); - StretchBlt(hDC, 0, 0, BACKGROUND_X, BACKGROUND_Y, hMemDC, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); - (HBITMAP)SelectObject(hMemDC, hOldBitmap); - - DeleteDC(hMemDC); - ReleaseDC(floatbar->hwnd, hDC); + 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]); + button_paint(floatbar->buttons[i], hdc); return 0; } @@ -249,6 +228,7 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam PAINTSTRUCT ps; Button* button; + HDC hdc; int pos_x; int pos_y; @@ -265,6 +245,10 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam 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; @@ -274,8 +258,8 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam break; case WM_PAINT: - BeginPaint(hWnd, &ps); - floatbar_paint(floatbar); + hdc = BeginPaint(hWnd, &ps); + floatbar_paint(floatbar, hdc); EndPaint(hWnd, &ps); break; @@ -403,7 +387,9 @@ LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam break; } break; + case WM_DESTROY: + DeleteDC(floatbar->hdcmem); PostQuitMessage(0); break; @@ -427,8 +413,9 @@ static FloatBar* floatbar_create(wfContext* wfc) 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_X, BACKGROUND_Y, LR_DEFAULTCOLOR); + 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); @@ -453,7 +440,7 @@ void floatbar_window_create(wfContext *wfc) { WNDCLASSEX wnd_cls; HWND barWnd; - int x = (GetSystemMetrics(SM_CXSCREEN) - BACKGROUND_X) / 2; + int x = (GetSystemMetrics(SM_CXSCREEN) - BACKGROUND_W) / 2; wnd_cls.cbSize = sizeof(WNDCLASSEX); wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; @@ -472,7 +459,7 @@ void floatbar_window_create(wfContext *wfc) wfc->floatbar = floatbar_create(wfc); - barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_X, BACKGROUND_Y, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar); + 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);