[client,common] fix file copy client to server

This commit is contained in:
Armin Novak 2023-02-27 14:50:43 +01:00 committed by akallabeth
parent 9fb4465722
commit 39c06a4683
2 changed files with 297 additions and 89 deletions

View File

@ -76,6 +76,7 @@ typedef struct
fuse_req_t req;
/*for FILECONTENTS_SIZE must be ino number* */
size_t req_ino;
UINT32 lockId;
} CliprdrFuseStream;
typedef struct
@ -89,7 +90,7 @@ typedef struct
struct timespec st_mtim;
char* name;
wArrayList* child_inos;
UINT32 streamID;
INT64 lockID;
} CliprdrFuseInode;
#endif
@ -97,12 +98,12 @@ typedef struct
{
char* name;
FILE* fp;
INT64 size;
} CliprdrLocalFile;
typedef struct
{
UINT32 streamID;
UINT32 lockId;
BOOL locked;
size_t count;
CliprdrLocalFile* files;
@ -126,14 +127,15 @@ struct cliprdr_file_context
BOOL file_formats_registered;
UINT32 file_capability_flags;
UINT32 local_stream_id;
UINT32 remote_stream_id;
UINT32 local_lock_id;
UINT32 remote_lock_id;
wHashTable* local_streams;
wLog* log;
void* clipboard;
CliprdrClientContext* context;
char* path;
char* current_path;
BYTE hash[WINPR_SHA256_DIGEST_LENGTH];
};
@ -144,7 +146,7 @@ static BOOL local_stream_discard(const void* key, void* value, void* arg);
#if defined(WITH_FUSE2) || defined(WITH_FUSE3)
static BOOL cliprdr_fuse_repopulate(CliprdrFileContext* file, wArrayList* list);
static UINT cliprdr_file_send_client_file_contents(CliprdrFileContext* file, UINT32 streamId,
UINT32 listIndex, UINT32 dwFlags,
UINT32 lockId, UINT32 listIndex, UINT32 dwFlags,
UINT32 nPositionLow, UINT32 nPositionHigh,
UINT32 cbRequested);
@ -195,14 +197,14 @@ static void cliprdr_file_fuse_node_free(void* obj)
free(inode);
}
static CliprdrFuseInode* cliprdr_file_fuse_node_new(UINT32 streamID, size_t lindex, size_t ino,
static CliprdrFuseInode* cliprdr_file_fuse_node_new(UINT32 lockID, size_t lindex, size_t ino,
size_t parent, const char* path, mode_t mode)
{
CliprdrFuseInode* node = (CliprdrFuseInode*)calloc(1, sizeof(CliprdrFuseInode));
if (!node)
goto fail;
node->streamID = streamID;
node->lockID = lockID;
node->ino = ino;
node->parent_ino = parent;
node->lindex = lindex;
@ -327,7 +329,8 @@ error:
static int cliprdr_file_fuse_util_get_and_update_stream_list(CliprdrFileContext* file,
fuse_req_t req, size_t ino,
UINT32 type, UINT32* stream_id)
UINT32 type, UINT32* stream_id,
UINT32* lockId)
{
int rc = ENOMEM;
@ -339,16 +342,17 @@ static int cliprdr_file_fuse_util_get_and_update_stream_list(CliprdrFileContext*
CliprdrFuseInode* node = cliprdr_file_fuse_util_get_inode(file->ino_list, ino);
if (node)
{
CliprdrFuseStream* stream = HashTable_GetItemValue(file->remote_streams, &node->streamID);
CliprdrFuseStream* stream = HashTable_GetItemValue(file->remote_streams, &node->lockID);
if (stream)
{
CliprdrFuseStream* request =
cliprdr_fuse_stream_new(node->streamID, req, stream->req_ino, type);
cliprdr_fuse_stream_new(node->lockID, req, stream->req_ino, type);
if (request)
{
if (Queue_Enqueue(file->requests_in_flight, stream))
{
*stream_id = node->streamID;
*stream_id = node->lockID;
*lockId = node->lockID;
rc = 0;
}
}
@ -369,7 +373,7 @@ static int cliprdr_file_fuse_util_add_stream_list(CliprdrFileContext* file)
if (!stream)
return err;
const BOOL res = HashTable_Insert(file->remote_streams, &stream->stream_id, stream);
const BOOL res = HashTable_Insert(file->remote_streams, &stream->lockId, stream);
if (!res)
{
cliprdr_fuse_stream_free(stream);
@ -533,8 +537,9 @@ void cliprdr_file_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t o
{
int err;
CliprdrFileContext* file = (CliprdrFileContext*)fuse_req_userdata(req);
UINT32 lindex;
UINT32 stream_id;
UINT32 lindex = 0;
UINT32 stream_id = 0;
UINT32 lock_id = 0;
WINPR_ASSERT(file);
@ -546,7 +551,7 @@ void cliprdr_file_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t o
}
err = cliprdr_file_fuse_util_get_and_update_stream_list(file, req, ino, FILECONTENTS_RANGE,
&stream_id);
&stream_id, &lock_id);
if (err)
{
fuse_reply_err(req, err);
@ -556,7 +561,7 @@ void cliprdr_file_fuse_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t o
UINT32 nPositionLow = (off >> 0) & 0xFFFFFFFF;
UINT32 nPositionHigh = (off >> 32) & 0xFFFFFFFF;
cliprdr_file_send_client_file_contents(file, stream_id, lindex, FILECONTENTS_RANGE,
cliprdr_file_send_client_file_contents(file, stream_id, lock_id, lindex, FILECONTENTS_RANGE,
nPositionLow, nPositionHigh, size);
}
@ -612,14 +617,16 @@ void cliprdr_file_fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char* nam
if (!size_set)
{
UINT32 streamID = 0;
UINT32 lockId = 0;
const int err = cliprdr_file_fuse_util_get_and_update_stream_list(
file, req, ino, FILECONTENTS_SIZE, &streamID);
file, req, ino, FILECONTENTS_SIZE, &streamID, &lockId);
if (err != 0)
{
fuse_reply_err(req, err);
return;
}
cliprdr_file_send_client_file_contents(file, streamID, lindex, FILECONTENTS_SIZE, 0, 0, 0);
cliprdr_file_send_client_file_contents(file, streamID, lockId, lindex, FILECONTENTS_SIZE, 0,
0, 0);
return;
}
e.ino = ino;
@ -748,12 +755,11 @@ static BOOL add_stream_node(const void* key, void* value, void* arg)
WINPR_ASSERT(node_arg->root);
char name[10] = { 0 };
_snprintf(name, sizeof(name), "%08" PRIx32, stream->stream_id);
_snprintf(name, sizeof(name), "%08" PRIx32, stream->lockId);
const size_t idx = ArrayList_Count(node_arg->list);
CliprdrFuseInode* node =
cliprdr_file_fuse_node_new(stream->stream_id, idx, FUSE_ROOT_ID + 1 + stream->stream_id,
FUSE_ROOT_ID, name, S_IFDIR | 0700);
CliprdrFuseInode* node = cliprdr_file_fuse_node_new(
stream->lockId, idx, FUSE_ROOT_ID + 1 + stream->lockId, FUSE_ROOT_ID, name, S_IFDIR | 0700);
if (!node)
return FALSE;
node->size_set = TRUE;
@ -799,14 +805,17 @@ fail:
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_file_send_client_file_contents(CliprdrFileContext* file, UINT32 streamId,
UINT32 listIndex, UINT32 dwFlags,
UINT32 lockId, UINT32 listIndex, UINT32 dwFlags,
UINT32 nPositionLow, UINT32 nPositionHigh,
UINT32 cbRequested)
{
CLIPRDR_FILE_CONTENTS_REQUEST formatFileContentsRequest = { 0 };
formatFileContentsRequest.streamId = streamId;
formatFileContentsRequest.listIndex = listIndex;
formatFileContentsRequest.dwFlags = dwFlags;
CLIPRDR_FILE_CONTENTS_REQUEST formatFileContentsRequest = {
.streamId = streamId,
.clipDataId = lockId,
.haveClipDataId = cliprdr_file_context_current_flags(file) & CB_CAN_LOCK_CLIPDATA,
.listIndex = listIndex,
.dwFlags = dwFlags
};
WINPR_ASSERT(file);
switch (dwFlags)
@ -1001,7 +1010,8 @@ static BOOL cliprdr_file_fuse_create_nodes(CliprdrFileContext* file, wStream* s,
char curName[ARRAYSIZE(descriptor.cFileName)] = { 0 };
char dirName[ARRAYSIZE(descriptor.cFileName)] = { 0 };
Stream_Read(s, &descriptor, sizeof(FILEDESCRIPTORW));
if (!cliprdr_read_filedescriptor(s, &descriptor))
goto fail;
ConvertWCharNToUtf8(descriptor.cFileName, ARRAYSIZE(descriptor.cFileName), curName,
ARRAYSIZE(curName));
@ -1015,7 +1025,7 @@ static BOOL cliprdr_file_fuse_create_nodes(CliprdrFileContext* file, wStream* s,
CliprdrFuseInode* inode = NULL;
if (split_point == NULL)
{
inode = cliprdr_file_fuse_node_new(rootNode->streamID, lindex, nextIno++, rootNode->ino,
inode = cliprdr_file_fuse_node_new(rootNode->lockID, lindex, nextIno++, rootNode->ino,
curName, 0700);
if (!ArrayList_Append(file->ino_list, inode))
goto fail;
@ -1032,7 +1042,7 @@ static BOOL cliprdr_file_fuse_create_nodes(CliprdrFileContext* file, wStream* s,
parent = (CliprdrFuseInode*)HashTable_GetItemValue(mapDir, dirName);
if (!parent)
goto fail;
inode = cliprdr_file_fuse_node_new(rootNode->streamID, lindex, nextIno++, parent->ino,
inode = cliprdr_file_fuse_node_new(rootNode->lockID, lindex, nextIno++, parent->ino,
baseName, 0700);
if (!inode)
goto fail;
@ -1172,33 +1182,52 @@ static UINT cliprdr_file_context_send_contents(CliprdrClientContext* context,
return context->ClientFileContentsResponse(context, &response);
}
static FILE* file_for_request(CliprdrFileContext* file, UINT32 streamId, UINT32 listIndex)
static CliprdrLocalFile* file_info_for_request(CliprdrFileContext* file, UINT32 lockId,
UINT32 listIndex)
{
FILE* fp = NULL;
HashTable_Lock(file->local_streams);
WINPR_ASSERT(file);
CliprdrLocalStream* cur = HashTable_GetItemValue(file->local_streams, &streamId);
CliprdrLocalStream* cur = HashTable_GetItemValue(file->local_streams, &lockId);
if (cur)
{
if (listIndex < cur->count)
{
CliprdrLocalFile* f = &cur->files[listIndex];
if (f->fp)
fp = f->fp;
else
{
if (strncmp("file://", f->name, 7) == 0)
fp = fopen(&f->name[7], "rb");
else
fp = fopen(f->name, "rb");
f->fp = fp;
}
WLog_INFO("xxxx", "got %s [%" PRIu32 "]", f->name, listIndex);
return f;
}
}
HashTable_Unlock(file->local_streams);
return NULL;
}
return fp;
static CliprdrLocalFile* file_for_request(CliprdrFileContext* file, UINT32 lockId, UINT32 listIndex)
{
CliprdrLocalFile* f = file_info_for_request(file, lockId, listIndex);
if (f)
{
if (!f->fp)
{
const char* name = f->name;
f->fp = winpr_fopen(name, "rb");
}
if (!f->fp)
return NULL;
}
return f;
}
static void cliprdr_local_file_try_close(CliprdrLocalFile* file, UINT res, UINT64 offset,
UINT64 size)
{
WINPR_ASSERT(file);
if ((res != 0) || ((file->size > 0) && (offset + size >= file->size)))
{
fclose(file->fp);
file->fp = NULL;
}
}
static UINT cliprdr_file_context_server_file_size_request(
@ -1217,15 +1246,23 @@ static UINT cliprdr_file_context_server_file_size_request(
fileContentsRequest->cbRequested);
}
FILE* fp =
file_for_request(file, fileContentsRequest->streamId, fileContentsRequest->listIndex);
if (!fp)
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
HashTable_Lock(file->local_streams);
if (_fseeki64(fp, 0, SEEK_END) < 0)
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
UINT res = CHANNEL_RC_OK;
CliprdrLocalFile* rfile =
file_for_request(file, fileContentsRequest->clipDataId, fileContentsRequest->listIndex);
if (!rfile)
res = cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
const INT64 size = _ftelli64(fp);
if (_fseeki64(rfile->fp, 0, SEEK_END) < 0)
res = cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
const INT64 size = _ftelli64(rfile->fp);
rfile->size = size;
cliprdr_local_file_try_close(rfile, res, 0, 0);
HashTable_Unlock(file->local_streams);
if (res != CHANNEL_RC_OK)
return res;
return cliprdr_file_context_send_contents(file->context, fileContentsRequest, &size,
sizeof(size));
}
@ -1234,52 +1271,71 @@ static UINT cliprdr_file_context_server_file_range_request(
CliprdrFileContext* file, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
BYTE* data = NULL;
wClipboardFileRangeRequest request = { 0 };
WINPR_ASSERT(fileContentsRequest);
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
request.nPositionLow = fileContentsRequest->nPositionLow;
request.nPositionHigh = fileContentsRequest->nPositionHigh;
request.cbRequested = fileContentsRequest->cbRequested;
FILE* fp =
file_for_request(file, fileContentsRequest->streamId, fileContentsRequest->listIndex);
if (!fp)
goto fail;
HashTable_Lock(file->local_streams);
const UINT64 offset = (((UINT64)fileContentsRequest->nPositionHigh) << 32) |
((UINT64)fileContentsRequest->nPositionLow);
if (_fseeki64(fp, offset, SEEK_SET) < 0)
CliprdrLocalFile* rfile =
file_for_request(file, fileContentsRequest->clipDataId, fileContentsRequest->listIndex);
if (!rfile)
goto fail;
if (_fseeki64(rfile->fp, offset, SEEK_SET) < 0)
goto fail;
data = malloc(fileContentsRequest->cbRequested);
if (!data)
goto fail;
const size_t r = fread(data, 1, fileContentsRequest->cbRequested, fp);
const size_t r = fread(data, 1, fileContentsRequest->cbRequested, rfile->fp);
const UINT rc = cliprdr_file_context_send_contents(file->context, fileContentsRequest, data, r);
free(data);
cliprdr_local_file_try_close(rfile, rc, offset, fileContentsRequest->cbRequested);
HashTable_Unlock(file->local_streams);
return rc;
fail:
cliprdr_local_file_try_close(rfile, ERROR_INTERNAL_ERROR, offset,
fileContentsRequest->cbRequested);
free(data);
HashTable_Unlock(file->local_streams);
return cliprdr_file_context_send_file_contents_failure(file->context, fileContentsRequest);
}
static UINT change_lock(CliprdrFileContext* file, UINT32 streamID, BOOL lock)
static BOOL update_sub_path(CliprdrFileContext* file, UINT32 lockID)
{
WINPR_ASSERT(file);
WINPR_ASSERT(file->path);
char lockstr[32] = { 0 };
_snprintf(lockstr, sizeof(lockstr), "%08" PRIx32, lockID);
free(file->current_path);
file->current_path = GetCombinedPath(file->path, lockstr);
return file->current_path != NULL;
}
static UINT change_lock(CliprdrFileContext* file, UINT32 lockId, BOOL lock)
{
WINPR_ASSERT(file);
HashTable_Lock(file->local_streams);
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &streamID);
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &lockId);
if (lock && !stream)
{
stream = cliprdr_local_stream_new(streamID, NULL, 0);
HashTable_Insert(file->local_streams, &streamID, stream);
file->local_stream_id = streamID;
stream = cliprdr_local_stream_new(lockId, NULL, 0);
HashTable_Insert(file->local_streams, &lockId, stream);
file->local_lock_id = lockId;
}
if (stream)
{
stream->locked = lock;
stream->lockId = lockId;
update_sub_path(file, lockId);
}
if (!lock)
HashTable_Foreach(file->local_streams, local_stream_discard, file);
@ -1432,7 +1488,7 @@ void* cliprdr_file_context_get_context(CliprdrFileContext* file)
return file->clipboard;
}
const char* cliprdr_file_context_base_path(CliprdrFileContext* file)
static const char* cliprdr_file_context_base_path(CliprdrFileContext* file)
{
WINPR_ASSERT(file);
return file->path;
@ -1474,6 +1530,7 @@ void cliprdr_file_context_free(CliprdrFileContext* file)
HashTable_Free(file->local_streams);
winpr_RemoveDirectory(file->path);
free(file->path);
free(file->current_path);
free(file);
}
@ -1482,12 +1539,15 @@ static BOOL create_base_path(CliprdrFileContext* file)
WINPR_ASSERT(file);
char base[64] = { 0 };
_snprintf(base, sizeof(base), "/.xfreerdp.cliprdr.%" PRIu32, GetCurrentProcessId());
_snprintf(base, sizeof(base), "com.freerdp.client.cliprdr.%" PRIu32, GetCurrentProcessId());
file->path = GetKnownSubPath(KNOWN_PATH_TEMP, base);
if (!file->path)
return FALSE;
if (!update_sub_path(file, 0))
return FALSE;
if (!winpr_PathFileExists(file->path) && !winpr_PathMakePath(file->path, 0))
{
WLog_Print(file->log, WLOG_ERROR, "Failed to create directory '%s'", file->path);
@ -1498,32 +1558,150 @@ static BOOL create_base_path(CliprdrFileContext* file)
static void cliprdr_local_file_free(CliprdrLocalFile* file)
{
const CliprdrLocalFile empty = { 0 };
if (!file)
return;
if (file->fp)
fclose(file->fp);
free(file->name);
*file = empty;
}
static BOOL cliprdr_local_file_new(CliprdrLocalFile* f, const char* path)
{
const CliprdrLocalFile empty = { 0 };
WINPR_ASSERT(f);
WINPR_ASSERT(path);
*f = empty;
f->name = _strdup(path);
if (!f->name)
goto fail;
return TRUE;
fail:
cliprdr_local_file_free(f);
return FALSE;
}
static void cliprdr_local_files_free(CliprdrLocalStream* stream)
{
WINPR_ASSERT(stream);
for (size_t x = 0; x < stream->count; x++)
cliprdr_local_file_free(&stream->files[x]);
free(stream->files);
stream->files = NULL;
stream->count = 0;
}
static void cliprdr_local_stream_free(void* obj)
{
CliprdrLocalStream* stream = (CliprdrLocalStream*)obj;
if (stream)
{
for (size_t x = 0; x < stream->count; x++)
cliprdr_local_file_free(&stream->files[x]);
free(stream->files);
}
cliprdr_local_files_free(stream);
free(stream);
}
static BOOL append_entry(CliprdrLocalStream* stream, const char* path)
{
CliprdrLocalFile* tmp = realloc(stream->files, sizeof(CliprdrLocalFile) * (stream->count + 1));
if (!tmp)
return FALSE;
stream->files = tmp;
CliprdrLocalFile* f = &stream->files[stream->count++];
return cliprdr_local_file_new(f, path);
}
static BOOL is_directory(const char* path)
{
WCHAR* wpath = ConvertUtf8ToWCharAlloc(path, NULL);
if (!wpath)
return FALSE;
HANDLE hFile =
CreateFileW(wpath, 0, FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
free(wpath);
if (hFile == INVALID_HANDLE_VALUE)
return FALSE;
BY_HANDLE_FILE_INFORMATION fileInformation = { 0 };
const BOOL status = GetFileInformationByHandle(hFile, &fileInformation);
CloseHandle(hFile);
if (!status)
return FALSE;
return fileInformation.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
}
static BOOL add_directory(CliprdrLocalStream* stream, const char* path)
{
char* wildcardpath = GetCombinedPath(path, "*");
if (!wildcardpath)
return FALSE;
WCHAR* wpath = ConvertUtf8ToWCharAlloc(wildcardpath, NULL);
free(wildcardpath);
if (!wpath)
return FALSE;
WIN32_FIND_DATAW FindFileData = { 0 };
HANDLE hFind = FindFirstFileW(wpath, &FindFileData);
free(wpath);
if (hFind == INVALID_HANDLE_VALUE)
return FALSE;
BOOL rc = FALSE;
char* next = NULL;
do
{
const WCHAR dot[] = { '.', '\0' };
const WCHAR dotdot[] = { '.', '.', '\0' };
if (_wcscmp(FindFileData.cFileName, dot) == 0)
continue;
if (_wcscmp(FindFileData.cFileName, dotdot) == 0)
continue;
char cFileName[MAX_PATH] = { 0 };
ConvertWCharNToUtf8(FindFileData.cFileName, ARRAYSIZE(FindFileData.cFileName), cFileName,
ARRAYSIZE(cFileName));
free(next);
next = GetCombinedPath(path, cFileName);
if (!next)
goto fail;
if (!append_entry(stream, next))
goto fail;
if (is_directory(next))
{
if (!add_directory(stream, next))
goto fail;
}
} while (FindNextFileW(hFind, &FindFileData));
rc = TRUE;
fail:
free(next);
FindClose(hFind);
return rc;
}
static BOOL cliprdr_local_stream_update(CliprdrLocalStream* stream, const char* data, size_t size)
{
BOOL rc = FALSE;
WINPR_ASSERT(stream);
if (size == 0)
return TRUE;
free(stream->files);
cliprdr_local_files_free(stream);
stream->files = calloc(size, sizeof(CliprdrLocalFile));
if (!stream->files)
return FALSE;
@ -1534,14 +1712,31 @@ static BOOL cliprdr_local_stream_update(CliprdrLocalStream* stream, const char*
char* ptr = strtok(copy, "\r\n");
while (ptr)
{
stream->files[stream->count++].name = _strdup(ptr);
const char* name = ptr;
if (strncmp("file:///", ptr, 8) == 0)
name = &ptr[7];
else if (strncmp("file:/", ptr, 6) == 0)
name = &ptr[5];
if (!append_entry(stream, name))
goto fail;
if (is_directory(name))
{
const BOOL res = add_directory(stream, name);
if (!res)
goto fail;
}
ptr = strtok(NULL, "\r\n");
}
rc = TRUE;
fail:
free(copy);
return TRUE;
return rc;
}
CliprdrLocalStream* cliprdr_local_stream_new(UINT32 streamID, const char* data, size_t size)
CliprdrLocalStream* cliprdr_local_stream_new(UINT32 lockId, const char* data, size_t size)
{
CliprdrLocalStream* stream = calloc(1, sizeof(CliprdrLocalStream));
if (!stream)
@ -1550,7 +1745,7 @@ CliprdrLocalStream* cliprdr_local_stream_new(UINT32 streamID, const char* data,
if (!cliprdr_local_stream_update(stream, data, size))
goto fail;
stream->streamID = streamID;
stream->lockId = lockId;
return stream;
fail:
@ -1587,6 +1782,7 @@ static void* UINTPointerClone(const void* other)
*copy = *src;
return copy;
}
CliprdrFileContext* cliprdr_file_context_new(void* context)
{
CliprdrFileContext* file = calloc(1, sizeof(CliprdrFileContext));
@ -1680,6 +1876,7 @@ BOOL local_stream_discard(const void* key, void* value, void* arg)
return TRUE;
}
#if defined(WITH_FUSE2) || defined(WITH_FUSE3)
static BOOL remote_stream_discard(const void* key, void* value, void* arg)
{
CliprdrFuseStream* stream = (CliprdrFuseStream*)value;
@ -1691,6 +1888,7 @@ static BOOL remote_stream_discard(const void* key, void* value, void* arg)
fuse_reply_err(stream->req, EIO);
return HashTable_Remove(file->remote_streams, key);
}
#endif
BOOL cliprdr_file_context_clear(CliprdrFileContext* file)
{
@ -1706,17 +1904,17 @@ BOOL cliprdr_file_context_update_client_data(CliprdrFileContext* file, const cha
size_t size)
{
BOOL rc = FALSE;
UINT32 streamID = file->local_stream_id++;
UINT32 lockId = file->local_lock_id;
HashTable_Lock(file->local_streams);
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &streamID);
CliprdrLocalStream* stream = HashTable_GetItemValue(file->local_streams, &lockId);
if (stream)
rc = cliprdr_local_stream_update(stream, data, size);
else
{
stream = cliprdr_local_stream_new(streamID, data, size);
rc = HashTable_Insert(file->local_streams, &streamID, stream);
stream = cliprdr_local_stream_new(lockId, data, size);
rc = HashTable_Insert(file->local_streams, &stream->lockId, stream);
}
HashTable_Unlock(file->local_streams);
return rc;
@ -1755,3 +1953,12 @@ UINT32 cliprdr_file_context_remote_get_flags(CliprdrFileContext* file)
WINPR_ASSERT(file);
return file->file_capability_flags;
}
BOOL cliprdr_file_context_update_base(CliprdrFileContext* file, wClipboard* clip)
{
wClipboardDelegate* delegate = ClipboardGetDelegate(clip);
if (!delegate)
return FALSE;
delegate->basePath = file->current_path;
return TRUE;
}

View File

@ -41,7 +41,8 @@ extern "C"
FREERDP_API UINT32 cliprdr_file_context_current_flags(CliprdrFileContext* file);
FREERDP_API void* cliprdr_file_context_get_context(CliprdrFileContext* file);
FREERDP_API const char* cliprdr_file_context_base_path(CliprdrFileContext* file);
FREERDP_API BOOL cliprdr_file_context_update_base(CliprdrFileContext* file, wClipboard* clip);
FREERDP_API BOOL cliprdr_file_context_init(CliprdrFileContext* file,
CliprdrClientContext* cliprdr);