### pf_server_post_connect callback Source: https://pub.freerdp.com/api/pf__server_8c_source.html Handles post-connection setup, including channel initialization, client context creation, and starting the client thread. ```c WINPR_ATTR_NODISCARD static BOOL pf_server_post_connect(freerdp_peer* peer) { pServerContext* ps = nullptr; pClientContext* pc = nullptr; rdpSettings* client_settings = nullptr; proxyData* pdata = nullptr; rdpSettings* frontSettings = nullptr; WINPR_ASSERT(peer); ps = (pServerContext*)peer->context; WINPR_ASSERT(ps); frontSettings = peer->context->settings; WINPR_ASSERT(frontSettings); pdata = ps->pdata; WINPR_ASSERT(pdata); const char* ClientHostname = freerdp_settings_get_string(frontSettings, FreeRDP_ClientHostname); PROXY_LOG_INFO(TAG, ps, "Accepted client: %s", ClientHostname); if (!pf_server_setup_channels(peer)) { PROXY_LOG_ERR(TAG, ps, "error setting up channels"); return FALSE; } pc = pf_context_create_client_context(frontSettings); if (pc == nullptr) { PROXY_LOG_ERR(TAG, ps, "failed to create client context!"); return FALSE; } client_settings = pc->cctx.context.settings; /* keep both sides of the connection in pdata */ proxy_data_set_client_context(pdata, pc); if (!pf_server_get_target_info(peer->context, client_settings, pdata->config)) { PROXY_LOG_INFO(TAG, ps, "pf_server_get_target_info failed!"); return FALSE; } PROXY_LOG_INFO(TAG, ps, "remote target is %s:%" PRIu32 "", freerdp_settings_get_string(client_settings, FreeRDP_ServerHostname), freerdp_settings_get_uint32(client_settings, FreeRDP_ServerPort)); if (!pf_modules_run_hook(pdata->module, HOOK_TYPE_SERVER_POST_CONNECT, pdata, peer)) return FALSE; /* Start a proxy's client in it's own thread */ pdata->client_thread = CreateThread(nullptr, 0, pf_client_start, pc, 0, nullptr); if (!pdata->client_thread) { PROXY_LOG_ERR(TAG, ps, "failed to create client thread"); return FALSE; } return TRUE; } ``` -------------------------------- ### shadow_subsystem_start Source: https://pub.freerdp.com/api/shadow__subsystem_8c_source.html Starts the shadow subsystem by invoking the entry point start function. ```c int shadow_subsystem_start(rdpShadowSubsystem* subsystem) { int status = 0; if (!subsystem || !subsystem->ep.Start) return -1; status = subsystem->ep.Start(subsystem); return status; } ``` -------------------------------- ### Initialize and Run Sample Server Process Source: https://pub.freerdp.com/api/TestConnect_8c_source.html This snippet demonstrates setting up a local server process, configuring command-line arguments, and executing the instance for testing purposes. ```c char* clientArgs[] = { "test", "/v:127.0.0.1:XXXXX", "/cert:ignore", "/rfx", nullptr }; char* commandLine = nullptr; size_t commandLineLen = 0; int argc = 4; char* path = nullptr; char* wpath = nullptr; char* exe = GetCombinedPath(TESTING_OUTPUT_DIRECTORY, "server"); (void)_snprintf(arg1, 18, "/v:127.0.0.1:%d", port); clientArgs[1] = arg1; if (!exe) goto fail; path = GetCombinedPath(exe, "Sample"); wpath = GetCombinedPath(exe, "Sample"); free(exe); exe = nullptr; if (!path || !wpath) goto fail; exe = GetCombinedPath(path, "sfreerdp-server" CMAKE_EXECUTABLE_SUFFIX); if (!exe) goto fail; printf("Sample Server: %s\n", exe); printf("Workspace: %s\n", wpath); if (!winpr_PathFileExists(exe)) goto fail; if (!prepare_certificates(wpath)) goto fail; // Start sample server locally. commandLineLen = strlen(exe) + strlen("--port=XXXXX") + 1; commandLine = malloc(commandLineLen); if (!commandLine) goto fail; (void)_snprintf(commandLine, commandLineLen, "%s --port=%d", exe, port); si.cb = sizeof(si); if (!CreateProcessA(nullptr, commandLine, nullptr, nullptr, FALSE, 0, nullptr, wpath, &si, &process)) goto fail; Sleep(5000); /* let the server start */ r = runInstance(argc, clientArgs, nullptr, 10000); if (!TerminateProcess(process.hProcess, 0)) goto fail; (void)WaitForSingleObject(process.hProcess, INFINITE); (void)CloseHandle(process.hProcess); (void)CloseHandle(process.hThread); printf("%s: returned %d!\n", __func__, r); rc = r; if (rc == 0) printf("%s: Success!\n", __func__); fail: free(exe); free(path); free(wpath); free(commandLine); return rc; ``` -------------------------------- ### Synthetic file module setup and make_synthetic_file start Source: https://pub.freerdp.com/api/synthetic__file_8c_source.html Initialization and setup for the synthetic file module: includes required WinPR headers, defines the module tag, declares MIME type constants, defines the synthetic_file structure, and starts the make_synthetic_file function that validates input, checks the local file with FindFirstFileW, and allocates the structure. ```c #include #include WINPR_PRAGMA_DIAG_PUSH WINPR_PRAGMA_DIAG_IGNORED_RESERVED_ID_MACRO WINPR_PRAGMA_DIAG_IGNORED_UNUSED_MACRO #define _FILE_OFFSET_BITS 64 // NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp) WINPR_PRAGMA_DIAG_POP #include #include #include #include #include #include #include #include #include #include #include #include "clipboard.h" #include "synthetic_file.h" #include "../log.h" #define TAG WINPR_TAG("clipboard.synthetic.file") ``` ```c static const char* mime_uri_list = "text/uri-list"; static const char* mime_FileGroupDescriptorW = "FileGroupDescriptorW"; static const char* mime_gnome_copied_files = "x-special/gnome-copied-files"; static const char* mime_mate_copied_files = "x-special/mate-copied-files"; ``` ```c struct synthetic_file { WCHAR* local_name; WCHAR* remote_name; HANDLE fd; INT64 offset; DWORD dwFileAttributes; FILETIME ftCreationTime; FILETIME ftLastAccessTime; FILETIME ftLastWriteTime; DWORD nFileSizeHigh; DWORD nFileSizeLow; }; ``` ```c void free_synthetic_file(struct synthetic_file* file); ``` ```c static struct synthetic_file* make_synthetic_file(const WCHAR* local_name, const WCHAR* remote_name) { struct synthetic_file* file = nullptr; WIN32_FIND_DATAW fd = WINPR_C_ARRAY_INIT; HANDLE hFind = nullptr; WINPR_ASSERT(local_name); WINPR_ASSERT(remote_name); hFind = FindFirstFileW(local_name, &fd); if (INVALID_HANDLE_VALUE == hFind) { WLog_ERR(TAG, "FindFirstFile failed (%" PRIu32 ")", GetLastError()); return nullptr; } FindClose(hFind); file = calloc(1, sizeof(*file)); if (!file) return nullptr; file->fd = INVALID_HANDLE_VALUE; file->offset = 0; file->local_name = _wcsdup(local_name); if (!file->local_name) goto fail; file->remote_name = _wcsdup(remote_name); if (!file->remote_name) goto fail; { ``` -------------------------------- ### Implement main entry point Source: https://pub.freerdp.com/api/TestFuzzServerSeedGen_8c_source.html Initializes the application, handles signals, and parses command-line arguments. ```c int main(int argc, char** argv) { (void)signal(SIGPIPE, SIG_IGN); const char* outdir = argc > 1 ? argv[1] : "."; int do_input = 1; if (argc > 2) { errno = 0; const unsigned long val = strtoul(argv[2], nullptr, 0); if ((errno != 0) || (val > INT_MAX)) return -1; ``` -------------------------------- ### Get GUID unit ID from libusb_device with get_guid_unit_id_from_device Source: https://pub.freerdp.com/api/uvc__h264_8c_source.html Retrieves the unit ID for a given extension unit GUID from a libusb_device by iterating over its configurations. Returns 0 if the device descriptor cannot be read, if no configuration matches, or if the GUID is not found. Logs an error when the device or configuration descriptor cannot be obtained. ```c static uint8_t get_guid_unit_id_from_device(libusb_device* device, const uint8_t* guid) { struct libusb_device_descriptor ddesc = WINPR_C_ARRAY_INIT; if (libusb_get_device_descriptor(device, &ddesc) != 0) { WLog_ERR(TAG, "Couldn't get device descriptor"); return 0; } for (uint8_t i = 0; i < ddesc.bNumConfigurations; ++i) { uint8_t rc = 0; struct libusb_config_descriptor* config = nullptr; if (libusb_get_config_descriptor(device, i, &config) != 0) { WLog_ERR(TAG, "Couldn't get config descriptor for " "configuration %" PRIu8, i); } else rc = get_guid_unit_id_from_config_descriptor(config, guid, &ddesc); libusb_free_config_descriptor(config); if (rc != 0) return rc; } /* no match found */ return 0; } ``` -------------------------------- ### Display Command Line Help Source: https://pub.freerdp.com/api/client_2common_2cmdline_8c_source.html Prints usage examples for various redirection features and gateway proxy configuration. ```c printf("TCP redirection: /rdp2tcp:/usr/bin/rdp2tcp\n"); printf("\n"); printf("Audio Output Redirection: /sound:sys:oss,dev:1,format:1\n"); printf("Audio Output Redirection: /sound:sys:alsa\n"); printf("Audio Input Redirection: /microphone:sys:oss,dev:1,format:1\n"); printf("Audio Input Redirection: /microphone:sys:alsa\n"); printf("\n"); printf("Multimedia Redirection: /video\n"); #ifdef CHANNEL_URBDRC_CLIENT printf("USB Device Redirection: /usb:id:054c:0268#4669:6e6b,addr:04:0c\n"); #endif printf("\n"); printf("For Gateways, the https_proxy environment variable is respected:\n"); #ifdef _WIN32 printf(" set HTTPS_PROXY=http://proxy.contoso.com:3128/\n"); #else printf(" export https_proxy=http://proxy.contoso.com:3128/\n"); #endif printf(" %s /gateway:g:rdp.contoso.com ...\n", name); printf("\n"); printf("More documentation is coming, in the meantime consult source files\n"); printf("\n"); return TRUE; ``` -------------------------------- ### Get bitmap codec GUID name (rdp_get_bitmap_codec_guid_name) Source: https://pub.freerdp.com/api/capabilities_8c_source.html Returns a string name for a known bitmap codec GUID. Recognizes REMOTEFX, NSCODEC, IGNORE, IMAGE_REMOTEFX, and (when WITH_JPEG is defined) JPEG; otherwise returns "CODEC_GUID_UNKNOWN". ```c static char* rdp_get_bitmap_codec_guid_name(const GUID* guid) { WINPR_ASSERT(guid); if (sUuidEqual(guid, &CODEC_GUID_REMOTEFX)) return "CODEC_GUID_REMOTEFX"; else if (sUuidEqual(guid, &CODEC_GUID_NSCODEC)) return "CODEC_GUID_NSCODEC"; else if (sUuidEqual(guid, &CODEC_GUID_IGNORE)) return "CODEC_GUID_IGNORE"; else if (sUuidEqual(guid, &CODEC_GUID_IMAGE_REMOTEFX)) return "CODEC_GUID_IMAGE_REMOTEFX"; #if defined(WITH_JPEG) else if (sUuidEqual(guid, &CODEC_GUID_JPEG)) return "CODEC_GUID_JPEG"; #endif return "CODEC_GUID_UNKNOWN"; } ``` -------------------------------- ### Initialize Client Capabilities Source: https://pub.freerdp.com/api/Clipboard_8m_source.html Sets up the general capability set and sends client capabilities to the server. ```c capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET *)&(generalCapabilitySet); generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = CB_CAPS_VERSION_2; generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES; cliprdr->ClientCapabilities(cliprdr, &capabilities); return 1; } ``` -------------------------------- ### Get certificate validity date Source: https://pub.freerdp.com/api/certificate_8c_source.html Returns the certificate validity date as a string. The startDate parameter selects the start date when TRUE and the end date when FALSE. ```c char* freerdp_certificate_get_validity(const rdpCertificate* cert, BOOL startDate) { WINPR_ASSERT(cert); return x509_utils_get_date(cert->x509, startDate); } ``` -------------------------------- ### Post-connect peer setup Source: https://pub.freerdp.com/api/mf__peer_8c_source.html Post-connect setup: sets scale to 1, forces desktop width/height to the server screen size and color depth to 32, then triggers a DesktopResize update. Returns FALSE if any setting fails. The mouse_down_left flag is reset to FALSE. ```c WINPR_ATTR_NODISCARD static BOOL mf_peer_post_connect(freerdp_peer* client) { mfInfo* mfi = mf_info_get_instance(); WINPR_ASSERT(client); mfPeerContext* context = (mfPeerContext*)client->context; WINPR_ASSERT(context); rdpSettings* settings = client->context->settings; WINPR_ASSERT(settings); mfi->scale = 1; // mfi->servscreen_width = 2880 / mfi->scale; // mfi->servscreen_height = 1800 / mfi->scale; UINT32 bitsPerPixel = 32; if ((freerdp_settings_get_uint32(settings, FreeRDP_DesktopWidth) != mfi->servscreen_width) || (freerdp_settings_get_uint32(settings, FreeRDP_DesktopHeight) != mfi->servscreen_height)) { } if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, mfi->servscreen_width)) return FALSE; if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight, mfi->servscreen_height)) return FALSE; if (!freerdp_settings_set_uint32(settings, FreeRDP_ColorDepth, bitsPerPixel)) return FALSE; WINPR_ASSERT(client->context->update); WINPR_ASSERT(client->context->update->DesktopResize); client->context->update->DesktopResize(client->context); mfi->mouse_down_left = FALSE; } ``` -------------------------------- ### xf_Pointer_GetCursorForCurrentScale: initial checks and setup Source: https://pub.freerdp.com/api/xf__graphics_8c_source.html Starts the implementation of xf_Pointer_GetCursorForCurrentScale, which is compiled only when WITH_XCURSOR and WITH_XRENDER are defined. It initializes an XcursorImage and checks that the context, pointer, and GDI are valid, returning FALSE otherwise. ```c static BOOL xf_Pointer_GetCursorForCurrentScale(rdpContext* context, rdpPointer* pointer, Cursor* cursor) { #if defined(WITH_XCURSOR) && defined(WITH_XRENDER) xfContext* xfc = (xfContext*)context; xfPointer* xpointer = (xfPointer*)pointer; XcursorImage ci = WINPR_C_ARRAY_INIT; int cursorIndex = -1; if (!context || !pointer || !context->gdi) return FALSE; ``` -------------------------------- ### Start Audio Server Context Source: https://pub.freerdp.com/api/server_2rdpsnd__main_8c_source.html Initializes the audio server, opens the virtual channel (dynamic or static), and sets up the necessary synchronization primitives and threads. ```c 908static UINT rdpsnd_server_start(RdpsndServerContext* context) 909{ 910 void* buffer = nullptr; 911 DWORD bytesReturned = 0; 912 RdpsndServerPrivate* priv = nullptr; 913 UINT error = ERROR_INTERNAL_ERROR; 914 PULONG pSessionId = nullptr; 915 916 WINPR_ASSERT(context); 917 WINPR_ASSERT(context->priv); 918 919 priv = context->priv; 920 priv->SessionId = WTS_CURRENT_SESSION; 921 922 if (context->use_dynamic_virtual_channel) 923 { 924 UINT32 channelId = 0; 925 BOOL status = TRUE; 926 927 if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, 928 (LPSTR*)&pSessionId, &bytesReturned)) 929 { 930 priv->SessionId = (DWORD)*pSessionId; 931 WTSFreeMemory(pSessionId); 932 priv->ChannelHandle = WTSVirtualChannelOpenEx(priv->SessionId, RDPSND_DVC_CHANNEL_NAME, 933 WTS_CHANNEL_OPTION_DYNAMIC); 934 if (!priv->ChannelHandle) 935 { 936 WLog_ERR(TAG, "Open audio dynamic virtual channel (%s) failed!", 937 RDPSND_DVC_CHANNEL_NAME); 938 return ERROR_INTERNAL_ERROR; 939 } 940 941 channelId = WTSChannelGetIdByHandle(priv->ChannelHandle); 942 943 IFCALLRET(context->ChannelIdAssigned, status, context, channelId); 944 if (!status) 945 { 946 WLog_ERR(TAG, "context->ChannelIdAssigned failed!"); 947 goto out_close; 948 } 949 } 950 else 951 { 952 WLog_ERR(TAG, "WTSQuerySessionInformationA failed!"); 953 return ERROR_INTERNAL_ERROR; 954 } 955 } 956 else 957 { 958 priv->ChannelHandle = 959 WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RDPSND_CHANNEL_NAME); 960 if (!priv->ChannelHandle) 961 { 962 WLog_ERR(TAG, "Open audio static virtual channel (rdpsnd) failed!"); 963 return ERROR_INTERNAL_ERROR; 964 } 965 } 966 967 if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, 968 &bytesReturned) || 969 (bytesReturned != sizeof(HANDLE))) 970 { 971 WLog_ERR(TAG, 972 "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned " 973 "size(% ``` ```c PRIu32 ")", 974 bytesReturned); 975 976 if (buffer) 977 WTSFreeMemory(buffer); 978 979 goto out_close; 980 } 981 982 priv->channelEvent = *(HANDLE*)buffer; 983 WTSFreeMemory(buffer); 984 priv->rdpsnd_pdu = Stream_New(nullptr, 4096); 985 986 if (!priv->rdpsnd_pdu) 987 { 988 WLog_ERR(TAG, "Stream_New failed!"); 989 error = CHANNEL_RC_NO_MEMORY; 990 goto out_close; 991 } 992 993 if (!InitializeCriticalSectionEx(&context->priv->lock, 0, 0)) 994 { 995 WLog_ERR(TAG, "InitializeCriticalSectionEx failed!"); 996 goto out_pdu; 997 } 998 999 if ((error = rdpsnd_server_send_formats(context))) 1000 { 1001 WLog_ERR(TAG, "rdpsnd_server_send_formats failed with error %" PRIu32 "", error); 1002 goto out_lock; 1003 } 1004 1005 if (priv->ownThread) 1006 { 1007 context->priv->StopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); 1008 1009 if (!context->priv->StopEvent) 1010 { 1011 WLog_ERR(TAG, "CreateEvent failed!"); 1012 goto out_lock; 1013 } 1014 1015 context->priv->Thread = 1016 CreateThread(nullptr, 0, rdpsnd_server_thread, (void*)context, 0, nullptr); 1017 1018 if (!context->priv->Thread) 1019 { 1020 WLog_ERR(TAG, "CreateThread failed!"); 1021 goto out_stopEvent; 1022 } 1023 } 1024 1025 return CHANNEL_RC_OK; 1026out_stopEvent: 1027 (void)CloseHandle(context->priv->StopEvent); 1028 context->priv->StopEvent = nullptr; 1029out_lock: 1030 DeleteCriticalSection(&context->priv->lock); 1031out_pdu: 1032 Stream_Free(context->priv->rdpsnd_pdu, TRUE); 1033 context->priv->rdpsnd_pdu = nullptr; 1034out_close: 1035 (void)WTSVirtualChannelClose(context->priv->ChannelHandle); 1036 context->priv->ChannelHandle = nullptr; 1037 return error; 1038} ``` -------------------------------- ### init_app_details callback function Source: https://pub.freerdp.com/api/utils_2helpers_8c_source.html Initializes vendor and product strings from FREERDP_VENDOR_STRING and FREERDP_PRODUCT_STRING. Sets version based on WITH_RESOURCE_VERSIONING and calls updateDetailsString. ```c static BOOL CALLBACK init_app_details(WINPR_ATTR_UNUSED PINIT_ONCE once, WINPR_ATTR_UNUSED PVOID param, WINPR_ATTR_UNUSED PVOID* context) { const size_t vlen = sizeof(FREERDP_VENDOR_STRING); const size_t plen = sizeof(FREERDP_PRODUCT_STRING); const char* rvlen = strncpy(s_freerdp_vendor_string, FREERDP_VENDOR_STRING, vlen); const char* rplen = strncpy(s_freerdp_product_string, FREERDP_PRODUCT_STRING, plen); if (!rvlen || !rplen) return FALSE; #if defined(WITH_RESOURCE_VERSIONING) s_freerdp_version = FREERDP_VERSION_MAJOR; #else s_freerdp_version = -1; #endif updateDetailsString(); return TRUE; } ``` -------------------------------- ### Search for camera device by devpath and get GUID unit ID Source: https://pub.freerdp.com/api/uvc__h264_8c_source.html Initializes libusb, enumerates devices, and searches for a device whose devpath matches the given camera devpath. On a match, it attempts to retrieve the GUID unit ID and returns it; otherwise returns 0. The loop continues on non-matching devpaths to allow for another match. ```c if (0 != libusb_init(&usb_ctx)) { WLog_ERR(TAG, "Unable to initialize libusb"); return 0; } ssize_t cnt = libusb_get_device_list(usb_ctx, &device_list); for (ssize_t i = 0; i < cnt; i++) { char path[MAX_DEVPATH_STR_SIZE] = WINPR_C_ARRAY_INIT; libusb_device* device = device_list[i]; if (!device || !get_devpath_from_device(device, path, sizeof(path))) continue; if (0 != strcmp(cam_devpath, path)) continue; /* found device with matching devpath, try to get guid unit id */ unit_id = get_guid_unit_id_from_device(device, guid); if (unit_id > 0) break; /* got it */ /* there's chance for another devpath match - continue */ } libusb_free_device_list(device_list, TRUE); libusb_exit(usb_ctx); return unit_id; ``` -------------------------------- ### Start the proxy server with pf_server_start Source: https://pub.freerdp.com/api/pf__server_8c_source.html Initializes the proxy server listener using the provided configuration. ```c BOOL pf_server_start(proxyServer* server) { WSADATA wsaData; WINPR_ASSERT(server); if (!WTSRegisterWtsApiFunctionTable(FreeRDP_InitWtsApi())) goto error; if (!winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT)) goto error; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) goto error; WINPR_ASSERT(server->config); WINPR_ASSERT(server->listener); WINPR_ASSERT(server->listener->Open); if (!server->listener->Open(server->listener, server->config->Host, server->config->Port)) { switch (errno) { case EADDRINUSE: WLog_ERR(TAG, "failed to start listener: address already in use!"); break; case EACCES: WLog_ERR(TAG, "failed to start listener: insufficient permissions!"); break; default: WLog_ERR(TAG, "failed to start listener: errno=%d", errno); break; } goto error; } return TRUE; error: WSACleanup(); return FALSE; } ``` -------------------------------- ### mf_peer_post_connect: initialize mouse state and audio channels Source: https://pub.freerdp.com/api/mf__peer_8c_source.html Initializes mouse state and conditionally starts audio output (rdpsnd) and input (audin) channels based on compile-time flags. Returns TRUE after setup. ```c 304 mfi->mouse_down_right = FALSE; 305 mfi->mouse_down_other = FALSE; 306#ifdef CHANNEL_RDPSND_SERVER 307 308 if (WTSVirtualChannelManagerIsChannelJoined(context->vcm, "rdpsnd")) 309 { 310 mf_peer_rdpsnd_init(context); /* Audio Output */ 311 } 312 313#endif 314 /* Dynamic Virtual Channels */ 315#ifdef CHANNEL_AUDIN_SERVER 316 mf_peer_audin_init(context); /* Audio Input */ 317#endif 318 return TRUE; 319} ``` -------------------------------- ### Get timezone from TZ environment variable Source: https://pub.freerdp.com/api/winpr_2libwinpr_2timezone_2timezone_8c_source.html Reads the TZ environment variable using GetEnvironmentVariableA. If the value starts with a colon, the colon is removed as documented in tzset(3). Returns a heap-allocated string or null on failure. ```c static char* winpr_time_zone_from_env(void) { LPCSTR tz = "TZ"; char* tzid = nullptr; DWORD nSize = GetEnvironmentVariableA(tz, nullptr, 0); if (nSize > 0) { tzid = (char*)calloc(nSize, sizeof(char)); if (!tzid) goto fail; if (!GetEnvironmentVariableA(tz, tzid, nSize)) goto fail; else if (tzid[0] == ':') { /* Remove leading colon, see tzset(3) */ memmove(tzid, tzid + 1, nSize - sizeof(char)); } } return tzid; fail: free(tzid); return nullptr; } ``` -------------------------------- ### pf_client_post_connect: initialize client after connection Source: https://pub.freerdp.com/api/pf__client_8c_source.html Post-connect setup: runs hooks, initializes GDI, registers update callbacks, hooks channel data reception, sets heartbeat handler, marks connected, flushes queued channel data, and triggers server reactivation. Requires valid instance and proxy data. ```c WINPR_ATTR_NODISCARD static BOOL pf_client_post_connect(freerdp* instance) { WINPR_ASSERT(instance); rdpContext* context = instance->context; WINPR_ASSERT(context); rdpUpdate* update = context->update; WINPR_ASSERT(update); pClientContext* pc = (pClientContext*)context; WINPR_ASSERT(pc); WINPR_ASSERT(pc->pdata); pServerContext* ps = proxy_data_get_server_context(pc->pdata); WINPR_ASSERT(ps); if (!pf_modules_run_hook(pc->pdata->module, HOOK_TYPE_CLIENT_POST_CONNECT, pc->pdata, pc)) return FALSE; if (!gdi_init(instance, PIXEL_FORMAT_BGRA32)) return FALSE; WINPR_ASSERT(freerdp_settings_get_bool(context->settings, FreeRDP_SoftwareGdi)); pf_client_register_update_callbacks(update); /* virtual channels receive data hook */ pc->client_receive_channel_data_original = instance->ReceiveChannelData; instance->ReceiveChannelData = pf_client_receive_channel_data_hook; instance->heartbeat->ServerHeartbeat = pf_client_on_server_heartbeat; pc->connected = TRUE; /* Send cached channel data */ if (!sendQueuedChannelData(pc)) return FALSE; /* * after the connection fully established and settings were negotiated with target server, * send a reactivation sequence to the client with the negotiated settings. This way, * settings are synchorinized between proxy's peer and and remote target. */ return proxy_server_reactivate(&ps->context, context); } ``` -------------------------------- ### Print Configuration File Help Source: https://pub.freerdp.com/api/sdl__prefs_8cpp_source.html Prints the help documentation for global and user configuration files to standard output, detailing supported options and their defaults. ```cpp void SdlPref::print_config_file_help(int version) { #if defined(WITH_WINPR_JSON) const std::string url = "https://wiki.libsdl.org/SDL" + std::to_string(version); std::cout << "GLOBAL CONFIGURATION FILE" << std::endl; std::cout << std::endl; std::cout << " The SDL client supports some system defined configuration options." << std::endl; std::cout << " Settings are stored in JSON format" << std::endl; std::cout << " The location is a system configuration file. Location for current machine is " << SdlPref::instance()->get_pref_file(true) << std::endl; std::cout << std::endl; std::cout << " The following configuration options are supported:" << std::endl; std::cout << std::endl; std::cout << " isUserConfigEnabled" << std::endl; std::cout << " Allows to enable/disable user specific configuration files." << std::endl; std::cout << " Default enabled" << std::endl; std::cout << std::endl; std::cout << " All options of the following user configuration file are also supported here." << std::endl; std::cout << std::endl; std::cout << "CONFIGURATION FILE" << std::endl; std::cout << std::endl; std::cout << " The SDL client supports some user defined configuration options." << std::endl; std::cout << " Settings are stored in JSON format" << std::endl; std::cout << " The location is a per user file. Location for current user is " << SdlPref::instance()->get_pref_file() << std::endl; std::cout << " The XDG_CONFIG_HOME environment variable can be used to override the base directory." << std::endl; std::cout << std::endl; std::cout << " The following configuration options are supported:" << std::endl; std::cout << std::endl; std::cout << " SDL_KeyModMask" << std::endl; std::cout << " Defines the key combination required for SDL client shortcuts." << std::endl; std::cout << " Default KMOD_RSHIFT" << std::endl; std::cout << " An array of SDL_Keymod strings as defined at " "" << url << "/SDL_Keymod" << std::endl; std::cout << std::endl; std::cout << " SDL_Fullscreen" << std::endl; std::cout << " Toggles client fullscreen state." << std::endl; std::cout << " Default SDL_SCANCODE_RETURN." << std::endl; std::cout << " A string as " "defined at " << url << "/SDLScancodeLookup" << std::endl; std::cout << std::endl; std::cout << " SDL_Minimize" << std::endl; std::cout << " Minimizes client windows." << std::endl; std::cout << " Default SDL_SCANCODE_M." << std::endl; std::cout << " A string as " "defined at " << url << "/SDLScancodeLookup" << std::endl; std::cout << std::endl; std::cout << " SDL_Resizeable" << std::endl; std::cout << " Toggles local window resizeable state." << std::endl; std::cout << " Default SDL_SCANCODE_R." << std::endl; std::cout << " A string as " "defined at " << url << "/SDLScancodeLookup" << std::endl; std::cout << std::endl; std::cout << " SDL_Grab" << std::endl; std::cout << " Toggles keyboard and mouse grab state." << std::endl; std::cout << " Default SDL_SCANCODE_G." << std::endl; std::cout << " A string as " "defined at " << url << "/SDLScancodeLookup" << std::endl; std::cout << std::endl; std::cout << " SDL_Disconnect" << std::endl; std::cout << " Disconnects from the RDP session." << std::endl; std::cout << " Default SDL_SCANCODE_D." << std::endl; std::cout << " A string as defined at " << url << "/SDLScancodeLookup" << std::endl; #endif } ``` -------------------------------- ### Get NTLM AV_PAIR list length Source: https://pub.freerdp.com/api/ntlm__av__pairs_8c_source.html Computes the total length of an AV_PAIR list by locating the terminating MsvAvEOL pair and returning its offset plus the header size. Returns 0 if the list is invalid or the pointer is before the start. ```c ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList) { size_t cbAvPair = 0; NTLM_AV_PAIR* pAvPair = nullptr; pAvPair = ntlm_av_pair_get(pAvPairList, cbAvPairList, MsvAvEOL, &cbAvPair); if (!pAvPair) return 0; if (pAvPair < pAvPairList) return 0; const size_t size = WINPR_ASSERTING_INT_CAST(size_t, ((PBYTE)pAvPair - (PBYTE)pAvPairList)) + sizeof(NTLM_AV_PAIR); WINPR_ASSERT(size <= UINT32_MAX); WINPR_ASSERT(size >= 0); return (ULONG)size; } ``` -------------------------------- ### wf_is_x509_certificate_trusted: certificate chain setup Source: https://pub.freerdp.com/api/wf__client_8c_source.html Starts certificate trust verification for an X.509 certificate using Windows CryptoAPI. Initializes chain parameters and allocates a buffer for the DER-encoded public key, logging an error and jumping to CleanUp on allocation failure. ```c static DWORD wf_is_x509_certificate_trusted(const char* common_name, const char* subject, const char* issuer, const char* fingerprint) { HRESULT hr = CRYPT_E_NOT_FOUND; DWORD dwChainFlags = CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; PCCERT_CONTEXT pCert = nullptr; HCERTCHAINENGINE hChainEngine = nullptr; PCCERT_CHAIN_CONTEXT pChainContext = nullptr; CERT_ENHKEY_USAGE EnhkeyUsage = WINPR_C_ARRAY_INIT; CERT_USAGE_MATCH CertUsage = WINPR_C_ARRAY_INIT; CERT_CHAIN_PARA ChainPara = WINPR_C_ARRAY_INIT; CERT_CHAIN_POLICY_PARA ChainPolicy = WINPR_C_ARRAY_INIT; CERT_CHAIN_POLICY_STATUS PolicyStatus = WINPR_C_ARRAY_INIT; CERT_CHAIN_ENGINE_CONFIG EngineConfig = WINPR_C_ARRAY_INIT; DWORD derPubKeyLen = WINPR_ASSERTING_INT_CAST(uint32_t, strlen(fingerprint)); char* derPubKey = calloc(derPubKeyLen, sizeof(char)); if (nullptr == derPubKey) { WLog_ERR(TAG, "Could not allocate derPubKey"); goto CleanUp; } /* ``` -------------------------------- ### pipe.c includes and initial setup Source: https://pub.freerdp.com/api/pipe_8c_source.html Initial portion of pipe.c with includes, configuration, and the start of the named pipe implementation. It sets up a static array for shared server sockets and defines a structure for tracking them, along with helper functions for pipe handle management. ```c #include #include #include #include #include #include #ifdef WINPR_HAVE_UNISTD_H #include #endif #ifndef _WIN32 #include "../handle/handle.h" #include #include #include #include #include #ifdef WINPR_HAVE_SYS_AIO_H #undef WINPR_HAVE_SYS_AIO_H /* disable for now, incomplete */ #endif #ifdef WINPR_HAVE_SYS_AIO_H #include #endif #include "pipe.h" #include "../log.h" #define TAG WINPR_TAG("pipe") /* * Since the WinPR implementation of named pipes makes use of UNIX domain * sockets, it is not possible to bind the same name more than once (i.e., * SO_REUSEADDR does not work with UNIX domain sockets). As a result, the * first call to CreateNamedPipe with name n creates a "shared" UNIX domain * socket descriptor that gets duplicated via dup() for the first and all * subsequent calls to CreateNamedPipe with name n. * * The following array keeps track of the references to the shared socked * descriptors. If an entry's reference count is zero the base socket * descriptor gets closed and the entry is removed from the list. */ static wArrayList* g_NamedPipeServerSockets = nullptr; typedef struct { char* name; int serverfd; int references; } NamedPipeServerSocketEntry; static BOOL PipeIsHandled(HANDLE handle) { return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_ANONYMOUS_PIPE, FALSE); } static int PipeGetFd(HANDLE handle) { WINPR_PIPE* pipe = (WINPR_PIPE*)handle; if (!PipeIsHandled(handle)) return -1; return pipe->fd; } static BOOL PipeCloseHandle(HANDLE handle) { WINPR_PIPE* pipe = (WINPR_PIPE*)handle; if (!PipeIsHandled(handle)) return FALSE; if (pipe->fd != -1) { close(pipe->fd); pipe->fd = -1; } return TRUE; } static BOOL PipeRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { SSIZE_T io_status = 0; WINPR_PIPE* pipe = nullptr; BOOL status = TRUE; if (lpOverlapped) { ``` -------------------------------- ### Print Command Line Help Source: https://pub.freerdp.com/api/shadow__server_8c_source.html Displays usage instructions and security notes for the shadow server, including information about SAM file paths and NLA authentication. ```c WINPR_ATTR_NODISCARD static int shadow_server_print_command_line_help(int argc, char** argv, const COMMAND_LINE_ARGUMENT_A* largs) { if ((argc < 1) || !largs || !argv) return -1; { char* path = winpr_GetConfigFilePath(TRUE, "SAM"); printf("Usage: %s [options]\n", argv[0]); printf("\n"); printf("Notes: By default NLA security is active.\n"); printf("\tIn this mode a SAM database is required.\n"); printf("\tProvide one with /sam-file:\n"); printf("\telse the default path %s is used.\n", path); printf("\tIf there is no existing SAM file authentication for all users will fail.\n"); printf("\n\tIf authentication against PAM is desired, start with -sec-nla (requires " "compiled in " "support for PAM)\n\n"); ``` -------------------------------- ### SSE2 quantization decode block (beginning) Source: https://pub.freerdp.com/api/rfx__sse2_8c_source.html Inline function rfx_quantization_decode_block_sse2, which performs the quantization decode (inverse quantization) for a block of integer coefficients. The snippet shows the beginning of the function, with its signature and the start of its parameter setup. The implementation continues beyond the displayed lines. ```c static inline void __attribute__((ATTRIBUTES)) rfx_quantization_decode_block_sse2(INT16* WINPR_RESTRICT buffer, const size_t buffer_size, ``` -------------------------------- ### Connect using bookmark with permission handling Source: https://pub.freerdp.com/api/SessionActivity_8java_source.html Creates a session from a bookmark, adjusts screen settings to device metrics when automatic or fit-screen, and requests RECORD_AUDIO/CAMERA permissions only if the corresponding redirect is enabled. If permissions are needed, it stores the bookmark and returns; otherwise it proceeds to connectWithTitle. ```java private void connect(BookmarkBase bookmark) { session = GlobalApp.createSession(bookmark, getApplicationContext()); BookmarkBase.ScreenSettings screenSettings = session.getBookmark().getActiveScreenSettings(); Log.v(TAG, "Screen Resolution: " + screenSettings.getResolutionString()); if (screenSettings.isAutomatic()) { // Instead of enforcing obsolete ratios based on screen categories, // directly map to actual device metrics without arbitrary multi-scaling. screenSettings.setHeight(screen_height); screenSettings.setWidth(screen_width); } if (screenSettings.isFitScreen()) { screenSettings.setHeight(screen_height); screenSettings.setWidth(screen_width); } // RECORD_AUDIO / CAMERA: only if the matching redirect is enabled. java.util.ArrayList needed = new java.util.ArrayList<>(); if (bookmark.getAdvancedSettings().getRedirectMicrophone() && checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) needed.add(Manifest.permission.RECORD_AUDIO); if (bookmark.getAdvancedSettings().getRedirectCamera() && checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) needed.add(Manifest.permission.CAMERA); if (!needed.isEmpty()) { pendingConnectBookmark = bookmark; requestPermissions(needed.toArray(new String[0]), REQUEST_MEDIA_PERMISSIONS); return; } connectWithTitle(bookmark.getLabel()); } ``` -------------------------------- ### main - client startup and shutdown Source: https://pub.freerdp.com/api/tf__freerdp_8c_source.html Entry point that creates a client context, parses command-line settings, registers stream dump handlers, starts the client, runs the thread proc, and stops the client. On failure, frees the context and returns -1. ```c int main(int argc, char* argv[]) { int rc = -1; RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT; RdpClientEntry(&clientEntryPoints); rdpContext* context = freerdp_client_context_new(&clientEntryPoints); if (!context) goto fail; { const int status = freerdp_client_settings_parse_command_line(context->settings, argc, argv, FALSE); if (status) { rc = freerdp_client_settings_command_line_status_print(context->settings, status, argc, argv); goto fail; } } if (!stream_dump_register_handlers(context, CONNECTION_STATE_MCS_CREATE_REQUEST, FALSE)) goto fail; if (freerdp_client_start(context) != 0) goto fail; { const DWORD res = tf_client_thread_proc(context->instance); rc = (int)res; } if (freerdp_client_stop(context) != 0) rc = -1; fail: freerdp_client_context_free(context); return rc; } ``` -------------------------------- ### wf_event.c: Low-level keyboard hook setup and key state helpers Source: https://pub.freerdp.com/api/wf__event_8c_source.html Initial part of wf_event.c showing includes, global state, helper functions ctrl_down/alt_ctrl_down, and the start of the low-level keyboard hook wf_ll_kbd_proc. The hook checks for flipping state and verifies the foreground window before processing key events. ```c #include #include #include #include #include #include "wf_client.h" #include "wf_gdi.h" #include "wf_event.h" #include #include static HWND g_focus_hWnd = nullptr; static HWND g_main_hWnd = nullptr; static HWND g_parent_hWnd = nullptr; #define RESIZE_MIN_DELAY 200 /* minimum delay in ms between two resizes */ static BOOL wf_scale_blt(wfContext* wfc, HDC hdc, int x, int y, int w, int h, HDC hdcSrc, int x1, int y1, DWORD rop); static BOOL wf_scale_mouse_event(wfContext* wfc, UINT16 flags, INT32 x, INT32 y); #if (_WIN32_WINNT >= 0x0500) static BOOL wf_scale_mouse_event_ex(wfContext* wfc, UINT16 flags, UINT16 buttonMask, INT32 x, INT32 y); #endif static BOOL g_flipping_in = FALSE; static BOOL g_flipping_out = FALSE; static BOOL g_keystates[256] = WINPR_C_ARRAY_INIT; static BOOL ctrl_down(void) { return g_keystates[VK_CONTROL] || g_keystates[VK_LCONTROL] || g_keystates[VK_RCONTROL]; } static BOOL alt_ctrl_down(void) { const BOOL altDown = g_keystates[VK_MENU] || g_keystates[VK_LMENU] || g_keystates[VK_RMENU]; return altDown && ctrl_down(); } LRESULT CALLBACK wf_ll_kbd_proc(int nCode, WPARAM wParam, LPARAM lParam) { DWORD ext_proc_id = 0; wfContext* wfc = nullptr; DWORD rdp_scancode; BOOL keystate; rdpInput* input; PKBDLLHOOKSTRUCT p; DEBUG_KBD("Low-level keyboard hook, hWnd %X nCode %X wParam %X", g_focus_hWnd, nCode, wParam); if (g_flipping_in) { if (!alt_ctrl_down()) g_flipping_in = FALSE; return CallNextHookEx(nullptr, nCode, wParam, lParam); } if (g_parent_hWnd && g_main_hWnd) { wfc = (wfContext*)GetWindowLongPtr(g_main_hWnd, GWLP_USERDATA); GUITHREADINFO gui_thread_info; gui_thread_info.cbSize = sizeof(GUITHREADINFO); HWND fg_win_hwnd = GetForegroundWindow(); DWORD fg_win_thread_id = GetWindowThreadProcessId(fg_win_hwnd, &ext_proc_id); BOOL result = GetGUIThreadInfo(fg_win_thread_id, &gui_thread_info); if (gui_thread_info.hwndFocus != wfc->hWndParent) { g_focus_hWnd = nullptr; return CallNextHookEx(nullptr, nCode, wParam, lParam); } g_focus_hWnd = g_main_hWnd; } if (g_focus_hWnd && (nCode == HC_ACTION)) { switch (wParam) { case WM_KEYDOWN: case WM_SYSKEYDOWN: case WM_KEYUP: case WM_SYSKEYUP: if (!wfc) wfc = (wfContext*)GetWindowLongPtr(g_focus_hWnd, GWLP_USERDATA); p = (PKBDLLHOOKSTRUCT)lParam; if (!wfc || !p) return 1; ``` -------------------------------- ### ResumeThread: Start thread if not started Source: https://pub.freerdp.com/api/thread_8c_source.html Resumes a thread by starting it if not already started. Locks the thread mutex, calls winpr_StartThread when needed, and unlocks. Returns 0 on success, -1 on invalid handle or mutex failure; warns if the thread was already started. ```c DWORD ResumeThread(HANDLE hThread) { ULONG Type = 0; WINPR_HANDLE* Object = nullptr; WINPR_THREAD* thread = nullptr; if (!winpr_Handle_GetInfo(hThread, &Type, &Object) || Object->Type != HANDLE_TYPE_THREAD) { WLog_ERR(TAG, "hThread is not a thread"); SetLastError(ERROR_INVALID_PARAMETER); return (DWORD)-1; } thread = (WINPR_THREAD*)Object; if (!run_mutex_fkt(pthread_mutex_lock, &thread->mutex)) return (DWORD)-1; if (!thread->started) { if (!winpr_StartThread(thread)) { run_mutex_fkt(pthread_mutex_checked_unlock, &thread->mutex); return (DWORD)-1; } } else WLog_WARN(TAG, "Thread already started!"); if (!run_mutex_fkt(pthread_mutex_checked_unlock, &thread->mutex)) return (DWORD)-1; return 0; } ```