Proxy cleanups (#7568)
* Fixed C++ issues with proxy context * Added freerdp_settings_get_string_writable * Define WITH_PROXY_EMULATE_SMARTCARD in config.h
This commit is contained in:
parent
02535ea200
commit
724c6f8192
@ -177,5 +177,6 @@
|
||||
|
||||
/* Proxy */
|
||||
#cmakedefine WITH_PROXY_MODULES
|
||||
#cmakedefine WITH_PROXY_EMULATE_SMARTCARD
|
||||
|
||||
#endif /* FREERDP_CONFIG_H */
|
||||
|
@ -29,123 +29,124 @@
|
||||
|
||||
#define PROXY_SESSION_ID_LENGTH 32
|
||||
|
||||
typedef struct proxy_data proxyData;
|
||||
typedef struct proxy_module proxyModule;
|
||||
typedef struct channel_data_event_info proxyChannelDataEventInfo;
|
||||
|
||||
typedef struct _InterceptContextMapEntry
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
void (*free)(struct _InterceptContextMapEntry*);
|
||||
} InterceptContextMapEntry;
|
||||
#endif
|
||||
|
||||
/* All proxy interception channels derive from this base struct
|
||||
* and set their cleanup function accordingly. */
|
||||
static INLINE void intercept_context_entry_free(void* obj)
|
||||
{
|
||||
InterceptContextMapEntry* entry = obj;
|
||||
if (!entry)
|
||||
return;
|
||||
if (!entry->free)
|
||||
return;
|
||||
entry->free(entry);
|
||||
}
|
||||
typedef struct proxy_data proxyData;
|
||||
typedef struct proxy_module proxyModule;
|
||||
typedef struct channel_data_event_info proxyChannelDataEventInfo;
|
||||
|
||||
/**
|
||||
* Wraps rdpContext and holds the state for the proxy's server.
|
||||
*/
|
||||
struct p_server_context
|
||||
{
|
||||
rdpContext context;
|
||||
|
||||
proxyData* pdata;
|
||||
|
||||
HANDLE vcm;
|
||||
HANDLE dynvcReady;
|
||||
|
||||
wHashTable* interceptContextMap;
|
||||
};
|
||||
typedef struct p_server_context pServerContext;
|
||||
|
||||
/**
|
||||
* Wraps rdpContext and holds the state for the proxy's client.
|
||||
*/
|
||||
typedef struct p_client_context pClientContext;
|
||||
|
||||
struct p_client_context
|
||||
{
|
||||
rdpContext context;
|
||||
|
||||
proxyData* pdata;
|
||||
|
||||
/*
|
||||
* In a case when freerdp_connect fails,
|
||||
* Used for NLA fallback feature, to check if the server should close the connection.
|
||||
* When it is set to TRUE, proxy's client knows it shouldn't signal the server thread to
|
||||
* closed the connection when pf_client_post_disconnect is called, because it is trying to
|
||||
* connect reconnect without NLA. It must be set to TRUE before the first try, and to FALSE
|
||||
* after the connection fully established, to ensure graceful shutdown of the connection
|
||||
* when it will be closed.
|
||||
*/
|
||||
BOOL allow_next_conn_failure;
|
||||
|
||||
BOOL connected; /* Set after client post_connect. */
|
||||
|
||||
pReceiveChannelData client_receive_channel_data_original;
|
||||
wQueue* cached_server_channel_data;
|
||||
BOOL (*sendChannelData)(pClientContext* pc, const proxyChannelDataEventInfo* ev);
|
||||
|
||||
/* X509 specific */
|
||||
char* remote_hostname;
|
||||
wStream* remote_pem;
|
||||
UINT16 remote_port;
|
||||
UINT32 remote_flags;
|
||||
|
||||
BOOL input_state_sync_pending;
|
||||
UINT32 input_state;
|
||||
|
||||
wHashTable* interceptContextMap;
|
||||
UINT32 computerNameLen;
|
||||
BOOL computerNameUnicode;
|
||||
union
|
||||
typedef struct _InterceptContextMapEntry
|
||||
{
|
||||
WCHAR* wc;
|
||||
char* c;
|
||||
void* v;
|
||||
} computerName;
|
||||
};
|
||||
void (*free)(struct _InterceptContextMapEntry*);
|
||||
} InterceptContextMapEntry;
|
||||
|
||||
/**
|
||||
* Holds data common to both sides of a proxy's session.
|
||||
*/
|
||||
struct proxy_data
|
||||
{
|
||||
proxyModule* module;
|
||||
const proxyConfig* config;
|
||||
/* All proxy interception channels derive from this base struct
|
||||
* and set their cleanup function accordingly. */
|
||||
FREERDP_API void intercept_context_entry_free(void* obj);
|
||||
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
/**
|
||||
* Wraps rdpContext and holds the state for the proxy's server.
|
||||
*/
|
||||
struct p_server_context
|
||||
{
|
||||
rdpContext context;
|
||||
|
||||
HANDLE abort_event;
|
||||
HANDLE client_thread;
|
||||
HANDLE gfx_server_ready;
|
||||
proxyData* pdata;
|
||||
|
||||
char session_id[PROXY_SESSION_ID_LENGTH + 1];
|
||||
HANDLE vcm;
|
||||
HANDLE dynvcReady;
|
||||
|
||||
/* used to external modules to store per-session info */
|
||||
wHashTable* modules_info;
|
||||
psPeerReceiveChannelData server_receive_channel_data_original;
|
||||
};
|
||||
wHashTable* interceptContextMap;
|
||||
};
|
||||
typedef struct p_server_context pServerContext;
|
||||
|
||||
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src);
|
||||
BOOL pf_context_init_server_context(freerdp_peer* client);
|
||||
pClientContext* pf_context_create_client_context(rdpSettings* clientSettings);
|
||||
/**
|
||||
* Wraps rdpContext and holds the state for the proxy's client.
|
||||
*/
|
||||
typedef struct p_client_context pClientContext;
|
||||
|
||||
proxyData* proxy_data_new(void);
|
||||
void proxy_data_set_client_context(proxyData* pdata, pClientContext* context);
|
||||
void proxy_data_set_server_context(proxyData* pdata, pServerContext* context);
|
||||
void proxy_data_free(proxyData* pdata);
|
||||
struct p_client_context
|
||||
{
|
||||
rdpContext context;
|
||||
|
||||
BOOL proxy_data_shall_disconnect(proxyData* pdata);
|
||||
void proxy_data_abort_connect(proxyData* pdata);
|
||||
proxyData* pdata;
|
||||
|
||||
/*
|
||||
* In a case when freerdp_connect fails,
|
||||
* Used for NLA fallback feature, to check if the server should close the connection.
|
||||
* When it is set to TRUE, proxy's client knows it shouldn't signal the server thread to
|
||||
* closed the connection when pf_client_post_disconnect is called, because it is trying to
|
||||
* connect reconnect without NLA. It must be set to TRUE before the first try, and to FALSE
|
||||
* after the connection fully established, to ensure graceful shutdown of the connection
|
||||
* when it will be closed.
|
||||
*/
|
||||
BOOL allow_next_conn_failure;
|
||||
|
||||
BOOL connected; /* Set after client post_connect. */
|
||||
|
||||
pReceiveChannelData client_receive_channel_data_original;
|
||||
wQueue* cached_server_channel_data;
|
||||
BOOL (*sendChannelData)(pClientContext* pc, const proxyChannelDataEventInfo* ev);
|
||||
|
||||
/* X509 specific */
|
||||
char* remote_hostname;
|
||||
wStream* remote_pem;
|
||||
UINT16 remote_port;
|
||||
UINT32 remote_flags;
|
||||
|
||||
BOOL input_state_sync_pending;
|
||||
UINT32 input_state;
|
||||
|
||||
wHashTable* interceptContextMap;
|
||||
UINT32 computerNameLen;
|
||||
BOOL computerNameUnicode;
|
||||
union
|
||||
{
|
||||
WCHAR* wc;
|
||||
char* c;
|
||||
void* v;
|
||||
} computerName;
|
||||
};
|
||||
|
||||
/**
|
||||
* Holds data common to both sides of a proxy's session.
|
||||
*/
|
||||
struct proxy_data
|
||||
{
|
||||
proxyModule* module;
|
||||
const proxyConfig* config;
|
||||
|
||||
pServerContext* ps;
|
||||
pClientContext* pc;
|
||||
|
||||
HANDLE abort_event;
|
||||
HANDLE client_thread;
|
||||
HANDLE gfx_server_ready;
|
||||
|
||||
char session_id[PROXY_SESSION_ID_LENGTH + 1];
|
||||
|
||||
/* used to external modules to store per-session info */
|
||||
wHashTable* modules_info;
|
||||
psPeerReceiveChannelData server_receive_channel_data_original;
|
||||
};
|
||||
|
||||
FREERDP_API BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src);
|
||||
FREERDP_API BOOL pf_context_init_server_context(freerdp_peer* client);
|
||||
FREERDP_API pClientContext* pf_context_create_client_context(rdpSettings* clientSettings);
|
||||
|
||||
FREERDP_API proxyData* proxy_data_new(void);
|
||||
FREERDP_API void proxy_data_set_client_context(proxyData* pdata, pClientContext* context);
|
||||
FREERDP_API void proxy_data_set_server_context(proxyData* pdata, pServerContext* context);
|
||||
FREERDP_API void proxy_data_free(proxyData* pdata);
|
||||
|
||||
FREERDP_API BOOL proxy_data_shall_disconnect(proxyData* pdata);
|
||||
FREERDP_API void proxy_data_abort_connect(proxyData* pdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FREERDP_SERVER_PROXY_PFCONTEXT_H */
|
||||
|
@ -1745,13 +1745,14 @@ extern "C"
|
||||
FREERDP_API BOOL freerdp_settings_set_uint64(rdpSettings* settings, size_t id, UINT64 param);
|
||||
|
||||
FREERDP_API const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id);
|
||||
FREERDP_API char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id);
|
||||
FREERDP_API BOOL freerdp_settings_set_string_len(rdpSettings* settings, size_t id,
|
||||
const char* param, size_t len);
|
||||
FREERDP_API BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id,
|
||||
const char* param);
|
||||
|
||||
FREERDP_API const void* freerdp_settings_get_pointer(const rdpSettings* settings, size_t id);
|
||||
FREERDP_API void* freerdp_settings_get_pointer_writable(const rdpSettings* settings, size_t id);
|
||||
FREERDP_API void* freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id);
|
||||
FREERDP_API BOOL freerdp_settings_set_pointer(rdpSettings* settings, size_t id,
|
||||
const void* data);
|
||||
FREERDP_API BOOL freerdp_settings_set_pointer_len(rdpSettings* settings, size_t id,
|
||||
|
@ -2527,6 +2527,231 @@ const char* freerdp_settings_get_string(const rdpSettings* settings, size_t id)
|
||||
}
|
||||
}
|
||||
|
||||
char* freerdp_settings_get_string_writable(rdpSettings* settings, size_t id)
|
||||
{
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
switch (id)
|
||||
{
|
||||
case FreeRDP_AcceptedCert:
|
||||
return settings->AcceptedCert;
|
||||
|
||||
case FreeRDP_ActionScript:
|
||||
return settings->ActionScript;
|
||||
|
||||
case FreeRDP_AllowedTlsCiphers:
|
||||
return settings->AllowedTlsCiphers;
|
||||
|
||||
case FreeRDP_AlternateShell:
|
||||
return settings->AlternateShell;
|
||||
|
||||
case FreeRDP_AssistanceFile:
|
||||
return settings->AssistanceFile;
|
||||
|
||||
case FreeRDP_AuthenticationServiceClass:
|
||||
return settings->AuthenticationServiceClass;
|
||||
|
||||
case FreeRDP_CertificateAcceptedFingerprints:
|
||||
return settings->CertificateAcceptedFingerprints;
|
||||
|
||||
case FreeRDP_CertificateContent:
|
||||
return settings->CertificateContent;
|
||||
|
||||
case FreeRDP_CertificateFile:
|
||||
return settings->CertificateFile;
|
||||
|
||||
case FreeRDP_CertificateName:
|
||||
return settings->CertificateName;
|
||||
|
||||
case FreeRDP_ClientAddress:
|
||||
return settings->ClientAddress;
|
||||
|
||||
case FreeRDP_ClientDir:
|
||||
return settings->ClientDir;
|
||||
|
||||
case FreeRDP_ClientHostname:
|
||||
return settings->ClientHostname;
|
||||
|
||||
case FreeRDP_ClientProductId:
|
||||
return settings->ClientProductId;
|
||||
|
||||
case FreeRDP_ComputerName:
|
||||
return settings->ComputerName;
|
||||
|
||||
case FreeRDP_ConfigPath:
|
||||
return settings->ConfigPath;
|
||||
|
||||
case FreeRDP_ConnectionFile:
|
||||
return settings->ConnectionFile;
|
||||
|
||||
case FreeRDP_CurrentPath:
|
||||
return settings->CurrentPath;
|
||||
|
||||
case FreeRDP_Domain:
|
||||
return settings->Domain;
|
||||
|
||||
case FreeRDP_DrivesToRedirect:
|
||||
return settings->DrivesToRedirect;
|
||||
|
||||
case FreeRDP_DumpRemoteFxFile:
|
||||
return settings->DumpRemoteFxFile;
|
||||
|
||||
case FreeRDP_DynamicDSTTimeZoneKeyName:
|
||||
return settings->DynamicDSTTimeZoneKeyName;
|
||||
|
||||
case FreeRDP_GatewayAcceptedCert:
|
||||
return settings->GatewayAcceptedCert;
|
||||
|
||||
case FreeRDP_GatewayAccessToken:
|
||||
return settings->GatewayAccessToken;
|
||||
|
||||
case FreeRDP_GatewayDomain:
|
||||
return settings->GatewayDomain;
|
||||
|
||||
case FreeRDP_GatewayHostname:
|
||||
return settings->GatewayHostname;
|
||||
|
||||
case FreeRDP_GatewayPassword:
|
||||
return settings->GatewayPassword;
|
||||
|
||||
case FreeRDP_GatewayUsername:
|
||||
return settings->GatewayUsername;
|
||||
|
||||
case FreeRDP_HomePath:
|
||||
return settings->HomePath;
|
||||
|
||||
case FreeRDP_ImeFileName:
|
||||
return settings->ImeFileName;
|
||||
|
||||
case FreeRDP_KerberosKdc:
|
||||
return settings->KerberosKdc;
|
||||
|
||||
case FreeRDP_KerberosRealm:
|
||||
return settings->KerberosRealm;
|
||||
|
||||
case FreeRDP_KeyboardRemappingList:
|
||||
return settings->KeyboardRemappingList;
|
||||
|
||||
case FreeRDP_NtlmSamFile:
|
||||
return settings->NtlmSamFile;
|
||||
|
||||
case FreeRDP_Password:
|
||||
return settings->Password;
|
||||
|
||||
case FreeRDP_PasswordHash:
|
||||
return settings->PasswordHash;
|
||||
|
||||
case FreeRDP_PlayRemoteFxFile:
|
||||
return settings->PlayRemoteFxFile;
|
||||
|
||||
case FreeRDP_PreconnectionBlob:
|
||||
return settings->PreconnectionBlob;
|
||||
|
||||
case FreeRDP_PrivateKeyContent:
|
||||
return settings->PrivateKeyContent;
|
||||
|
||||
case FreeRDP_PrivateKeyFile:
|
||||
return settings->PrivateKeyFile;
|
||||
|
||||
case FreeRDP_ProxyHostname:
|
||||
return settings->ProxyHostname;
|
||||
|
||||
case FreeRDP_ProxyPassword:
|
||||
return settings->ProxyPassword;
|
||||
|
||||
case FreeRDP_ProxyUsername:
|
||||
return settings->ProxyUsername;
|
||||
|
||||
case FreeRDP_RDP2TCPArgs:
|
||||
return settings->RDP2TCPArgs;
|
||||
|
||||
case FreeRDP_RdpKeyContent:
|
||||
return settings->RdpKeyContent;
|
||||
|
||||
case FreeRDP_RdpKeyFile:
|
||||
return settings->RdpKeyFile;
|
||||
|
||||
case FreeRDP_RedirectionAcceptedCert:
|
||||
return settings->RedirectionAcceptedCert;
|
||||
|
||||
case FreeRDP_RedirectionDomain:
|
||||
return settings->RedirectionDomain;
|
||||
|
||||
case FreeRDP_RedirectionTargetFQDN:
|
||||
return settings->RedirectionTargetFQDN;
|
||||
|
||||
case FreeRDP_RedirectionTargetNetBiosName:
|
||||
return settings->RedirectionTargetNetBiosName;
|
||||
|
||||
case FreeRDP_RedirectionUsername:
|
||||
return settings->RedirectionUsername;
|
||||
|
||||
case FreeRDP_RemoteApplicationCmdLine:
|
||||
return settings->RemoteApplicationCmdLine;
|
||||
|
||||
case FreeRDP_RemoteApplicationFile:
|
||||
return settings->RemoteApplicationFile;
|
||||
|
||||
case FreeRDP_RemoteApplicationGuid:
|
||||
return settings->RemoteApplicationGuid;
|
||||
|
||||
case FreeRDP_RemoteApplicationIcon:
|
||||
return settings->RemoteApplicationIcon;
|
||||
|
||||
case FreeRDP_RemoteApplicationName:
|
||||
return settings->RemoteApplicationName;
|
||||
|
||||
case FreeRDP_RemoteApplicationProgram:
|
||||
return settings->RemoteApplicationProgram;
|
||||
|
||||
case FreeRDP_RemoteApplicationWorkingDir:
|
||||
return settings->RemoteApplicationWorkingDir;
|
||||
|
||||
case FreeRDP_RemoteAssistancePassStub:
|
||||
return settings->RemoteAssistancePassStub;
|
||||
|
||||
case FreeRDP_RemoteAssistancePassword:
|
||||
return settings->RemoteAssistancePassword;
|
||||
|
||||
case FreeRDP_RemoteAssistanceRCTicket:
|
||||
return settings->RemoteAssistanceRCTicket;
|
||||
|
||||
case FreeRDP_RemoteAssistanceSessionId:
|
||||
return settings->RemoteAssistanceSessionId;
|
||||
|
||||
case FreeRDP_ServerHostname:
|
||||
return settings->ServerHostname;
|
||||
|
||||
case FreeRDP_ShellWorkingDirectory:
|
||||
return settings->ShellWorkingDirectory;
|
||||
|
||||
case FreeRDP_SmartcardCertificate:
|
||||
return settings->SmartcardCertificate;
|
||||
|
||||
case FreeRDP_SmartcardPrivateKey:
|
||||
return settings->SmartcardPrivateKey;
|
||||
|
||||
case FreeRDP_TargetNetAddress:
|
||||
return settings->TargetNetAddress;
|
||||
|
||||
case FreeRDP_TransportDumpFile:
|
||||
return settings->TransportDumpFile;
|
||||
|
||||
case FreeRDP_Username:
|
||||
return settings->Username;
|
||||
|
||||
case FreeRDP_WindowTitle:
|
||||
return settings->WindowTitle;
|
||||
|
||||
case FreeRDP_WmClass:
|
||||
return settings->WmClass;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "[%s] Invalid key index %" PRIuz, __FUNCTION__, id);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
BOOL freerdp_settings_set_string_(rdpSettings* settings, size_t id, const char* val, size_t len,
|
||||
BOOL cleanup)
|
||||
{
|
||||
@ -2776,7 +3001,7 @@ BOOL freerdp_settings_set_string(rdpSettings* settings, size_t id, const char* v
|
||||
return freerdp_settings_set_string_(settings, id, val, len, TRUE);
|
||||
}
|
||||
|
||||
void* freerdp_settings_get_pointer_writable(const rdpSettings* settings, size_t id)
|
||||
void* freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id)
|
||||
{
|
||||
WINPR_ASSERT(settings);
|
||||
|
||||
|
@ -269,21 +269,7 @@ def write_getter_case(f, val):
|
||||
f.write('\t\tcase FreeRDP_' + val + ':\n')
|
||||
f.write('\t\t\treturn settings->' + val + ';\n\n')
|
||||
|
||||
def write_getter(f, entry_dict, entry_type, entry_name):
|
||||
isString = 'string' in entry_name
|
||||
isPointer = 'pointer' in entry_name
|
||||
values = get_values(entry_dict, entry_type)
|
||||
|
||||
if isPointer:
|
||||
f.write('void*')
|
||||
elif isString:
|
||||
f.write('const ' + entry_type)
|
||||
else:
|
||||
f.write(entry_type)
|
||||
if isPointer:
|
||||
f.write(' freerdp_settings_get_pointer_writable(const rdpSettings* settings, size_t id)\n')
|
||||
else:
|
||||
f.write(' freerdp_settings_get_' + entry_name.lower() + '(const rdpSettings* settings, size_t id)\n')
|
||||
def write_getter_body(f, values):
|
||||
f.write('{\n')
|
||||
f.write('\tWINPR_ASSERT(settings);\n\n')
|
||||
f.write('\tswitch (id)\n')
|
||||
@ -297,6 +283,28 @@ def write_getter(f, entry_dict, entry_type, entry_name):
|
||||
f.write('\t}\n')
|
||||
f.write('}\n\n')
|
||||
|
||||
def write_getter(f, entry_dict, entry_type, entry_name):
|
||||
isString = 'string' in entry_name
|
||||
isPointer = 'pointer' in entry_name
|
||||
values = get_values(entry_dict, entry_type)
|
||||
|
||||
if isPointer:
|
||||
f.write('void*')
|
||||
elif isString:
|
||||
f.write('const ' + entry_type)
|
||||
else:
|
||||
f.write(entry_type)
|
||||
|
||||
if isPointer:
|
||||
f.write(' freerdp_settings_get_pointer_writable(rdpSettings* settings, size_t id)\n')
|
||||
else:
|
||||
f.write(' freerdp_settings_get_' + entry_name.lower() + '(const rdpSettings* settings, size_t id)\n')
|
||||
write_getter_body(f, values)
|
||||
|
||||
if isString:
|
||||
f.write('char* freerdp_settings_get_' + entry_name.lower() + '_writable(rdpSettings* settings, size_t id)\n')
|
||||
write_getter_body(f, values)
|
||||
|
||||
def write_setter_case(f, val, isString, isPointer):
|
||||
f.write('\t\tcase FreeRDP_' + val + ':\n')
|
||||
if isPointer:
|
||||
|
@ -41,6 +41,7 @@ set(${MODULE_PREFIX}_SRCS
|
||||
|
||||
set(PROXY_APP_SRCS freerdp_proxy.c)
|
||||
|
||||
option(WITH_PROXY_EMULATE_SMARTCARD "Compile proxy smartcard emulation" OFF)
|
||||
add_subdirectory("channels")
|
||||
|
||||
# On windows create dll version information.
|
||||
@ -116,7 +117,3 @@ if (WITH_PROXY_MODULES)
|
||||
add_subdirectory("modules")
|
||||
endif()
|
||||
|
||||
option(WITH_PROXY_EMULATE_SMARTCARD "Compile proxy smartcard emulation" OFF)
|
||||
if (WITH_PROXY_EMULATE_SMARTCARD)
|
||||
add_definitions("-DWITH_PROXY_EMULATE_SMARTCARD")
|
||||
endif()
|
||||
|
@ -18,6 +18,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/assert.h>
|
||||
#include <winpr/string.h>
|
||||
#include <winpr/print.h>
|
||||
|
@ -121,6 +121,16 @@ static BOOL pf_context_revert_str_settings(rdpSettings* dst, const rdpSettings*
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void intercept_context_entry_free(void* obj)
|
||||
{
|
||||
InterceptContextMapEntry* entry = obj;
|
||||
if (!entry)
|
||||
return;
|
||||
if (!entry->free)
|
||||
return;
|
||||
entry->free(entry);
|
||||
}
|
||||
|
||||
BOOL pf_context_copy_settings(rdpSettings* dst, const rdpSettings* src)
|
||||
{
|
||||
BOOL rc = FALSE;
|
||||
|
Loading…
Reference in New Issue
Block a user