Merge branch 'master' of github.com:awakecoding/FreeRDP into channels
|
@ -49,3 +49,7 @@ endif()
|
||||||
if(WITH_OPENSLES)
|
if(WITH_OPENSLES)
|
||||||
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "opensles" "")
|
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "opensles" "")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_WINMM)
|
||||||
|
add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "winmm" "")
|
||||||
|
endif()
|
||||||
|
|
|
@ -607,6 +607,15 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
|
||||||
}
|
}
|
||||||
#endif
|
#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)
|
if (audin->device == NULL)
|
||||||
{
|
{
|
||||||
DEBUG_WARN("no sound device.");
|
DEBUG_WARN("no sound device.");
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
# FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
# FreeRDP cmake build script
|
||||||
|
#
|
||||||
|
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
|
||||||
|
define_channel_client_subsystem("audin" "winmm" "")
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_SRCS
|
||||||
|
audin_winmm.c)
|
||||||
|
|
||||||
|
include_directories(..)
|
||||||
|
|
||||||
|
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||||
|
|
||||||
|
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
|
||||||
|
|
||||||
|
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||||
|
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||||
|
MODULE freerdp
|
||||||
|
MODULES freerdp-utils)
|
||||||
|
|
||||||
|
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winmm.lib)
|
||||||
|
|
||||||
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
|
||||||
|
|
||||||
|
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
|
||||||
|
|
||||||
|
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client/winmm")
|
|
@ -0,0 +1,309 @@
|
||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Audio Input Redirection Virtual Channel - WinMM implementation
|
||||||
|
*
|
||||||
|
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <MMSystem.h>
|
||||||
|
|
||||||
|
#include <winpr/crt.h>
|
||||||
|
#include <winpr/cmdline.h>
|
||||||
|
#include <freerdp/addin.h>
|
||||||
|
|
||||||
|
#include "audin_main.h"
|
||||||
|
|
||||||
|
typedef struct _AudinWinmmDevice
|
||||||
|
{
|
||||||
|
IAudinDevice iface;
|
||||||
|
|
||||||
|
char* device_name;
|
||||||
|
AudinReceive receive;
|
||||||
|
void* user_data;
|
||||||
|
HANDLE thread;
|
||||||
|
HANDLE stopEvent;
|
||||||
|
HWAVEIN hWaveIn;
|
||||||
|
PWAVEFORMATEX *ppwfx;
|
||||||
|
PWAVEFORMATEX pwfx_cur;
|
||||||
|
UINT32 ppwfx_size;
|
||||||
|
UINT32 cFormats;
|
||||||
|
UINT32 frames_per_packet;
|
||||||
|
} AudinWinmmDevice;
|
||||||
|
|
||||||
|
static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance,
|
||||||
|
DWORD_PTR dwParam1, DWORD_PTR dwParam2)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) dwInstance;
|
||||||
|
PWAVEHDR pWaveHdr;
|
||||||
|
|
||||||
|
switch(uMsg)
|
||||||
|
{
|
||||||
|
case WIM_CLOSE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIM_DATA:
|
||||||
|
pWaveHdr = (WAVEHDR *)dwParam1;
|
||||||
|
if (WHDR_DONE == (WHDR_DONE & pWaveHdr->dwFlags))
|
||||||
|
{
|
||||||
|
if (pWaveHdr->dwBytesRecorded
|
||||||
|
&& !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0))
|
||||||
|
{
|
||||||
|
winmm->receive(pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, winmm->user_data);
|
||||||
|
waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WIM_OPEN:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DWORD audin_winmm_thread_func(void* arg)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) arg;
|
||||||
|
char *buffer;
|
||||||
|
int size, i;
|
||||||
|
WAVEHDR waveHdr[4];
|
||||||
|
|
||||||
|
if (!winmm->hWaveIn)
|
||||||
|
{
|
||||||
|
if (MMSYSERR_NOERROR != waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur,
|
||||||
|
(DWORD_PTR)waveInProc, (DWORD_PTR)winmm, CALLBACK_FUNCTION))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size = (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet + 7) / 8;
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
buffer = (char *) malloc(size);
|
||||||
|
waveHdr[i].dwBufferLength = size;
|
||||||
|
waveHdr[i].dwFlags = 0;
|
||||||
|
waveHdr[i].lpData = buffer;
|
||||||
|
if (MMSYSERR_NOERROR != waveInPrepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
|
||||||
|
{
|
||||||
|
DEBUG_DVC("waveInPrepareHeader failed.");
|
||||||
|
}
|
||||||
|
if (MMSYSERR_NOERROR != waveInAddBuffer(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
|
||||||
|
{
|
||||||
|
DEBUG_DVC("waveInAddBuffer failed.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
waveInStart(winmm->hWaveIn);
|
||||||
|
|
||||||
|
WaitForSingleObject(winmm->stopEvent, INFINITE);
|
||||||
|
|
||||||
|
waveInStop(winmm->hWaveIn);
|
||||||
|
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
if (MMSYSERR_NOERROR != waveInUnprepareHeader(winmm->hWaveIn, &waveHdr[i], sizeof(waveHdr[i])))
|
||||||
|
{
|
||||||
|
DEBUG_DVC("waveInUnprepareHeader failed.");
|
||||||
|
}
|
||||||
|
free(waveHdr[i].lpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
waveInClose(winmm->hWaveIn);
|
||||||
|
winmm->hWaveIn = NULL;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void audin_winmm_free(IAudinDevice* device)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < winmm->cFormats; i++)
|
||||||
|
{
|
||||||
|
free(winmm->ppwfx[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(winmm->ppwfx);
|
||||||
|
free(winmm->device_name);
|
||||||
|
free(winmm);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void audin_winmm_close(IAudinDevice* device)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
|
||||||
|
|
||||||
|
DEBUG_DVC("");
|
||||||
|
|
||||||
|
SetEvent(winmm->stopEvent);
|
||||||
|
|
||||||
|
WaitForSingleObject(winmm->thread, INFINITE);
|
||||||
|
|
||||||
|
CloseHandle(winmm->thread);
|
||||||
|
CloseHandle(winmm->stopEvent);
|
||||||
|
|
||||||
|
winmm->thread = NULL;
|
||||||
|
winmm->stopEvent = NULL;
|
||||||
|
winmm->receive = NULL;
|
||||||
|
winmm->user_data = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void audin_winmm_set_format(IAudinDevice* device, audinFormat* format, UINT32 FramesPerPacket)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
winmm->frames_per_packet = FramesPerPacket;
|
||||||
|
|
||||||
|
for (i = 0; i < winmm->cFormats; i++)
|
||||||
|
{
|
||||||
|
if (winmm->ppwfx[i]->wFormatTag == format->wFormatTag
|
||||||
|
&& winmm->ppwfx[i]->nChannels == format->nChannels
|
||||||
|
&& winmm->ppwfx[i]->wBitsPerSample == format->wBitsPerSample)
|
||||||
|
{
|
||||||
|
winmm->pwfx_cur = winmm->ppwfx[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static BOOL audin_winmm_format_supported(IAudinDevice* device, audinFormat* format)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
|
||||||
|
PWAVEFORMATEX pwfx;
|
||||||
|
BYTE *data;
|
||||||
|
|
||||||
|
pwfx = (PWAVEFORMATEX)malloc(sizeof(WAVEFORMATEX) + format->cbSize);
|
||||||
|
pwfx->cbSize = format->cbSize;
|
||||||
|
pwfx->wFormatTag = format->wFormatTag;
|
||||||
|
pwfx->nChannels = format->nChannels;
|
||||||
|
pwfx->nSamplesPerSec = format->nSamplesPerSec;
|
||||||
|
pwfx->nBlockAlign = format->nBlockAlign;
|
||||||
|
pwfx->wBitsPerSample = format->wBitsPerSample;
|
||||||
|
data = (BYTE *)pwfx + sizeof(WAVEFORMATEX);
|
||||||
|
|
||||||
|
memcpy(data, format->data, format->cbSize);
|
||||||
|
|
||||||
|
if (pwfx->wFormatTag == WAVE_FORMAT_PCM)
|
||||||
|
{
|
||||||
|
pwfx->nAvgBytesPerSec = pwfx->nSamplesPerSec * pwfx->nBlockAlign;
|
||||||
|
if (MMSYSERR_NOERROR == waveInOpen(NULL, WAVE_MAPPER, pwfx, 0, 0, WAVE_FORMAT_QUERY))
|
||||||
|
{
|
||||||
|
if (winmm->cFormats >= winmm->ppwfx_size)
|
||||||
|
{
|
||||||
|
winmm->ppwfx_size *= 2;
|
||||||
|
winmm->ppwfx = realloc(winmm->ppwfx, sizeof(PWAVEFORMATEX) * winmm->ppwfx_size);
|
||||||
|
}
|
||||||
|
winmm->ppwfx[winmm->cFormats++] = pwfx;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(pwfx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data)
|
||||||
|
{
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
|
||||||
|
|
||||||
|
DEBUG_DVC("");
|
||||||
|
|
||||||
|
winmm->receive = receive;
|
||||||
|
winmm->user_data = user_data;
|
||||||
|
|
||||||
|
winmm->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
winmm->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_winmm_thread_func, winmm, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] =
|
||||||
|
{
|
||||||
|
{ "audio-dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "audio device name" },
|
||||||
|
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static void audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* args)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
DWORD flags;
|
||||||
|
COMMAND_LINE_ARGUMENT_A* arg;
|
||||||
|
AudinWinmmDevice* winmm = (AudinWinmmDevice*) device;
|
||||||
|
|
||||||
|
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
|
||||||
|
|
||||||
|
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_winmm_args, flags, winmm, NULL, NULL);
|
||||||
|
|
||||||
|
arg = audin_winmm_args;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
CommandLineSwitchStart(arg)
|
||||||
|
|
||||||
|
CommandLineSwitchCase(arg, "audio-dev")
|
||||||
|
{
|
||||||
|
winmm->device_name = _strdup(arg->Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
CommandLineSwitchEnd(arg)
|
||||||
|
}
|
||||||
|
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef STATIC_CHANNELS
|
||||||
|
#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)
|
||||||
|
{
|
||||||
|
ADDIN_ARGV* args;
|
||||||
|
AudinWinmmDevice* winmm;
|
||||||
|
|
||||||
|
winmm = (AudinWinmmDevice*) malloc(sizeof(AudinWinmmDevice));
|
||||||
|
ZeroMemory(winmm, sizeof(AudinWinmmDevice));
|
||||||
|
|
||||||
|
winmm->iface.Open = audin_winmm_open;
|
||||||
|
winmm->iface.FormatSupported = audin_winmm_format_supported;
|
||||||
|
winmm->iface.SetFormat = audin_winmm_set_format;
|
||||||
|
winmm->iface.Close = audin_winmm_close;
|
||||||
|
winmm->iface.Free = audin_winmm_free;
|
||||||
|
|
||||||
|
args = pEntryPoints->args;
|
||||||
|
|
||||||
|
audin_winmm_parse_addin_args(winmm, args);
|
||||||
|
|
||||||
|
if (!winmm->device_name)
|
||||||
|
winmm->device_name = _strdup("default");
|
||||||
|
|
||||||
|
winmm->ppwfx_size = 10;
|
||||||
|
winmm->ppwfx = malloc(sizeof(PWAVEFORMATEX) * winmm->ppwfx_size);
|
||||||
|
|
||||||
|
pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -413,13 +413,13 @@ int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelI
|
||||||
|
|
||||||
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
|
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
|
||||||
|
|
||||||
|
free(channel->channel_name);
|
||||||
|
|
||||||
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
|
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
|
||||||
ichannel = (IWTSVirtualChannel*) channel;
|
ichannel = (IWTSVirtualChannel*) channel;
|
||||||
ichannel->Close(ichannel);
|
ichannel->Close(ichannel);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(channel->channel_name);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -177,9 +177,9 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat
|
||||||
struct STAT st;
|
struct STAT st;
|
||||||
BOOL exists;
|
BOOL exists;
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
const static int mode = _S_IREAD | _S_IWRITE ;
|
const static int mode = _S_IREAD | _S_IWRITE ;
|
||||||
#else
|
#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;
|
BOOL largeFile = FALSE;
|
||||||
#endif
|
#endif
|
||||||
int oflag = 0;
|
int oflag = 0;
|
||||||
|
@ -265,8 +265,10 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (largeFile)
|
if (largeFile)
|
||||||
{
|
{
|
||||||
oflag |= O_LARGEFILE;
|
oflag |= O_LARGEFILE;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
oflag |= O_BINARY;
|
||||||
#endif
|
#endif
|
||||||
file->fd = OPEN(file->fullpath, oflag, mode);
|
file->fd = OPEN(file->fullpath, oflag, mode);
|
||||||
|
|
||||||
|
@ -426,7 +428,7 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
|
||||||
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input)
|
BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UINT32 Length, wStream* input)
|
||||||
{
|
{
|
||||||
char* s = NULL;
|
char* s = NULL;
|
||||||
mode_t m;
|
mode_t m;
|
||||||
UINT64 size;
|
UINT64 size;
|
||||||
int status;
|
int status;
|
||||||
char* fullpath;
|
char* fullpath;
|
||||||
|
@ -456,7 +458,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||||
tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
|
tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
|
||||||
tv[1].tv_usec = 0;
|
tv[1].tv_usec = 0;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
/* TODO on win32 */
|
/* TODO on win32 */
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
utimes(file->fullpath, tv);
|
utimes(file->fullpath, tv);
|
||||||
#else
|
#else
|
||||||
|
@ -474,15 +476,17 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||||
fchmod(file->fd, st.st_mode);
|
fchmod(file->fd, st.st_mode);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileEndOfFileInformation:
|
case FileEndOfFileInformation:
|
||||||
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
|
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
|
||||||
case FileAllocationInformation:
|
case FileAllocationInformation:
|
||||||
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
|
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
|
||||||
|
#ifndef _WIN32
|
||||||
Stream_Read_UINT64(input, size);
|
Stream_Read_UINT64(input, size);
|
||||||
if (ftruncate(file->fd, size) != 0)
|
if (ftruncate(file->fd, size) != 0)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FileDispositionInformation:
|
case FileDispositionInformation:
|
||||||
|
@ -509,10 +513,16 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
|
||||||
fullpath = drive_file_combine_fullpath(file->basepath, s);
|
fullpath = drive_file_combine_fullpath(file->basepath, s);
|
||||||
free(s);
|
free(s);
|
||||||
|
|
||||||
/* TODO rename does not work on win32 */
|
#ifdef _WIN32
|
||||||
if (rename(file->fullpath, fullpath) == 0)
|
if (file->fd)
|
||||||
|
close(file->fd);
|
||||||
|
#endif
|
||||||
|
if (rename(file->fullpath, fullpath) == 0)
|
||||||
{
|
{
|
||||||
drive_file_set_fullpath(file, fullpath);
|
drive_file_set_fullpath(file, fullpath);
|
||||||
|
#ifdef _WIN32
|
||||||
|
file->fd = OPEN(fullpath, O_RDWR | O_BINARY);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -40,13 +40,13 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define STAT stat
|
#define STAT __stat64
|
||||||
#define OPEN _open
|
#define OPEN _open
|
||||||
#define close _close
|
#define close _close
|
||||||
#define read _read
|
#define read _read
|
||||||
#define write _write
|
#define write _write
|
||||||
#define LSEEK _lseek
|
#define LSEEK _lseeki64
|
||||||
#define FSTAT fstat
|
#define FSTAT _fstat64
|
||||||
#define STATVFS statvfs
|
#define STATVFS statvfs
|
||||||
#define mkdir(a,b) _mkdir(a)
|
#define mkdir(a,b) _mkdir(a)
|
||||||
#define rmdir _rmdir
|
#define rmdir _rmdir
|
||||||
|
|
|
@ -576,29 +576,29 @@ static void drive_process_irp(DRIVE_DEVICE* drive, IRP* irp)
|
||||||
|
|
||||||
static void* drive_thread_func(void* arg)
|
static void* drive_thread_func(void* arg)
|
||||||
{
|
{
|
||||||
IRP* irp;
|
IRP* irp;
|
||||||
wMessage message;
|
wMessage message;
|
||||||
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
|
DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg;
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
if (!MessageQueue_Wait(drive->IrpQueue))
|
if (!MessageQueue_Wait(drive->IrpQueue))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
|
if (!MessageQueue_Peek(drive->IrpQueue, &message, TRUE))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (message.id == WMQ_QUIT)
|
if (message.id == WMQ_QUIT)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
irp = (IRP*) message.wParam;
|
irp = (IRP*) message.wParam;
|
||||||
|
|
||||||
if (irp)
|
if (irp)
|
||||||
drive_process_irp(drive, irp);
|
drive_process_irp(drive, irp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExitThread(0);
|
ExitThread(0);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void drive_irp_request(DEVICE* device, IRP* irp)
|
static void drive_irp_request(DEVICE* device, IRP* irp)
|
||||||
|
@ -712,13 +712,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||||
drive->Path = _strdup("/");
|
drive->Path = _strdup("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
sys_code_page = GetACP();
|
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 */
|
/* Special case: path[0] == '%' -> user home dir */
|
||||||
if (strcmp(drive->Path, "%") == 0)
|
if (strcmp(drive->Path, "%") == 0)
|
||||||
{
|
{
|
||||||
_snprintf(buf, sizeof(buf), "%s\\", getenv("USERPROFILE"));
|
_snprintf(buf, sizeof(buf), "%s\\", getenv("USERPROFILE"));
|
||||||
drive_register_drive_path(pEntryPoints, drive->Name, _strdup(buf));
|
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++)
|
for (dev = devlist, i = 0; *dev; dev += 4, i++)
|
||||||
{
|
{
|
||||||
if (*dev > 'B')
|
if (*dev > 'B')
|
||||||
{
|
{
|
||||||
/* Suppress disk drives A and B to avoid pesty messages */
|
/* Suppress disk drives A and B to avoid pesty messages */
|
||||||
len = _snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
|
len = _snprintf(buf, sizeof(buf) - 4, "%s", drive->Name);
|
||||||
buf[len] = '_';
|
buf[len] = '_';
|
||||||
|
@ -744,11 +744,11 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
drive_register_drive_path(pEntryPoints, drive->Name, drive->Path);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,6 +67,15 @@ void devman_free(DEVMAN* devman)
|
||||||
free(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)
|
static void devman_register_device(DEVMAN* devman, DEVICE* device)
|
||||||
{
|
{
|
||||||
void* key = NULL;
|
void* key = NULL;
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
|
|
||||||
#include "rdpdr_main.h"
|
#include "rdpdr_main.h"
|
||||||
|
|
||||||
|
void devman_unregister_device(DEVMAN* devman, void* key);
|
||||||
BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device);
|
BOOL devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device);
|
||||||
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
|
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,15 @@
|
||||||
#include <freerdp/constants.h>
|
#include <freerdp/constants.h>
|
||||||
#include <freerdp/channels/rdpdr.h>
|
#include <freerdp/channels/rdpdr.h>
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
#include <dbt.h>
|
||||||
|
#else
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_UNISTD_H
|
#ifdef HAVE_UNISTD_H
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -44,6 +53,432 @@
|
||||||
|
|
||||||
#include "rdpdr_main.h"
|
#include "rdpdr_main.h"
|
||||||
|
|
||||||
|
typedef struct _DEVICE_DRIVE_EXT DEVICE_DRIVE_EXT;
|
||||||
|
|
||||||
|
struct _DEVICE_DRIVE_EXT
|
||||||
|
{
|
||||||
|
DEVICE device;
|
||||||
|
char* path;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn);
|
||||||
|
|
||||||
|
static void rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 count, UINT32 ids[])
|
||||||
|
{
|
||||||
|
wStream* s;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
s = Stream_New(NULL, 256);
|
||||||
|
|
||||||
|
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
|
||||||
|
Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_REMOVE);
|
||||||
|
Stream_Write_UINT32(s, count);
|
||||||
|
|
||||||
|
for (i = 0; i < count; i++)
|
||||||
|
Stream_Write_UINT32(s, ids[i]);
|
||||||
|
|
||||||
|
Stream_SealLength(s);
|
||||||
|
|
||||||
|
rdpdr_send(rdpdr, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
|
||||||
|
LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
rdpdrPlugin *rdpdr;
|
||||||
|
PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
|
||||||
|
|
||||||
|
rdpdr = (rdpdrPlugin *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
|
||||||
|
|
||||||
|
switch(Msg)
|
||||||
|
{
|
||||||
|
case WM_DEVICECHANGE:
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case DBT_DEVICEARRIVAL:
|
||||||
|
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
|
||||||
|
{
|
||||||
|
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
|
||||||
|
DWORD unitmask = lpdbv->dbcv_unitmask;
|
||||||
|
int i;
|
||||||
|
char drive_path[4] = { 'c', ':', '/', '\0'};
|
||||||
|
|
||||||
|
for (i = 0; i < 26; i++)
|
||||||
|
{
|
||||||
|
if (unitmask & 0x01)
|
||||||
|
{
|
||||||
|
RDPDR_DRIVE* drive;
|
||||||
|
|
||||||
|
drive_path[0] = 'A' + i;
|
||||||
|
|
||||||
|
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
|
||||||
|
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
|
||||||
|
|
||||||
|
drive->Type = RDPDR_DTYP_FILESYSTEM;
|
||||||
|
|
||||||
|
drive->Path = _strdup(drive_path);
|
||||||
|
drive_path[1] = '\0';
|
||||||
|
drive->Name = _strdup(drive_path);
|
||||||
|
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive);
|
||||||
|
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
|
||||||
|
}
|
||||||
|
unitmask = unitmask >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DBT_DEVICEREMOVECOMPLETE:
|
||||||
|
if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
|
||||||
|
{
|
||||||
|
PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
|
||||||
|
DWORD unitmask = lpdbv->dbcv_unitmask;
|
||||||
|
int i, j, count;
|
||||||
|
char drive_name_upper, drive_name_lower;
|
||||||
|
|
||||||
|
ULONG_PTR *keys;
|
||||||
|
DEVICE_DRIVE_EXT *device_ext;
|
||||||
|
UINT32 ids[1];
|
||||||
|
|
||||||
|
for (i = 0; i < 26; i++)
|
||||||
|
{
|
||||||
|
if (unitmask & 0x01)
|
||||||
|
{
|
||||||
|
drive_name_upper = 'A' + i;
|
||||||
|
drive_name_lower = 'a' + i;
|
||||||
|
|
||||||
|
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
|
||||||
|
|
||||||
|
for (j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]);
|
||||||
|
if (device_ext->path[0] == drive_name_upper || device_ext->path[0] == drive_name_lower)
|
||||||
|
{
|
||||||
|
devman_unregister_device(rdpdr->devman, (void *)keys[j]);
|
||||||
|
ids[0] = keys[j];
|
||||||
|
rdpdr_send_device_list_remove_request(rdpdr, 1, ids);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unitmask = unitmask >> 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* drive_hotplug_thread_func(void* arg)
|
||||||
|
{
|
||||||
|
rdpdrPlugin *rdpdr;
|
||||||
|
WNDCLASSEX wnd_cls;
|
||||||
|
HWND hwnd;
|
||||||
|
MSG msg;
|
||||||
|
BOOL bRet;
|
||||||
|
DEV_BROADCAST_HANDLE NotificationFilter;
|
||||||
|
HDEVNOTIFY hDevNotify;
|
||||||
|
|
||||||
|
rdpdr = (rdpdrPlugin *)arg;
|
||||||
|
|
||||||
|
/* init windows class */
|
||||||
|
wnd_cls.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wnd_cls.style = CS_HREDRAW | CS_VREDRAW;
|
||||||
|
wnd_cls.lpfnWndProc = hotplug_proc;
|
||||||
|
wnd_cls.cbClsExtra = 0;
|
||||||
|
wnd_cls.cbWndExtra = 0;
|
||||||
|
wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
wnd_cls.hCursor = NULL;
|
||||||
|
wnd_cls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
|
||||||
|
wnd_cls.lpszMenuName = NULL;
|
||||||
|
wnd_cls.lpszClassName = L"DRIVE_HOTPLUG";
|
||||||
|
wnd_cls.hInstance = NULL;
|
||||||
|
wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
RegisterClassEx(&wnd_cls);
|
||||||
|
|
||||||
|
/* create window */
|
||||||
|
hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL,
|
||||||
|
0, 0, 0, 0, 0,
|
||||||
|
NULL, NULL, NULL, NULL);
|
||||||
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)rdpdr);
|
||||||
|
|
||||||
|
rdpdr->hotplug_wnd = hwnd;
|
||||||
|
/* register device interface to hwnd */
|
||||||
|
NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE);
|
||||||
|
NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE;
|
||||||
|
hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||||
|
|
||||||
|
/* message loop */
|
||||||
|
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0)
|
||||||
|
{
|
||||||
|
if (bRet == -1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TranslateMessage(&msg);
|
||||||
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UnregisterDeviceNotification(hDevNotify);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
|
||||||
|
{
|
||||||
|
if (rdpdr->hotplug_wnd)
|
||||||
|
PostMessage(rdpdr->hotplug_wnd, WM_QUIT, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define MAX_USB_DEVICES 100
|
||||||
|
|
||||||
|
typedef struct _hotplug_dev {
|
||||||
|
char* path;
|
||||||
|
BOOL to_add;
|
||||||
|
} hotplug_dev;
|
||||||
|
|
||||||
|
static char* next_line(FILE* fd, size_t* len)
|
||||||
|
{
|
||||||
|
size_t newsiz;
|
||||||
|
int c;
|
||||||
|
char* newbuf;
|
||||||
|
char* lrbuf;
|
||||||
|
int lrsiz;
|
||||||
|
|
||||||
|
*len = 0;
|
||||||
|
lrsiz = 0;
|
||||||
|
lrbuf = NULL;
|
||||||
|
newbuf = NULL;
|
||||||
|
|
||||||
|
for (;;)
|
||||||
|
{
|
||||||
|
c = fgetc(fd);
|
||||||
|
if (ferror(fd))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (c == EOF)
|
||||||
|
{
|
||||||
|
if (*len == 0)
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lrbuf[(*len)] = '\0';
|
||||||
|
return lrbuf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*len == lrsiz)
|
||||||
|
{
|
||||||
|
newsiz = lrsiz + 4096;
|
||||||
|
newbuf = realloc(lrbuf, newsiz);
|
||||||
|
if (newbuf == NULL)
|
||||||
|
return NULL;
|
||||||
|
lrbuf = newbuf;
|
||||||
|
lrsiz = newsiz;
|
||||||
|
}
|
||||||
|
lrbuf[(*len)] = c;
|
||||||
|
|
||||||
|
if (c == '\n')
|
||||||
|
{
|
||||||
|
lrbuf[(*len)] = '\0';
|
||||||
|
return lrbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*len)++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char* get_word(char* str, unsigned int* offset)
|
||||||
|
{
|
||||||
|
char* p;
|
||||||
|
char* tmp;
|
||||||
|
int wlen;
|
||||||
|
|
||||||
|
if (*offset >= strlen(str))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
p = str + *offset;
|
||||||
|
tmp = p;
|
||||||
|
|
||||||
|
while (*tmp != ' ' && *tmp != '\0')
|
||||||
|
tmp++;
|
||||||
|
|
||||||
|
wlen = tmp - p;
|
||||||
|
*offset += wlen;
|
||||||
|
|
||||||
|
/* in case there are more than one space between words */
|
||||||
|
while (*(str + *offset) == ' ')
|
||||||
|
(*offset)++;
|
||||||
|
|
||||||
|
return strndup(p, wlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void handle_hotplug(rdpdrPlugin* rdpdr)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
size_t len;
|
||||||
|
char *line;
|
||||||
|
char *word;
|
||||||
|
unsigned int wlen;
|
||||||
|
|
||||||
|
hotplug_dev dev_array[MAX_USB_DEVICES];
|
||||||
|
int i, j;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
int count;
|
||||||
|
DEVICE_DRIVE_EXT *device_ext;
|
||||||
|
ULONG_PTR *keys;
|
||||||
|
UINT32 ids[1];
|
||||||
|
|
||||||
|
f = fopen("/proc/mounts", "r");
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((line = next_line(f, &len)))
|
||||||
|
{
|
||||||
|
wlen = 0;
|
||||||
|
while ((word = get_word(line, &wlen)))
|
||||||
|
{
|
||||||
|
/* copy hotpluged device mount point to the dev_array */
|
||||||
|
if (strstr(word, "/mnt/") != NULL || strstr(word, "/media/") != NULL)
|
||||||
|
{
|
||||||
|
dev_array[size].path = strdup(word);
|
||||||
|
dev_array[size++].to_add = TRUE;
|
||||||
|
}
|
||||||
|
free(word);
|
||||||
|
}
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
|
||||||
|
/* delete removed devices */
|
||||||
|
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
|
||||||
|
|
||||||
|
for (j = 0; j < count; j++)
|
||||||
|
{
|
||||||
|
BOOL dev_found = FALSE;
|
||||||
|
|
||||||
|
device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]);
|
||||||
|
|
||||||
|
/* not plugable device */
|
||||||
|
if (strstr(device_ext->path, "/mnt/") == NULL && strstr(device_ext->path, "/media/") == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
if (strstr(device_ext->path, dev_array[i].path) != NULL)
|
||||||
|
{
|
||||||
|
dev_found = TRUE;
|
||||||
|
dev_array[i].to_add = FALSE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev_found)
|
||||||
|
{
|
||||||
|
devman_unregister_device(rdpdr->devman, (void *)keys[j]);
|
||||||
|
ids[0] = keys[j];
|
||||||
|
rdpdr_send_device_list_remove_request(rdpdr, 1, ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add new devices */
|
||||||
|
for (i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
RDPDR_DRIVE* drive;
|
||||||
|
|
||||||
|
if (dev_array[i].to_add)
|
||||||
|
{
|
||||||
|
char* name;
|
||||||
|
|
||||||
|
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
|
||||||
|
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
|
||||||
|
|
||||||
|
drive->Type = RDPDR_DTYP_FILESYSTEM;
|
||||||
|
|
||||||
|
drive->Path = _strdup(dev_array[i].path);
|
||||||
|
name = strrchr(drive->Path, '/') + 1;
|
||||||
|
drive->Name = _strdup(name);
|
||||||
|
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(dev_array[i].path);
|
||||||
|
dev_array[i].path = NULL;
|
||||||
|
}
|
||||||
|
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* drive_hotplug_thread_func(void* arg)
|
||||||
|
{
|
||||||
|
rdpdrPlugin* rdpdr;
|
||||||
|
int mfd;
|
||||||
|
fd_set rfds;
|
||||||
|
struct timeval tv;
|
||||||
|
int rv;
|
||||||
|
|
||||||
|
rdpdr = (rdpdrPlugin *)arg;
|
||||||
|
|
||||||
|
rdpdr->stop_event = CreateEvent(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
|
mfd = open("/proc/mounts", O_RDONLY, 0);
|
||||||
|
if (mfd < 0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "ERROR: Unable to open /proc/mounts.");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(mfd, &rfds);
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
|
||||||
|
while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0)
|
||||||
|
{
|
||||||
|
if (WaitForSingleObject(rdpdr->stop_event, 0) == WAIT_OBJECT_0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (FD_ISSET(mfd, &rfds))
|
||||||
|
{
|
||||||
|
/* file /proc/mounts changed, handle this */
|
||||||
|
handle_hotplug(rdpdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
FD_ZERO(&rfds);
|
||||||
|
FD_SET(mfd, &rfds);
|
||||||
|
tv.tv_sec = 1;
|
||||||
|
tv.tv_usec = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
|
||||||
|
{
|
||||||
|
if (rdpdr->stop_event)
|
||||||
|
SetEvent(rdpdr->stop_event);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
||||||
{
|
{
|
||||||
UINT32 index;
|
UINT32 index;
|
||||||
|
@ -58,6 +493,11 @@ static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
|
||||||
for (index = 0; index < settings->DeviceCount; index++)
|
for (index = 0; index < settings->DeviceCount; index++)
|
||||||
{
|
{
|
||||||
device = settings->DeviceArray[index];
|
device = settings->DeviceArray[index];
|
||||||
|
if (strcmp(device->Name, "*") == 0)
|
||||||
|
{
|
||||||
|
rdpdr->hotplug_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)drive_hotplug_thread_func, rdpdr, 0, NULL);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
devman_load_device_service(rdpdr->devman, device);
|
devman_load_device_service(rdpdr->devman, device);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -497,6 +937,10 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
|
||||||
MessagePipe_Free(rdpdr->MsgPipe);
|
MessagePipe_Free(rdpdr->MsgPipe);
|
||||||
CloseHandle(rdpdr->thread);
|
CloseHandle(rdpdr->thread);
|
||||||
|
|
||||||
|
drive_hotplug_thread_terminate(rdpdr);
|
||||||
|
|
||||||
|
WaitForSingleObject(rdpdr->hotplug_thread, INFINITE);
|
||||||
|
|
||||||
rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle);
|
rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle);
|
||||||
|
|
||||||
if (rdpdr->data_in)
|
if (rdpdr->data_in)
|
||||||
|
|
|
@ -52,6 +52,14 @@ struct rdpdr_plugin
|
||||||
UINT16 versionMinor;
|
UINT16 versionMinor;
|
||||||
UINT16 clientID;
|
UINT16 clientID;
|
||||||
char computerName[256];
|
char computerName[256];
|
||||||
|
|
||||||
|
/* hotplug support */
|
||||||
|
HANDLE hotplug_thread;
|
||||||
|
#ifdef _WIN32
|
||||||
|
HWND hotplug_wnd;
|
||||||
|
#else
|
||||||
|
HANDLE stop_event;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);
|
int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s);
|
||||||
|
|
|
@ -201,12 +201,7 @@ static void* rdpsnd_server_thread(void* arg)
|
||||||
Stream_SetPosition(s, 0);
|
Stream_SetPosition(s, 0);
|
||||||
|
|
||||||
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
|
||||||
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
|
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
|
||||||
{
|
|
||||||
if (BytesReturned)
|
|
||||||
Stream_Seek(s, BytesReturned);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
if (!BytesReturned)
|
if (!BytesReturned)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -33,6 +33,8 @@ set(${MODULE_PREFIX}_SRCS
|
||||||
wf_rail.h
|
wf_rail.h
|
||||||
wf_interface.c
|
wf_interface.c
|
||||||
wf_interface.h
|
wf_interface.h
|
||||||
|
wf_floatbar.c
|
||||||
|
wf_floatbar.h
|
||||||
wfreerdp.rc
|
wfreerdp.rc
|
||||||
resource.h)
|
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
|
||||||
|
|
After Width: | Height: | Size: 49 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
After Width: | Height: | Size: 1.7 KiB |
|
@ -0,0 +1,466 @@
|
||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Windows Float Bar
|
||||||
|
*
|
||||||
|
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <Windows.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "wf_interface.h"
|
||||||
|
#include "wf_floatbar.h"
|
||||||
|
#include "wf_window.h"
|
||||||
|
#include "wf_gdi.h"
|
||||||
|
#include "resource.h"
|
||||||
|
|
||||||
|
typedef struct _Button Button;
|
||||||
|
|
||||||
|
/* TIMERs */
|
||||||
|
#define TIMER_HIDE 1
|
||||||
|
#define TIMER_ANIMAT_SHOW 2
|
||||||
|
#define TIMER_ANIMAT_HIDE 3
|
||||||
|
|
||||||
|
/* Button Type */
|
||||||
|
#define BUTTON_LOCKPIN 0
|
||||||
|
#define BUTTON_MINIMIZE 1
|
||||||
|
#define BUTTON_RESTORE 2
|
||||||
|
#define BUTTON_CLOSE 3
|
||||||
|
#define BTN_MAX 4
|
||||||
|
|
||||||
|
/* bmp size */
|
||||||
|
#define BACKGROUND_W 581
|
||||||
|
#define BACKGROUND_H 29
|
||||||
|
#define LOCK_X 13
|
||||||
|
#define MINIMIZE_X (BACKGROUND_W - 91)
|
||||||
|
#define CLOSE_X (BACKGROUND_W - 37)
|
||||||
|
#define RESTORE_X (BACKGROUND_W - 64)
|
||||||
|
|
||||||
|
#define BUTTON_Y 2
|
||||||
|
#define BUTTON_WIDTH 24
|
||||||
|
#define BUTTON_HEIGHT 24
|
||||||
|
|
||||||
|
struct _Button {
|
||||||
|
FloatBar* floatbar;
|
||||||
|
int type;
|
||||||
|
int x, y, h, w;
|
||||||
|
int active;
|
||||||
|
HBITMAP bmp;
|
||||||
|
HBITMAP bmp_act;
|
||||||
|
|
||||||
|
/* Lock Specified */
|
||||||
|
HBITMAP locked_bmp;
|
||||||
|
HBITMAP locked_bmp_act;
|
||||||
|
HBITMAP unlocked_bmp;
|
||||||
|
HBITMAP unlocked_bmp_act;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _FloatBar {
|
||||||
|
HWND parent;
|
||||||
|
HWND hwnd;
|
||||||
|
RECT rect;
|
||||||
|
LONG width;
|
||||||
|
LONG height;
|
||||||
|
wfContext* wfc;
|
||||||
|
Button* buttons[BTN_MAX];
|
||||||
|
BOOL shown;
|
||||||
|
BOOL locked;
|
||||||
|
HDC hdcmem;
|
||||||
|
HBITMAP background;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int button_hit(Button* button)
|
||||||
|
{
|
||||||
|
FloatBar* floatbar = button->floatbar;
|
||||||
|
|
||||||
|
switch (button->type)
|
||||||
|
{
|
||||||
|
case BUTTON_LOCKPIN:
|
||||||
|
if (!floatbar->locked)
|
||||||
|
{
|
||||||
|
button->bmp = button->locked_bmp;
|
||||||
|
button->bmp_act = button->locked_bmp_act;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button->bmp = button->unlocked_bmp;
|
||||||
|
button->bmp_act = button->unlocked_bmp_act;
|
||||||
|
}
|
||||||
|
|
||||||
|
floatbar->locked = ~floatbar->locked;
|
||||||
|
InvalidateRect(button->floatbar->hwnd, NULL, FALSE);
|
||||||
|
UpdateWindow(button->floatbar->hwnd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTON_MINIMIZE:
|
||||||
|
ShowWindow(floatbar->parent, SW_MINIMIZE);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTON_RESTORE:
|
||||||
|
wf_toggle_fullscreen(floatbar->wfc);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BUTTON_CLOSE:
|
||||||
|
SendMessage(floatbar->parent, WM_DESTROY, 0 , 0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int button_paint(Button* button, HDC hdc)
|
||||||
|
{
|
||||||
|
FloatBar* floatbar = button->floatbar;
|
||||||
|
|
||||||
|
SelectObject(floatbar->hdcmem, button->active ? button->bmp_act : button->bmp);
|
||||||
|
StretchBlt(hdc, button->x, button->y, button->w, button->h, floatbar->hdcmem, 0, 0, button->w, button->h, SRCCOPY);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Button* floatbar_create_button(FloatBar* floatbar, int type, int resid, int resid_act, int x, int y, int h, int w)
|
||||||
|
{
|
||||||
|
Button *button;
|
||||||
|
HDC hDC;
|
||||||
|
HDC hMemDC;
|
||||||
|
HBITMAP hBitmap;
|
||||||
|
HBITMAP hOldBitmap;
|
||||||
|
BITMAP bm;
|
||||||
|
|
||||||
|
button = (Button *)malloc(sizeof(Button));
|
||||||
|
|
||||||
|
if (!button)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
button->floatbar = floatbar;
|
||||||
|
button->type = type;
|
||||||
|
button->x = x;
|
||||||
|
button->y = y;
|
||||||
|
button->w = w;
|
||||||
|
button->h = h;
|
||||||
|
button->active = FALSE;
|
||||||
|
|
||||||
|
button->bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(resid), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
|
||||||
|
button->bmp_act = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(resid_act), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Button* floatbar_create_lock_button(FloatBar* floatbar,
|
||||||
|
int unlock_resid, int unlock_resid_act,
|
||||||
|
int lock_resid, int lock_resid_act,
|
||||||
|
int x, int y, int h, int w)
|
||||||
|
{
|
||||||
|
Button* button;
|
||||||
|
|
||||||
|
button = floatbar_create_button(floatbar, BUTTON_LOCKPIN, unlock_resid, unlock_resid_act, x, y, h, w);
|
||||||
|
|
||||||
|
if (!button)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
button->unlocked_bmp = button->bmp;
|
||||||
|
button->unlocked_bmp_act = button->bmp_act;
|
||||||
|
button->locked_bmp = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
|
||||||
|
button->locked_bmp_act = (HBITMAP)LoadImage(floatbar->wfc->hInstance, MAKEINTRESOURCE(lock_resid_act), IMAGE_BITMAP, w, h, LR_DEFAULTCOLOR);
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Button* floatbar_get_button(FloatBar* floatbar, int x, int y)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (y > BUTTON_Y && y < BUTTON_Y + BUTTON_HEIGHT)
|
||||||
|
for (i = 0; i < BTN_MAX; i++)
|
||||||
|
if (x > floatbar->buttons[i]->x && x < floatbar->buttons[i]->x + floatbar->buttons[i]->w)
|
||||||
|
return floatbar->buttons[i];
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int floatbar_paint(FloatBar* floatbar, HDC hdc)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!floatbar->wfc->fullscreen)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* paint background */
|
||||||
|
SelectObject(floatbar->hdcmem, floatbar->background);
|
||||||
|
StretchBlt(hdc, 0, 0, BACKGROUND_W, BACKGROUND_H, floatbar->hdcmem, 0, 0, BACKGROUND_W, BACKGROUND_H, SRCCOPY);
|
||||||
|
|
||||||
|
/* paint buttons */
|
||||||
|
for (i = 0; i < BTN_MAX; i++)
|
||||||
|
button_paint(floatbar->buttons[i], hdc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int floatbar_animation(FloatBar* floatbar, BOOL show)
|
||||||
|
{
|
||||||
|
SetTimer(floatbar->hwnd, show ? TIMER_ANIMAT_SHOW : TIMER_ANIMAT_HIDE, 10, NULL);
|
||||||
|
floatbar->shown = show;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
LRESULT CALLBACK floatbar_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
|
||||||
|
{
|
||||||
|
static int dragging = FALSE;
|
||||||
|
static int lbtn_dwn = FALSE;
|
||||||
|
static int btn_dwn_x = 0;
|
||||||
|
static FloatBar* floatbar;
|
||||||
|
static TRACKMOUSEEVENT tme;
|
||||||
|
|
||||||
|
PAINTSTRUCT ps;
|
||||||
|
Button* button;
|
||||||
|
HDC hdc;
|
||||||
|
int pos_x;
|
||||||
|
int pos_y;
|
||||||
|
|
||||||
|
int xScreen = GetSystemMetrics(SM_CXSCREEN);
|
||||||
|
|
||||||
|
switch(Msg)
|
||||||
|
{
|
||||||
|
case WM_CREATE:
|
||||||
|
floatbar = (FloatBar *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
||||||
|
floatbar->hwnd = hWnd;
|
||||||
|
floatbar->parent = GetParent(hWnd);
|
||||||
|
|
||||||
|
GetWindowRect(floatbar->hwnd, &floatbar->rect);
|
||||||
|
floatbar->width = floatbar->rect.right - floatbar->rect.left;
|
||||||
|
floatbar->height = floatbar->rect.bottom - floatbar->rect.top;
|
||||||
|
|
||||||
|
hdc = GetDC(hWnd);
|
||||||
|
floatbar->hdcmem = CreateCompatibleDC(hdc);
|
||||||
|
ReleaseDC(hWnd, hdc);
|
||||||
|
|
||||||
|
tme.cbSize = sizeof(TRACKMOUSEEVENT);
|
||||||
|
tme.dwFlags = TME_LEAVE;
|
||||||
|
tme.hwndTrack = hWnd;
|
||||||
|
tme.dwHoverTime = HOVER_DEFAULT;
|
||||||
|
|
||||||
|
SetTimer(hWnd, TIMER_HIDE, 3000, NULL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_PAINT:
|
||||||
|
hdc = BeginPaint(hWnd, &ps);
|
||||||
|
floatbar_paint(floatbar, hdc);
|
||||||
|
EndPaint(hWnd, &ps);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_LBUTTONDOWN:
|
||||||
|
pos_x = lParam & 0xffff;
|
||||||
|
pos_y = (lParam >> 16) & 0xffff;
|
||||||
|
|
||||||
|
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
||||||
|
if (!button)
|
||||||
|
{
|
||||||
|
SetCapture(hWnd);
|
||||||
|
dragging = TRUE;
|
||||||
|
btn_dwn_x = lParam & 0xffff;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
lbtn_dwn = TRUE;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_LBUTTONUP:
|
||||||
|
pos_x = lParam & 0xffff;
|
||||||
|
pos_y = (lParam >> 16) & 0xffff;
|
||||||
|
|
||||||
|
ReleaseCapture();
|
||||||
|
dragging = FALSE;
|
||||||
|
|
||||||
|
if (lbtn_dwn)
|
||||||
|
{
|
||||||
|
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
||||||
|
if (button)
|
||||||
|
button_hit(button);
|
||||||
|
lbtn_dwn = FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSEMOVE:
|
||||||
|
KillTimer(hWnd, TIMER_HIDE);
|
||||||
|
pos_x = lParam & 0xffff;
|
||||||
|
pos_y = (lParam >> 16) & 0xffff;
|
||||||
|
|
||||||
|
if (!floatbar->shown)
|
||||||
|
floatbar_animation(floatbar, TRUE);
|
||||||
|
|
||||||
|
if (dragging)
|
||||||
|
{
|
||||||
|
floatbar->rect.left = floatbar->rect.left + (lParam & 0xffff) - btn_dwn_x;
|
||||||
|
|
||||||
|
if (floatbar->rect.left < 0)
|
||||||
|
floatbar->rect.left = 0;
|
||||||
|
else if (floatbar->rect.left > xScreen - floatbar->width)
|
||||||
|
floatbar->rect.left = xScreen - floatbar->width;
|
||||||
|
|
||||||
|
MoveWindow(hWnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < BTN_MAX; i++)
|
||||||
|
floatbar->buttons[i]->active = FALSE;
|
||||||
|
|
||||||
|
button = floatbar_get_button(floatbar, pos_x, pos_y);
|
||||||
|
if (button)
|
||||||
|
button->active = TRUE;
|
||||||
|
|
||||||
|
InvalidateRect(hWnd, NULL, FALSE);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
TrackMouseEvent(&tme);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_CAPTURECHANGED:
|
||||||
|
dragging = FALSE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_MOUSELEAVE:
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < BTN_MAX; i++)
|
||||||
|
floatbar->buttons[i]->active = FALSE;
|
||||||
|
|
||||||
|
InvalidateRect(hWnd, NULL, FALSE);
|
||||||
|
UpdateWindow(hWnd);
|
||||||
|
|
||||||
|
SetTimer(hWnd, TIMER_HIDE, 3000, NULL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case WM_TIMER:
|
||||||
|
switch (wParam)
|
||||||
|
{
|
||||||
|
case TIMER_HIDE:
|
||||||
|
{
|
||||||
|
KillTimer(hWnd, TIMER_HIDE);
|
||||||
|
if (!floatbar->locked)
|
||||||
|
floatbar_animation(floatbar, FALSE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TIMER_ANIMAT_SHOW:
|
||||||
|
{
|
||||||
|
static int y = 0;
|
||||||
|
|
||||||
|
MoveWindow(floatbar->hwnd, floatbar->rect.left, (y++ - floatbar->height), floatbar->width, floatbar->height, TRUE);
|
||||||
|
if (y == floatbar->height)
|
||||||
|
{
|
||||||
|
y = 0;
|
||||||
|
KillTimer(hWnd, wParam);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TIMER_ANIMAT_HIDE:
|
||||||
|
{
|
||||||
|
static int y = 0;
|
||||||
|
|
||||||
|
MoveWindow(floatbar->hwnd, floatbar->rect.left, -y++, floatbar->width, floatbar->height, TRUE);
|
||||||
|
if (y == floatbar->height)
|
||||||
|
{
|
||||||
|
y = 0;
|
||||||
|
KillTimer(hWnd, wParam);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_DESTROY:
|
||||||
|
DeleteDC(floatbar->hdcmem);
|
||||||
|
PostQuitMessage(0);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return DefWindowProc(hWnd, Msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FloatBar* floatbar_create(wfContext* wfc)
|
||||||
|
{
|
||||||
|
FloatBar* floatbar;
|
||||||
|
|
||||||
|
floatbar = (FloatBar *)malloc(sizeof(FloatBar));
|
||||||
|
|
||||||
|
if (!floatbar)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
floatbar->locked = FALSE;
|
||||||
|
floatbar->shown = TRUE;
|
||||||
|
floatbar->hwnd = NULL;
|
||||||
|
floatbar->parent = wfc->hwnd;
|
||||||
|
floatbar->wfc = wfc;
|
||||||
|
floatbar->hdcmem = NULL;
|
||||||
|
|
||||||
|
floatbar->background = (HBITMAP)LoadImage(wfc->hInstance, MAKEINTRESOURCE(IDB_BACKGROUND), IMAGE_BITMAP, BACKGROUND_W, BACKGROUND_H, LR_DEFAULTCOLOR);
|
||||||
|
floatbar->buttons[0] = floatbar_create_button(floatbar, BUTTON_MINIMIZE, IDB_MINIMIZE, IDB_MINIMIZE_ACT, MINIMIZE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||||
|
floatbar->buttons[1] = floatbar_create_button(floatbar, BUTTON_RESTORE, IDB_RESTORE, IDB_RESTORE_ACT, RESTORE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||||
|
floatbar->buttons[2] = floatbar_create_button(floatbar, BUTTON_CLOSE, IDB_CLOSE, IDB_CLOSE_ACT, CLOSE_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||||
|
floatbar->buttons[3] = floatbar_create_lock_button(floatbar, IDB_UNLOCK, IDB_UNLOCK_ACT, IDB_LOCK, IDB_LOCK_ACT, LOCK_X, BUTTON_Y, BUTTON_HEIGHT, BUTTON_WIDTH);
|
||||||
|
|
||||||
|
return floatbar;
|
||||||
|
}
|
||||||
|
|
||||||
|
int floatbar_hide(FloatBar* floatbar)
|
||||||
|
{
|
||||||
|
MoveWindow(floatbar->hwnd, floatbar->rect.left, -floatbar->height, floatbar->width, floatbar->height, TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int floatbar_show(FloatBar* floatbar)
|
||||||
|
{
|
||||||
|
MoveWindow(floatbar->hwnd, floatbar->rect.left, floatbar->rect.top, floatbar->width, floatbar->height, TRUE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void floatbar_window_create(wfContext *wfc)
|
||||||
|
{
|
||||||
|
WNDCLASSEX wnd_cls;
|
||||||
|
HWND barWnd;
|
||||||
|
int x = (GetSystemMetrics(SM_CXSCREEN) - BACKGROUND_W) / 2;
|
||||||
|
|
||||||
|
wnd_cls.cbSize = sizeof(WNDCLASSEX);
|
||||||
|
wnd_cls.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
||||||
|
wnd_cls.lpfnWndProc = floatbar_proc;
|
||||||
|
wnd_cls.cbClsExtra = 0;
|
||||||
|
wnd_cls.cbWndExtra = 0;
|
||||||
|
wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
wnd_cls.hCursor = LoadCursor(wfc->hInstance, IDC_ARROW);
|
||||||
|
wnd_cls.hbrBackground = NULL;
|
||||||
|
wnd_cls.lpszMenuName = NULL;
|
||||||
|
wnd_cls.lpszClassName = L"floatbar";
|
||||||
|
wnd_cls.hInstance = wfc->hInstance;
|
||||||
|
wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
|
||||||
|
|
||||||
|
RegisterClassEx(&wnd_cls);
|
||||||
|
|
||||||
|
wfc->floatbar = floatbar_create(wfc);
|
||||||
|
|
||||||
|
barWnd = CreateWindowEx(WS_EX_TOPMOST, L"floatbar", L"floatbar", WS_CHILD, x, 0, BACKGROUND_W, BACKGROUND_H, wfc->hwnd, NULL, wfc->hInstance, wfc->floatbar);
|
||||||
|
if (barWnd == NULL)
|
||||||
|
return;
|
||||||
|
ShowWindow(barWnd, SW_SHOWNORMAL);
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* FreeRDP: A Remote Desktop Protocol Implementation
|
||||||
|
* Windows Float Bar
|
||||||
|
*
|
||||||
|
* Copyright 2013 Zhang Zhaolong <zhangzl2013@126.com>
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __WF_FLOATBAR_H__
|
||||||
|
#define __WF_FLOATBAR_H__
|
||||||
|
|
||||||
|
typedef struct _FloatBar FloatBar;
|
||||||
|
typedef struct wf_context wfContext;
|
||||||
|
|
||||||
|
void floatbar_window_create(wfContext* wfc);
|
||||||
|
int floatbar_show(FloatBar* floatbar);
|
||||||
|
int floatbar_hide(FloatBar* floatbar);
|
||||||
|
|
||||||
|
#endif
|
|
@ -322,6 +322,11 @@ void wf_toggle_fullscreen(wfContext* wfc)
|
||||||
wfc->disablewindowtracking = TRUE;
|
wfc->disablewindowtracking = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (wfc->fullscreen)
|
||||||
|
floatbar_show(wfc->floatbar);
|
||||||
|
else
|
||||||
|
floatbar_hide(wfc->floatbar);
|
||||||
|
|
||||||
SetParent(wfc->hwnd, wfc->fullscreen ? NULL : wfc->hWndParent);
|
SetParent(wfc->hwnd, wfc->fullscreen ? NULL : wfc->hWndParent);
|
||||||
wf_resize_window(wfc);
|
wf_resize_window(wfc);
|
||||||
ShowWindow(wfc->hwnd, SW_SHOW);
|
ShowWindow(wfc->hwnd, SW_SHOW);
|
||||||
|
@ -515,12 +520,18 @@ void wf_gdi_polyline(wfContext* wfc, POLYLINE_ORDER* polyline)
|
||||||
|
|
||||||
if (polyline->numPoints > 0)
|
if (polyline->numPoints > 0)
|
||||||
{
|
{
|
||||||
|
POINT temp;
|
||||||
|
|
||||||
|
temp.x = polyline->xStart;
|
||||||
|
temp.y = polyline->yStart;
|
||||||
pts = (POINT*) malloc(sizeof(POINT) * polyline->numPoints);
|
pts = (POINT*) malloc(sizeof(POINT) * polyline->numPoints);
|
||||||
|
|
||||||
for (i = 0; i < (int) polyline->numPoints; i++)
|
for (i = 0; i < (int) polyline->numPoints; i++)
|
||||||
{
|
{
|
||||||
pts[i].x = polyline->points[i].x;
|
temp.x += polyline->points[i].x;
|
||||||
pts[i].y = polyline->points[i].y;
|
temp.y += polyline->points[i].y;
|
||||||
|
pts[i].x = temp.x;
|
||||||
|
pts[i].y = temp.y;
|
||||||
|
|
||||||
if (wfc->drawing == wfc->primary)
|
if (wfc->drawing == wfc->primary)
|
||||||
wf_invalidate_region(wfc, pts[i].x, pts[i].y, pts[i].x + 1, pts[i].y + 1);
|
wf_invalidate_region(wfc, pts[i].x, pts[i].y, pts[i].x + 1, pts[i].y + 1);
|
||||||
|
|
|
@ -263,18 +263,16 @@ BOOL wf_pre_connect(freerdp* instance)
|
||||||
{
|
{
|
||||||
if (settings->UseMultimon)
|
if (settings->UseMultimon)
|
||||||
{
|
{
|
||||||
settings->DesktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
desktopWidth = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||||
settings->DesktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
desktopHeight = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
settings->DesktopWidth = GetSystemMetrics(SM_CXSCREEN);
|
desktopWidth = GetSystemMetrics(SM_CXSCREEN);
|
||||||
settings->DesktopHeight = GetSystemMetrics(SM_CYSCREEN);
|
desktopHeight = GetSystemMetrics(SM_CYSCREEN);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
desktopWidth = (desktopWidth + 3) & (~3);
|
|
||||||
|
|
||||||
if (desktopWidth != settings->DesktopWidth)
|
if (desktopWidth != settings->DesktopWidth)
|
||||||
{
|
{
|
||||||
freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, desktopWidth);
|
freerdp_set_param_uint32(settings, FreeRDP_DesktopWidth, desktopWidth);
|
||||||
|
@ -446,6 +444,7 @@ BOOL wf_post_connect(freerdp* instance)
|
||||||
freerdp_channels_post_connect(instance->context->channels, instance);
|
freerdp_channels_post_connect(instance->context->channels, instance);
|
||||||
|
|
||||||
wf_cliprdr_init(wfc, instance->context->channels);
|
wf_cliprdr_init(wfc, instance->context->channels);
|
||||||
|
floatbar_window_create(wfc);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <freerdp/codec/nsc.h>
|
#include <freerdp/codec/nsc.h>
|
||||||
#include <freerdp/client/file.h>
|
#include <freerdp/client/file.h>
|
||||||
|
|
||||||
|
#include "wf_floatbar.h"
|
||||||
#include "wf_event.h"
|
#include "wf_event.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -132,6 +133,7 @@ struct wf_context
|
||||||
int yCurrentScroll; // current vertical scroll value
|
int yCurrentScroll; // current vertical scroll value
|
||||||
int yMaxScroll; // maximum vertical scroll value
|
int yMaxScroll; // maximum vertical scroll value
|
||||||
cliprdrContext *cliprdr_context;
|
cliprdrContext *cliprdr_context;
|
||||||
|
FloatBar* floatbar;
|
||||||
};
|
};
|
||||||
typedef struct wf_context wfContext;
|
typedef struct wf_context wfContext;
|
||||||
|
|
||||||
|
|
|
@ -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),
|
window->handle = XCreateWindow(xfc->display, RootWindowOfScreen(xfc->screen),
|
||||||
x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual,
|
x, y, window->width, window->height, 0, xfc->depth, InputOutput, xfc->visual,
|
||||||
CWBackPixel | CWBackingStore | CWOverrideRedirect | CWColormap |
|
0, &xfc->attribs);
|
||||||
CWBorderPixel | CWWinGravity | CWBitGravity, &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",
|
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,
|
(UINT32) window->handle, window->left, window->top, window->right, window->bottom,
|
||||||
|
|
|
@ -866,8 +866,7 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
assert(NULL != hostname);
|
assert(NULL != hostname);
|
||||||
assert(NULL != common_name);
|
|
||||||
|
|
||||||
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||||
fprintf(stderr, "@ WARNING: CERTIFICATE NAME MISMATCH! @\n");
|
fprintf(stderr, "@ WARNING: CERTIFICATE NAME MISMATCH! @\n");
|
||||||
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
fprintf(stderr, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n");
|
||||||
|
@ -875,17 +874,14 @@ void tls_print_certificate_name_mismatch_error(char* hostname, char* common_name
|
||||||
fprintf(stderr, "does not match %s given in the certificate:\n", alt_names_count < 1 ? "the name" : "any of the names");
|
fprintf(stderr, "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, "Common Name (CN):\n");
|
||||||
fprintf(stderr, "\t%s\n", common_name ? common_name : "no CN found in certificate");
|
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);
|
assert(NULL != alt_names);
|
||||||
fprintf(stderr, "Alternative names:\n");
|
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");
|
fprintf(stderr, "A valid certificate for the wrong name should NOT be trusted!\n");
|
||||||
|
|
|
@ -165,48 +165,57 @@ DWORD GetEnvironmentVariableA(LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
||||||
|
|
||||||
DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
DWORD GetEnvironmentVariableEBA(LPCSTR envBlock, LPCSTR lpName, LPSTR lpBuffer, DWORD nSize)
|
||||||
{
|
{
|
||||||
int length;
|
int vLength = 0;
|
||||||
char* env = NULL;
|
char* env = NULL;
|
||||||
const char * penvb = envBlock;
|
const char * penvb = envBlock;
|
||||||
char *foundEquals;
|
char *foundEquals;
|
||||||
|
int nLength, fLength, lpNameLength;
|
||||||
|
|
||||||
|
if (!lpName || NULL == envBlock)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
lpNameLength = strlen(lpName);
|
||||||
|
if (0 == lpNameLength)
|
||||||
|
return 0;
|
||||||
|
|
||||||
while (*penvb && *(penvb+1))
|
while (*penvb && *(penvb+1))
|
||||||
{
|
{
|
||||||
length = strlen(penvb);
|
fLength = strlen(penvb);
|
||||||
foundEquals = strstr(penvb,"=");
|
foundEquals = strstr(penvb,"=");
|
||||||
if (foundEquals == NULL) {
|
if (foundEquals == NULL)
|
||||||
|
{
|
||||||
|
/* if no = sign is found the envBlock is broken */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nLength = foundEquals - penvb;
|
||||||
|
if (nLength != lpNameLength)
|
||||||
|
{
|
||||||
|
penvb += (fLength +1);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (strnicmp(penvb,lpName,foundEquals - penvb) == 0) {
|
if (strnicmp(penvb,lpName,nLength) == 0)
|
||||||
#else
|
#else
|
||||||
if (strncmp(penvb,lpName,foundEquals - penvb) == 0) {
|
if (strncmp(penvb,lpName,nLength) == 0)
|
||||||
#endif
|
#endif
|
||||||
if (*(penvb + (foundEquals - penvb)) == '=') {
|
{
|
||||||
// found variable ...
|
env = foundEquals + 1;
|
||||||
if (foundEquals == NULL) {
|
break;
|
||||||
return 0;
|
|
||||||
} else {
|
|
||||||
env = foundEquals + 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
penvb += (length +1);
|
penvb += (fLength +1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!env)
|
if (!env)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
length = strlen(env);
|
vLength = strlen(env);
|
||||||
|
|
||||||
if ((length + 1 > nSize) || (!lpBuffer))
|
if ((vLength + 1 > nSize) || (!lpBuffer))
|
||||||
return length + 1;
|
return vLength + 1;
|
||||||
|
|
||||||
CopyMemory(lpBuffer, env, length + 1);
|
CopyMemory(lpBuffer, env, vLength + 1);
|
||||||
|
|
||||||
return length;
|
return vLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -252,33 +261,23 @@ BOOL SetEnvironmentVariableEBA(LPSTR * envBlock,LPCSTR lpName, LPCSTR lpValue)
|
||||||
|
|
||||||
if (lpValue)
|
if (lpValue)
|
||||||
{
|
{
|
||||||
|
length = strlen(lpName) + strlen(lpValue) + 2; /* +2 because of = and \0 */
|
||||||
length = strlen(lpName) + strlen(lpValue) + 1;
|
envstr = (char*) malloc(length + 1); /* +1 because of closing \0 */
|
||||||
envstr = (char*) malloc(length + 1);
|
sprintf_s(envstr, length, "%s=%s", lpName, lpValue);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
length = strlen(lpName) + 1;
|
length = strlen(lpName) + 2; /* +2 because of = and \0 */
|
||||||
envstr = (char*) malloc(length + 1);
|
envstr = (char*) malloc(length + 1); /* +1 because of closing \0 */
|
||||||
sprintf_s(envstr, length + 1, "%s=", lpName);
|
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;
|
|
||||||
}
|
}
|
||||||
|
envstr[length] = '\0';
|
||||||
|
newEB = MergeEnvironmentStrings((LPCSTR)*envBlock,envstr);
|
||||||
|
free(envstr);
|
||||||
|
if (*envBlock != NULL)
|
||||||
|
free(*envBlock);
|
||||||
|
*envBlock = newEB;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -364,6 +363,7 @@ LPCH MergeEnvironmentStrings(PCSTR original, PCSTR merge)
|
||||||
// first build an char ** of the merge env strings
|
// first build an char ** of the merge env strings
|
||||||
|
|
||||||
mergeStrings = (LPCSTR*) malloc(mergeArraySize * sizeof(char *));
|
mergeStrings = (LPCSTR*) malloc(mergeArraySize * sizeof(char *));
|
||||||
|
ZeroMemory(mergeStrings,mergeArraySize * sizeof(char *));
|
||||||
mergeStringLenth = 0;
|
mergeStringLenth = 0;
|
||||||
|
|
||||||
cp = merge;
|
cp = merge;
|
||||||
|
|
|
@ -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 lpszEnvironmentBlock = "SHELL=123\0test=1\0test1=2\0DISPLAY=WINPR_TEST_VALUE\0\0";
|
||||||
LPTCH lpszEnvironmentBlockNew = NULL;
|
LPTCH lpszEnvironmentBlockNew = NULL;
|
||||||
|
|
||||||
|
/* Get length of an variable */
|
||||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", NULL, 0);
|
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", NULL, 0);
|
||||||
|
if (0 == length)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Get the variable itself */
|
||||||
p = (LPSTR) malloc(length);
|
p = (LPSTR) malloc(length);
|
||||||
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", p, length);
|
length = GetEnvironmentVariableEBA(lpszEnvironmentBlock,"DISPLAY", p, length);
|
||||||
|
|
||||||
|
@ -22,14 +26,47 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
|
||||||
|
|
||||||
if (strcmp(p, "WINPR_TEST_VALUE") != 0)
|
if (strcmp(p, "WINPR_TEST_VALUE") != 0)
|
||||||
{
|
{
|
||||||
|
free(p);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(p);
|
free(p);
|
||||||
|
|
||||||
lpszEnvironmentBlockNew = (LPTCH) malloc(1024);
|
/* Get length of an non-existing variable */
|
||||||
memcpy(lpszEnvironmentBlockNew,lpszEnvironmentBlock,56);
|
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 (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", "5"))
|
||||||
{
|
{
|
||||||
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
|
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
|
||||||
|
@ -44,13 +81,12 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Clear variable */
|
||||||
//free(lpszEnvironmentBlockNew);
|
|
||||||
|
|
||||||
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", NULL))
|
if (SetEnvironmentVariableEBA(&lpszEnvironmentBlockNew, "test", NULL))
|
||||||
{
|
{
|
||||||
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
|
if (GetEnvironmentVariableEBA(lpszEnvironmentBlockNew,"test", test, 1023))
|
||||||
{
|
{
|
||||||
|
free(lpszEnvironmentBlockNew);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -58,6 +94,34 @@ int TestEnvironmentGetSetEB(int argc, char* argv[])
|
||||||
// not found .. this is expected
|
// 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);
|
free(lpszEnvironmentBlockNew);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -251,6 +251,10 @@ BOOL _CreateProcessExA(HANDLE hToken, DWORD dwLogonFlags,
|
||||||
|
|
||||||
if (token->UserId)
|
if (token->UserId)
|
||||||
setuid((uid_t) 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)
|
if (execve(filename, pArgs, envp) < 0)
|
||||||
|
|