Skip to main content
The freerdp type (also spelled rdp_freerdp) is the top-level handle for an RDP client connection. It holds the pointer to the rdpContext and all callbacks that drive connection behaviour. In typical use you obtain a freerdp instance indirectly through freerdp_client_context_new()context->instance. When lower-level control is needed you can allocate one directly.

Instance Lifecycle

/* Allocate a bare instance */
freerdp* freerdp_new(void);

/* Free an instance (context must already be freed) */
void freerdp_free(freerdp* instance);
Always call freerdp_context_free() (or freerdp_client_context_free()) before calling freerdp_free(). Freeing the instance before the context is undefined behaviour.

Direct allocation

freerdp* instance = freerdp_new();
if (!instance)
    return -1;

/* Set custom context size before allocating the context */
instance->ContextSize = sizeof(MyContext);
instance->ContextNew  = my_context_new_cb;
instance->ContextFree = my_context_free_cb;

if (!freerdp_context_new(instance))
    goto fail;

/* ... connect, run, disconnect ... */

freerdp_context_free(instance);
fail:
freerdp_free(instance);

Key Fields

context
rdpContext*
Pointer to the associated context. Allocated by freerdp_context_new(). Access settings, channels, GDI, etc. through this field.
ContextSize
size_t
The number of bytes to allocate for the context. Defaults to sizeof(rdpContext). Set to sizeof(MyContext) before calling freerdp_context_new() to use an extended context struct.
ConnectionCallbackState
UINT
Internal field tracking whether PreConnect / PostConnect have been called. Do not modify directly.

Connection Callbacks

Set these on the freerdp instance — typically inside your ClientNew (i.e., pRdpClientNew) implementation — before calling freerdp_connect().

Authentication Callbacks

Certificate Verification Callbacks

VERIFY_CERT_FLAG_* Constants

ConstantValueMeaning
VERIFY_CERT_FLAG_NONE0x00No special flags
VERIFY_CERT_FLAG_LEGACY0x02Legacy certificate format
VERIFY_CERT_FLAG_REDIRECT0x10Certificate presented after a redirect
VERIFY_CERT_FLAG_GATEWAY0x20Certificate belongs to an RD Gateway
VERIFY_CERT_FLAG_CHANGED0x40Certificate differs from stored copy
VERIFY_CERT_FLAG_MISMATCH0x80Hostname mismatch detected
VERIFY_CERT_FLAG_MATCH_LEGACY_SHA10x100Matches a stored legacy SHA-1 fingerprint
VERIFY_CERT_FLAG_FP_IS_PEM0x200fingerprint is a PEM-encoded certificate

Other Callbacks

Context Allocation Callbacks

These are set directly on the freerdp struct (not via RDP_CLIENT_ENTRY_POINTS) when using the lower-level freerdp_context_new() path:

Minimal Example

#include <freerdp/freerdp.h>
#include <freerdp/client.h>
#include <freerdp/client/cmdline.h>

static BOOL my_pre_connect(freerdp* instance)
{
    rdpSettings* s = instance->context->settings;
    /* Prefer PEM in certificate callbacks */
    freerdp_settings_set_bool(s, FreeRDP_CertificateCallbackPreferPEM, TRUE);
    return TRUE;
}

static BOOL my_post_connect(freerdp* instance)
{
    /* Initialize GDI surface: XRGB32 pixel format */
    if (!gdi_init(instance, PIXEL_FORMAT_XRGB32))
        return FALSE;
    instance->context->update->BeginPaint = my_begin_paint;
    instance->context->update->EndPaint   = my_end_paint;
    return TRUE;
}

static void my_post_disconnect(freerdp* instance)
{
    gdi_free(instance);
}

static DWORD my_verify_cert(freerdp* instance, const char* host,
                             UINT16 port, const char* common_name,
                             const char* subject, const char* issuer,
                             const char* fingerprint, DWORD flags)
{
    /* Accept without prompting — DO NOT do this in production */
    return 2;  /* accept for this session only */
}

static BOOL my_client_new(freerdp* instance, rdpContext* context)
{
    instance->PreConnect             = my_pre_connect;
    instance->PostConnect            = my_post_connect;
    instance->PostDisconnect         = my_post_disconnect;
    instance->VerifyCertificateEx    = my_verify_cert;
    return TRUE;
}

static void my_client_free(freerdp* instance, rdpContext* context)
{
    (void)instance; (void)context;
}

static int my_client_start(rdpContext* c) { return 0; }
static int my_client_stop(rdpContext* c)  { return 0; }

int main(int argc, char* argv[])
{
    RDP_CLIENT_ENTRY_POINTS ep = { 0 };
    ep.Version     = RDP_CLIENT_INTERFACE_VERSION;
    ep.Size        = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
    ep.ContextSize = sizeof(rdpClientContext);
    ep.ClientNew   = my_client_new;
    ep.ClientFree  = my_client_free;
    ep.ClientStart = my_client_start;
    ep.ClientStop  = my_client_stop;

    rdpContext* ctx = freerdp_client_context_new(&ep);
    if (!ctx)
        return 1;

    freerdp_client_settings_parse_command_line(ctx->settings, argc, argv, FALSE);

    /* connect, run event loop — see Connection API */

    freerdp_client_context_free(ctx);
    return 0;
}