From c005e814268650b2fe958896b84726bb93fbdef1 Mon Sep 17 00:00:00 2001 From: grpomega Date: Thu, 6 Mar 2014 10:04:53 -0600 Subject: [PATCH 001/128] Need Week instead of Day for TZ transistion transistion.Day is being pulled and assigned to the DST transition times instead of the week of transition. This gives the wrong date for DST implementation. Pull request #1713 can be killed if libfreerdp/locale/timezone.c can be regenerated form the file resulting from the execution of this script. All implementations of DST appear to be calculated rather than specific. http://www.webexhibits.org/daylightsaving/g.html so transistion.Day should never be relevant. --- scripts/TimeZones.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/TimeZones.cs b/scripts/TimeZones.cs index d8b0d9edd..80a1550d9 100644 --- a/scripts/TimeZones.cs +++ b/scripts/TimeZones.cs @@ -141,7 +141,7 @@ namespace TimeZones tzr.StandardDate.wYear = (UInt16)0; tzr.StandardDate.wMonth = (UInt16)transition.Month; tzr.StandardDate.wDayOfWeek = (UInt16)transition.DayOfWeek; - tzr.StandardDate.wDay = (UInt16)transition.Day; + tzr.StandardDate.wDay = (UInt16)transition.Week; tzr.StandardDate.wHour = (UInt16)time.Hour; tzr.StandardDate.wMinute = (UInt16)time.Minute; tzr.StandardDate.wSecond = (UInt16)time.Second; @@ -153,7 +153,7 @@ namespace TimeZones tzr.DaylightDate.wYear = (UInt16)0; tzr.DaylightDate.wMonth = (UInt16)transition.Month; tzr.DaylightDate.wDayOfWeek = (UInt16)transition.DayOfWeek; - tzr.DaylightDate.wDay = (UInt16)transition.Day; + tzr.DaylightDate.wDay = (UInt16)transition.Week; tzr.DaylightDate.wHour = (UInt16)time.Hour; tzr.DaylightDate.wMinute = (UInt16)time.Minute; tzr.DaylightDate.wSecond = (UInt16)time.Second; From 4b67513f3c539f70ccc6e5f341ef740e750c9fc4 Mon Sep 17 00:00:00 2001 From: ilammy Date: Sat, 15 Aug 2015 00:15:44 +0300 Subject: [PATCH 002/128] winpr/clipboard: add CF_RAW clipboard format ID This fixed-ID format is aleady used and supported implicitly by wClipboard, so we are just codifying its ID for the client use. --- winpr/include/winpr/user.h | 1 + 1 file changed, 1 insertion(+) diff --git a/winpr/include/winpr/user.h b/winpr/include/winpr/user.h index 5edc6c87a..29983ec95 100644 --- a/winpr/include/winpr/user.h +++ b/winpr/include/winpr/user.h @@ -50,6 +50,7 @@ #define IDTIMEOUT 32000 #define IDASYNC 32001 +#define CF_RAW 0 #define CF_TEXT 1 #define CF_BITMAP 2 #define CF_METAFILEPICT 3 From 8434709fc6168c1927a91cf842078f9388e7b858 Mon Sep 17 00:00:00 2001 From: ilammy Date: Sun, 16 Aug 2015 11:56:36 +0300 Subject: [PATCH 003/128] client/X11: improve clipboard format search functions The functions now have appropriate names which tell what exactly they are searching for: xf_cliprdr_get_client_format_by_id() Get a client-provided format by client-side ID. xf_cliprdr_get_client_format_by_atom() Get a client-provided format by client-side format name. xf_cliprdr_get_server_format_by_atom() Get a corresponding server format by client-side format name. The return types of functions have been adjusted accordingly and correct formats are now used everywhere without mixing them up: client-side formats are used for client -> server data flow, while server-side ones are used for server -> client tranfers. This resolves the issue #1414 as, for some reason, xfreerdp required server format list to be present to be able to provide its own client formats. Actually, we need only client format list to provide these. Also, CF_RAW special case is handled in a more elegant way: it is assumed to be present in every server format list (which is true). --- client/X11/xf_cliprdr.c | 81 ++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 33 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index c474e743e..b212e7d4a 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -122,9 +122,9 @@ static BOOL xf_cliprdr_is_self_owned(xfClipboard* clipboard) return XGetSelectionOwner(xfc->display, clipboard->clipboard_atom) == xfc->drawable; } -static xfCliprdrFormat* xf_cliprdr_get_format_by_id(xfClipboard* clipboard, UINT32 formatId) +static xfCliprdrFormat* xf_cliprdr_get_client_format_by_id(xfClipboard* clipboard, UINT32 formatId) { - UINT32 index; + int index; xfCliprdrFormat* format; for (index = 0; index < clipboard->numClientFormats; index++) @@ -138,25 +138,41 @@ static xfCliprdrFormat* xf_cliprdr_get_format_by_id(xfClipboard* clipboard, UINT return NULL; } -static xfCliprdrFormat* xf_cliprdr_get_format_by_atom(xfClipboard* clipboard, Atom atom) +static xfCliprdrFormat* xf_cliprdr_get_client_format_by_atom(xfClipboard* clipboard, Atom atom) { - int i, j; + int i; xfCliprdrFormat* format; for (i = 0; i < clipboard->numClientFormats; i++) { format = &(clipboard->clientFormats[i]); - if (format->atom != atom) - continue; - - if (format->formatId == 0) + if (format->atom == atom) return format; + } - for (j = 0; j < clipboard->numServerFormats; j++) + return NULL; +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_server_format_by_atom(xfClipboard* clipboard, Atom atom) +{ + int i, j; + xfCliprdrFormat* client_format; + CLIPRDR_FORMAT* server_format; + + for (i = 0; i < clipboard->numClientFormats; i++) + { + client_format = &(clipboard->clientFormats[i]); + + if (client_format->atom == atom) { - if (clipboard->serverFormats[j].formatId == format->formatId) - return format; + for (j = 0; j < clipboard->numServerFormats; j++) + { + server_format = &(clipboard->serverFormats[j]); + + if (server_format->formatId == client_format->formatId) + return server_format; + } } } @@ -211,9 +227,6 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) CLIPRDR_FORMAT* formats = NULL; xfContext* xfc = clipboard->xfc; - if (!clipboard->numServerFormats) - return; /* server format list was not yet received */ - XGetWindowProperty(xfc->display, xfc->drawable, clipboard->property_atom, 0, 200, 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data); @@ -235,7 +248,7 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) { atom = ((Atom*) data)[i]; - format = xf_cliprdr_get_format_by_atom(clipboard, atom); + format = xf_cliprdr_get_client_format_by_atom(clipboard, atom); if (format) { @@ -273,7 +286,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa if (clipboard->incr_starts && hasData) return; - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId); if (!hasData || !data || !format) { @@ -346,7 +359,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target) xfCliprdrFormat* format; xfContext* xfc = clipboard->xfc; - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId); if (!format || (format->atom != target)) { @@ -501,7 +514,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* BOOL delayRespond; unsigned long length; unsigned long bytes_left; - xfCliprdrFormat* format; + CLIPRDR_FORMAT* format; xfContext* xfc = clipboard->xfc; if (xevent->xselectionrequest.owner != xfc->drawable) @@ -535,14 +548,14 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* } else { - format = xf_cliprdr_get_format_by_atom(clipboard, xevent->xselectionrequest.target); + format = xf_cliprdr_get_server_format_by_atom(clipboard, xevent->xselectionrequest.target); if (format && (xevent->xselectionrequest.requestor != xfc->drawable)) { formatId = format->formatId; altFormatId = formatId; - if (formatId == 0) + if (formatId == CF_RAW) { if (XGetWindowProperty(xfc->display, xevent->xselectionrequest.requestor, clipboard->property_atom, 0, 4, 0, XA_INTEGER, @@ -631,7 +644,7 @@ static BOOL xf_cliprdr_process_property_notify(xfClipboard* clipboard, XEvent* x else if ((xevent->xproperty.window == xfc->drawable) && (xevent->xproperty.state == PropertyNewValue) && clipboard->incr_starts) { - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId); if (format) xf_cliprdr_get_requested_data(clipboard, format->atom); @@ -867,14 +880,11 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR clipboard->numServerFormats = 0; } - clipboard->numServerFormats = formatList->numFormats; + clipboard->numServerFormats = formatList->numFormats + 1; /* +1 for CF_RAW */ - if (clipboard->numServerFormats) - { - if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(clipboard->numServerFormats, sizeof(CLIPRDR_FORMAT)))) { - WLog_ERR(TAG, "failed to allocate %d CLIPRDR_FORMAT structs", clipboard->numServerFormats); - return CHANNEL_RC_NO_MEMORY; - } + if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(clipboard->numServerFormats, sizeof(CLIPRDR_FORMAT)))) { + WLog_ERR(TAG, "failed to allocate %d CLIPRDR_FORMAT structs", clipboard->numServerFormats); + return CHANNEL_RC_NO_MEMORY; } for (i = 0; i < formatList->numFormats; i++) @@ -897,6 +907,11 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR } } + /* CF_RAW is always implicitly supported by the server */ + format = &clipboard->serverFormats[formatList->numFormats]; + format->formatId = CF_RAW; + format->formatName = NULL; + clipboard->numTargets = 2; for (i = 0; i < formatList->numFormats; i++) @@ -947,13 +962,13 @@ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, if (xf_cliprdr_is_self_owned(clipboard)) { - format = xf_cliprdr_get_format_by_id(clipboard, 0); + format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW); XChangeProperty(xfc->display, xfc->drawable, clipboard->property_atom, XA_INTEGER, 32, PropModeReplace, (BYTE*) &formatId, 1); } else - format = xf_cliprdr_get_format_by_id(clipboard, formatId); + format = xf_cliprdr_get_client_format_by_id(clipboard, formatId); if (!format) return xf_cliprdr_send_data_response(clipboard, NULL, 0); @@ -984,7 +999,7 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context UINT32 SrcSize; UINT32 formatId; UINT32 altFormatId; - xfCliprdrFormat* format; + CLIPRDR_FORMAT* format; BOOL nullTerminated = FALSE; UINT32 size = formatDataResponse->dataLen; BYTE* data = formatDataResponse->requestedFormatData; @@ -994,7 +1009,7 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context if (!clipboard->respond) return CHANNEL_RC_OK; - format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId); + format = xf_cliprdr_get_server_format_by_id(clipboard, clipboard->requestedFormatId); if (clipboard->data) { @@ -1140,7 +1155,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) n = 0; clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "_FREERDP_RAW", False); - clipboard->clientFormats[n].formatId = 0; + clipboard->clientFormats[n].formatId = CF_RAW; n++; clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "UTF8_STRING", False); From b9a297379b0a5f75c87e31f94975dc5f883a8ba9 Mon Sep 17 00:00:00 2001 From: ilammy Date: Mon, 17 Aug 2015 11:35:19 +0300 Subject: [PATCH 004/128] client/X11: improve named clipboard format support Clipboard formats are identified by numerical IDs and literal names. We can keep using arbitrary defined IDs for local clipboard formats as we are sure that they have some fixed meaning, but the server can and will be using its own IDs, which can be different from ours for the named formats. Therefore: 1) A correct way to compare a local format to a remote one is to check the names first, and only then compare their IDs. (Extra care should be taken to support short format names.) 2) Server IDs cannot be used with wClipboard directly when dealing with named formats. Format name should be used to extract correct local ID for the use with Clipboard{Set,Get}Data(). Also, I find the notion of 'alternate' format IDs to be confusing. We either deal with a fixed ID format (declared in ), or a format that was given an arbitrary fixed ID for local use (defined in ), or a remote format identified by a pair of an ID and a name. Format IDs can be local and remote, but there are no 'alternates'. So now: 1) A new function xf_cliprdr_formats_equal() is used to compare formats correctly in xf_cliprdr_get_server_format_by_atom() when searching for a server format corresponding to a local one, and in xf_cliprdr_server_format_list() when constructing a local TARGETS list from the server format list. 2) Correct local format IDs are used with wClipboard conversions by xf_cliprdr_process_requested_data() and xf_cliprdr_server_format_data_response(). 3) We refer to formatId and formatName when doing requests, and srcFormatId and dstFormatId when doing conversions, instead of using formatId and altFormatId for both purposes. 4) Server format ID and name are used to identify cached clipboard contents. The name is compared directly as a pointer because it will be a pointer from the same clipboard->serverFormats array. Also, the clipboard contents are invalidated when format list arrives, so xf_cliprdr_server_format_list() now also clears the format ID and name together with the data. --- client/X11/xf_cliprdr.c | 123 +++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 47 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index b212e7d4a..477c842b5 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -76,8 +76,8 @@ struct xf_clipboard int requestedFormatId; BYTE* data; - UINT32 data_format; - UINT32 data_alt_format; + UINT32 data_format_id; + const char* data_format_name; int data_length; XEvent* respond; @@ -122,6 +122,22 @@ static BOOL xf_cliprdr_is_self_owned(xfClipboard* clipboard) return XGetSelectionOwner(xfc->display, clipboard->clipboard_atom) == xfc->drawable; } +static BOOL xf_cliprdr_formats_equal(const CLIPRDR_FORMAT* server, const xfCliprdrFormat* client) +{ + if (server->formatName && client->formatName) + { + /* The server may be using short format names while we store them in full form. */ + return (0 == strncmp(server->formatName, client->formatName, strlen(server->formatName))); + } + + if (!server->formatName && !client->formatName) + { + return (server->formatId == client->formatId); + } + + return FALSE; +} + static xfCliprdrFormat* xf_cliprdr_get_client_format_by_id(xfClipboard* clipboard, UINT32 formatId) { int index; @@ -170,7 +186,7 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_server_format_by_atom(xfClipboard* clipboa { server_format = &(clipboard->serverFormats[j]); - if (server_format->formatId == client_format->formatId) + if (xf_cliprdr_formats_equal(server_format, client_format)) return server_format; } } @@ -277,8 +293,8 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa BOOL bSuccess; UINT32 SrcSize; UINT32 DstSize; - UINT32 formatId; - UINT32 altFormatId; + UINT32 srcFormatId; + UINT32 dstFormatId; BYTE* pSrcData = NULL; BYTE* pDstData = NULL; xfCliprdrFormat* format; @@ -294,8 +310,8 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa return; } - formatId = 0; - altFormatId = 0; + srcFormatId = 0; + dstFormatId = 0; switch (format->formatId) { @@ -303,16 +319,16 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa case CF_OEMTEXT: case CF_UNICODETEXT: size = strlen((char*) data) + 1; - formatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); break; case CF_DIB: - formatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); + srcFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); break; case CB_FORMAT_HTML: size = strlen((char*) data) + 1; - formatId = ClipboardGetFormatId(clipboard->system, "text/html"); + srcFormatId = ClipboardGetFormatId(clipboard->system, "text/html"); break; } @@ -324,17 +340,24 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa CopyMemory(pSrcData, data, SrcSize); - bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize); + bSuccess = ClipboardSetData(clipboard->system, srcFormatId, (void*) pSrcData, SrcSize); if (!bSuccess) free(pSrcData); - altFormatId = clipboard->requestedFormatId; + if (format->formatName) + { + dstFormatId = ClipboardGetFormatId(clipboard->system, format->formatName); + } + else + { + dstFormatId = format->formatId; + } - if (bSuccess && altFormatId) + if (bSuccess && dstFormatId) { DstSize = 0; - pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize); + pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); } if (!pDstData) @@ -508,8 +531,8 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* int fmt; Atom type; UINT32 formatId; + const char* formatName; XEvent* respond; - UINT32 altFormatId; BYTE* data = NULL; BOOL delayRespond; unsigned long length; @@ -553,7 +576,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* if (format && (xevent->xselectionrequest.requestor != xfc->drawable)) { formatId = format->formatId; - altFormatId = formatId; + formatName = format->formatName; if (formatId == CF_RAW) { @@ -566,12 +589,12 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* if (data) { - CopyMemory(&altFormatId, data, 4); + CopyMemory(&formatId, data, 4); XFree(data); } } - if ((clipboard->data != 0) && (formatId == clipboard->data_format) && (altFormatId == clipboard->data_alt_format)) + if ((clipboard->data != 0) && (formatId == clipboard->data_format_id) && (formatName == clipboard->data_format_name)) { /* Cached clipboard data available. Send it now */ respond->xselection.property = xevent->xselectionrequest.property; @@ -595,11 +618,11 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* respond->xselection.property = xevent->xselectionrequest.property; clipboard->respond = respond; - clipboard->data_format = formatId; - clipboard->data_alt_format = altFormatId; + clipboard->data_format_id = formatId; + clipboard->data_format_name = formatName; delayRespond = TRUE; - xf_cliprdr_send_data_request(clipboard, altFormatId); + xf_cliprdr_send_data_request(clipboard, formatId); } } } @@ -869,6 +892,9 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR clipboard->data = NULL; } + clipboard->data_format_id = -1; + clipboard->data_format_name = NULL; + if (clipboard->serverFormats) { for (i = 0; i < clipboard->numServerFormats; i++) @@ -920,7 +946,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR for (j = 0; j < clipboard->numClientFormats; j++) { - if (format->formatId == clipboard->clientFormats[j].formatId) + if (xf_cliprdr_formats_equal(format, &clipboard->clientFormats[j])) { xf_cliprdr_append_target(clipboard, clipboard->clientFormats[j].atom); } @@ -997,9 +1023,8 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context BYTE* pDstData; UINT32 DstSize; UINT32 SrcSize; - UINT32 formatId; - UINT32 altFormatId; - CLIPRDR_FORMAT* format; + UINT32 srcFormatId; + UINT32 dstFormatId; BOOL nullTerminated = FALSE; UINT32 size = formatDataResponse->dataLen; BYTE* data = formatDataResponse->requestedFormatData; @@ -1009,8 +1034,6 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context if (!clipboard->respond) return CHANNEL_RC_OK; - format = xf_cliprdr_get_server_format_by_id(clipboard, clipboard->requestedFormatId); - if (clipboard->data) { free(clipboard->data); @@ -1020,39 +1043,45 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context pDstData = NULL; DstSize = 0; - formatId = 0; - altFormatId = 0; + srcFormatId = 0; + dstFormatId = 0; - switch (clipboard->data_format) + if (clipboard->data_format_name) { + if (strcmp(clipboard->data_format_name, "HTML Format") == 0) + { + srcFormatId = ClipboardGetFormatId(clipboard->system, "HTML Format"); + dstFormatId = ClipboardGetFormatId(clipboard->system, "text/html"); + nullTerminated = TRUE; + } + } + else + { + switch (clipboard->data_format_id) + { case CF_TEXT: - formatId = CF_TEXT; - altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = CF_TEXT; + dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); nullTerminated = TRUE; break; case CF_OEMTEXT: - formatId = CF_OEMTEXT; - altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = CF_OEMTEXT; + dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); nullTerminated = TRUE; break; case CF_UNICODETEXT: - formatId = CF_UNICODETEXT; - altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); + srcFormatId = CF_UNICODETEXT; + dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING"); nullTerminated = TRUE; break; case CF_DIB: - formatId = CF_DIB; - altFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); - break; - - case CB_FORMAT_HTML: - formatId = ClipboardGetFormatId(clipboard->system, "HTML Format"); - altFormatId = ClipboardGetFormatId(clipboard->system, "text/html"); - nullTerminated = TRUE; + srcFormatId = CF_DIB; + dstFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp"); break; + } } SrcSize = (UINT32) size; @@ -1063,15 +1092,15 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context CopyMemory(pSrcData, data, SrcSize); - bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize); + bSuccess = ClipboardSetData(clipboard->system, srcFormatId, (void*) pSrcData, SrcSize); if (!bSuccess) free (pSrcData); - if (bSuccess && altFormatId) + if (bSuccess && dstFormatId) { DstSize = 0; - pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize); + pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); if ((DstSize > 1) && nullTerminated) DstSize--; From d7c9a31b4bb0cbd1b52861a523e1cd7231ee196b Mon Sep 17 00:00:00 2001 From: ilammy Date: Wed, 19 Aug 2015 17:25:17 +0300 Subject: [PATCH 005/128] client/X11: correctly trim terminating null bytes from strings Sometimes Windows sends strings with excess null terminating bytes. For example, when one copies digits from calc.exe. At the same time, some local applications freak out when they encounter null bytes (at least LibreOffice is known to be replacing them with '#'). According to the specification of UTF8_STRING format [1], the string data must not contain any trailing null bytes. So they all should be trimmed, not only the last one. Also, if the trailing null byte is not present, the length should not be adjusted. For example, Firefox is actually sending "HTML Format" without a null byte while Internet Explorer adds one. The spec for text/html format [2] says nothing about the teminating null byte, so we are free to remove it, but at least we should not mistakingly delete '>' character of "" tag when it is the last character. [1] http://www.pps.univ-paris-diderot.fr/~jch/software/UTF8_STRING/UTF8_STRING.text [2] https://www.ietf.org/rfc/rfc2854.txt --- client/X11/xf_cliprdr.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 477c842b5..a68cc3129 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -1102,8 +1102,11 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context DstSize = 0; pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); - if ((DstSize > 1) && nullTerminated) - DstSize--; + if (nullTerminated) + { + while (DstSize > 0 && pDstData[DstSize - 1] == '\0') + DstSize--; + } } clipboard->data = pDstData; From 46fb66e0fbe85b9caa236b709de5853cb6382cf9 Mon Sep 17 00:00:00 2001 From: ilammy Date: Tue, 18 Aug 2015 17:05:48 +0300 Subject: [PATCH 006/128] client/X11: send clipboard format data errors correctly xf_cliprdr_send_data_response() is consistently called with NULL data pointer as a way to report errors, but it was not setting the msgFlags field accordingly. --- client/X11/xf_cliprdr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index a68cc3129..e6fdf15a5 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -222,7 +222,7 @@ static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, in ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE)); - response.msgFlags = CB_RESPONSE_OK; + response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL; response.dataLen = size; response.requestedFormatData = data; From 532371d5aa5dbb2fa58ec9833138d7dcc2d3edaf Mon Sep 17 00:00:00 2001 From: ilammy Date: Tue, 18 Aug 2015 17:07:38 +0300 Subject: [PATCH 007/128] client/X11: remove unused function xf_cliprdr_send_data_request() is actually used instead of this one. --- client/X11/xf_cliprdr.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index e6fdf15a5..6dea2c1a4 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -823,24 +823,6 @@ UINT xf_cliprdr_send_client_format_list_response(xfClipboard* clipboard, BOOL st return clipboard->context->ClientFormatListResponse(clipboard->context, &formatListResponse); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -int xf_cliprdr_send_client_format_data_request(xfClipboard* clipboard, UINT32 formatId) -{ - CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; - - formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST; - formatDataRequest.msgFlags = CB_RESPONSE_OK; - - formatDataRequest.requestedFormatId = formatId; - clipboard->requestedFormatId = formatId; - - return clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest); -} - /** * Function description * From 626e40a9c15f0e8e9d878e702155ccbbafc35b77 Mon Sep 17 00:00:00 2001 From: ilammy Date: Fri, 14 Aug 2015 22:57:42 +0300 Subject: [PATCH 008/128] client/X11: add raw clipboard transfer indication Some time ago there was a property _FREERDP_CLIPRDR_ID which was indended to indicate that an XFreeRDP window owns a clipboard. This was necessary for raw transfers. This property was used by xf_cliprdr_is_self_owned() function. However, raw transfer support was broken and the meaning of xf_cliprdr_is_self_owned() gradually changed into checking whether the *current* window owns the clipboard, not just any XFreeRDP window. Thus _FREERDP_CLIPRDR_ID was removed in a4580923e77b4690 (xfreerdp/clipr: fix self owned test and hardening). However, now we are going to fix raw transfers and we need that property. This patch reintroduces a similar property "_FREERDP_CLIPRDR_RAW" which indicates that a window is an XFreeRDP window with enabled raw transfer. It is currently used by xf_cliprdr_server_format_data_request() to correctly request format data from another XFreeRDP instance via raw transfer protocol. This property can be queried from the clipboard owner with the function xf_cliprdr_is_raw_transfer_available() and can be enabled or disabled on the current window by xf_cliprdr_set_raw_transfer_enabled(). Disabling raw transfers will be necesary to correctly implement file transfers in the future. However, currently raw transfers are always enabled. --- client/X11/xf_cliprdr.c | 53 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 6dea2c1a4..04abea08f 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -64,6 +64,8 @@ struct xf_clipboard Atom clipboard_atom; Atom property_atom; + Atom raw_transfer_atom; + int numClientFormats; xfCliprdrFormat clientFormats[20]; @@ -122,6 +124,51 @@ static BOOL xf_cliprdr_is_self_owned(xfClipboard* clipboard) return XGetSelectionOwner(xfc->display, clipboard->clipboard_atom) == xfc->drawable; } +static void xf_cliprdr_set_raw_transfer_enabled(xfClipboard* clipboard, BOOL enabled) +{ + UINT32 data = enabled; + xfContext* xfc = clipboard->xfc; + + XChangeProperty(xfc->display, xfc->drawable, clipboard->raw_transfer_atom, + XA_INTEGER, 32, PropModeReplace, (BYTE*) &data, 1); +} + +static BOOL xf_cliprdr_is_raw_transfer_available(xfClipboard* clipboard) +{ + Atom type; + int format; + int result = 0; + unsigned long length; + unsigned long bytes_left; + UINT32* data = NULL; + UINT32 is_enabled = 0; + Window owner = None; + xfContext* xfc = clipboard->xfc; + + owner = XGetSelectionOwner(xfc->display, clipboard->clipboard_atom); + + if (owner != None) + { + result = XGetWindowProperty(xfc->display, owner, + clipboard->raw_transfer_atom, 0, 4, 0, XA_INTEGER, + &type, &format, &length, &bytes_left, (BYTE**) &data); + } + + if (data) + { + is_enabled = *data; + XFree(data); + } + + if ((owner == None) || (owner == xfc->drawable)) + return FALSE; + + if (result != Success) + return FALSE; + + return is_enabled ? TRUE : FALSE; +} + static BOOL xf_cliprdr_formats_equal(const CLIPRDR_FORMAT* server, const xfCliprdrFormat* client) { if (server->formatName && client->formatName) @@ -968,7 +1015,7 @@ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, xfClipboard* clipboard = (xfClipboard*) context->custom; xfContext* xfc = clipboard->xfc; - if (xf_cliprdr_is_self_owned(clipboard)) + if (xf_cliprdr_is_raw_transfer_available(clipboard)) { format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW); @@ -1140,6 +1187,10 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE); + clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE); + + xf_cliprdr_set_raw_transfer_enabled(clipboard, TRUE); + XSelectInput(xfc->display, clipboard->root_window, PropertyChangeMask); #ifdef WITH_XFIXES From 391ed0d91da25736da7ee663d853bb4bdba50a8d Mon Sep 17 00:00:00 2001 From: ilammy Date: Wed, 19 Aug 2015 10:59:49 +0300 Subject: [PATCH 009/128] client/X11: transfer raw clipboard format lists The first part of raw transfer sequence is to transfer the format list of the session A into the session B. Then we will be able to request/reply with raw data using proper format IDs. xf_cliprdr_server_format_list() of the session A now exposes the raw server format list. As soon as the list is received, it is serialized and put into _FREERDP_CLIPRDR_FORMATS property. xf_cliprdr_get_requested_targets() of the session B now checks whether the clipboard owner is a FreeRDP session with enabled raw transfer capability. If it is, the raw format list is simply extracted from _FREERDP_CLIPRDR_FORMATS of the clipboard owner. Otherwise, the format list is populated from the usual TARGETS clipboard format. --- client/X11/xf_cliprdr.c | 215 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 205 insertions(+), 10 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 04abea08f..6edf284a2 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -65,6 +65,7 @@ struct xf_clipboard Atom property_atom; Atom raw_transfer_atom; + Atom raw_format_list_atom; int numClientFormats; xfCliprdrFormat clientFormats[20]; @@ -276,7 +277,144 @@ static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, in return clipboard->context->ClientFormatDataResponse(clipboard->context, &response); } -static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) +static wStream* xf_cliprdr_serialize_server_format_list(xfClipboard* clipboard) +{ + UINT32 i; + UINT32 formatCount; + wStream* s = NULL; + + /* Typical MS Word format list is about 80 bytes long. */ + if (!(s = Stream_New(NULL, 128))) + { + WLog_ERR(TAG, "failed to allocate serialized format list"); + goto error; + } + + /* If present, the last format is always synthetic CF_RAW. Do not include it. */ + formatCount = (clipboard->numServerFormats > 0) ? clipboard->numServerFormats - 1 : 0; + + Stream_Write_UINT32(s, formatCount); + + for (i = 0; i < formatCount; i++) + { + CLIPRDR_FORMAT* format = &clipboard->serverFormats[i]; + size_t name_length = format->formatName ? strlen(format->formatName) : 0; + + if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32) + name_length + 1)) + { + WLog_ERR(TAG, "failed to expand serialized format list"); + goto error; + } + + Stream_Write_UINT32(s, format->formatId); + Stream_Write(s, format->formatName, name_length); + Stream_Write_UINT8(s, '\0'); + } + + Stream_SealLength(s); + + return s; + +error: + Stream_Free(s, TRUE); + return NULL; +} + +static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data, size_t length, UINT32* numFormats) +{ + UINT32 i; + wStream* s = NULL; + CLIPRDR_FORMAT* formats = NULL; + + if (!(s = Stream_New(data, length))) + { + WLog_ERR(TAG, "failed to allocate stream for parsing serialized format list"); + goto error; + } + + if (Stream_GetRemainingLength(s) < sizeof(UINT32)) + { + WLog_ERR(TAG, "too short serialized format list"); + goto error; + } + + Stream_Read_UINT32(s, *numFormats); + + if (!(formats = (CLIPRDR_FORMAT*) calloc(*numFormats, sizeof(CLIPRDR_FORMAT)))) + { + WLog_ERR(TAG, "failed to allocate format list"); + goto error; + } + + for (i = 0; i < *numFormats; i++) + { + if (Stream_GetRemainingLength(s) < sizeof(UINT32)) + { + WLog_ERR(TAG, "unexpected end of serialized format list"); + goto error; + } + + Stream_Read_UINT32(s, formats[i].formatId); + formats[i].formatName = strdup((char*) Stream_Pointer(s)); + Stream_Seek(s, strlen((char*) Stream_Pointer(s)) + 1); + } + + Stream_Free(s, FALSE); + + return formats; + +error: + Stream_Free(s, FALSE); + free(formats); + *numFormats = 0; + return NULL; +} + +static void xf_cliprdr_free_formats(CLIPRDR_FORMAT* formats, UINT32 numFormats) +{ + UINT32 i; + + for (i = 0; i < numFormats; i++) + { + free(formats[i].formatName); + } + + free(formats); +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard, UINT32* numFormats) +{ + Atom type = None; + int format = 0; + unsigned long length = 0; + unsigned long remaining; + BYTE* data = NULL; + CLIPRDR_FORMAT* formats = NULL; + xfContext* xfc = clipboard->xfc; + + *numFormats = 0; + + XGetWindowProperty(xfc->display, clipboard->owner, clipboard->raw_format_list_atom, + 0, 4096, False, clipboard->raw_format_list_atom, &type, &format, + &length, &remaining, &data); + + if (data && length > 0 && format == 8 && type == clipboard->raw_format_list_atom) + { + formats = xf_cliprdr_parse_server_format_list(data, length, numFormats); + } + else + { + WLog_ERR(TAG, "failed to retrieve raw format list: data=%p, length=%lu, format=%d, type=%d (expected=%d)", + data, length, format, type, clipboard->raw_format_list_atom); + } + + if (data) + XFree(data); + + return formats; +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboard, UINT32* numFormats) { int i; Atom atom; @@ -284,12 +422,12 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) int format_property; unsigned long length; unsigned long bytes_left; - UINT32 numFormats = 0; - CLIPRDR_FORMAT_LIST formatList; xfCliprdrFormat* format = NULL; CLIPRDR_FORMAT* formats = NULL; xfContext* xfc = clipboard->xfc; + *numFormats = 0; + XGetWindowProperty(xfc->display, xfc->drawable, clipboard->property_atom, 0, 200, 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data); @@ -315,12 +453,69 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) if (format) { - formats[numFormats].formatId = format->formatId; - formats[numFormats].formatName = format->formatName; - numFormats++; + formats[*numFormats].formatId = format->formatId; + formats[*numFormats].formatName = _strdup(format->formatName); + *numFormats += 1; } } +out: + if (data) + XFree(data); + + return formats; +} + +static CLIPRDR_FORMAT* xf_cliprdr_get_client_formats(xfClipboard* clipboard, UINT32* numFormats) +{ + CLIPRDR_FORMAT* formats = NULL; + + *numFormats = 0; + + if (xf_cliprdr_is_raw_transfer_available(clipboard)) + { + formats = xf_cliprdr_get_raw_server_formats(clipboard, numFormats); + } + + if (*numFormats == 0) + { + xf_cliprdr_free_formats(formats, *numFormats); + + formats = xf_cliprdr_get_formats_from_targets(clipboard, numFormats); + } + + return formats; +} + +static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard) +{ + wStream* formats = NULL; + xfContext* xfc = clipboard->xfc; + + formats = xf_cliprdr_serialize_server_format_list(clipboard); + + if (formats) + { + XChangeProperty(xfc->display, xfc->drawable, clipboard->raw_format_list_atom, + clipboard->raw_format_list_atom, 8, PropModeReplace, + Stream_Buffer(formats), Stream_Length(formats)); + } + else + { + XDeleteProperty(xfc->display, xfc->drawable, clipboard->raw_format_list_atom); + } + + Stream_Free(formats, TRUE); +} + +static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) +{ + UINT32 numFormats = 0; + CLIPRDR_FORMAT* formats = NULL; + CLIPRDR_FORMAT_LIST formatList; + + formats = xf_cliprdr_get_client_formats(clipboard, &numFormats); + ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST)); formatList.msgFlags = CB_RESPONSE_OK; @@ -329,10 +524,7 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard) clipboard->context->ClientFormatList(clipboard->context, &formatList); -out: - if (data) - XFree(data); - free(formats); + xf_cliprdr_free_formats(formats, numFormats); } static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData, BYTE* data, int size) @@ -967,6 +1159,8 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR format->formatId = CF_RAW; format->formatName = NULL; + xf_cliprdr_provide_server_format_list(clipboard); + clipboard->numTargets = 2; for (i = 0; i < formatList->numFormats; i++) @@ -1188,6 +1382,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc) clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE); clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE); + clipboard->raw_format_list_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE); xf_cliprdr_set_raw_transfer_enabled(clipboard, TRUE); From 7bce7ef372a483e221c4c08dec076c58212ba973 Mon Sep 17 00:00:00 2001 From: ilammy Date: Wed, 19 Aug 2015 10:25:59 +0300 Subject: [PATCH 010/128] client/X11: transfer raw clipboard format data The second step of raw transfer is to transfer the format data itself. This has been already implemented in XFreeRDP before, but several tweaks are required for it to work correctly. The idea of raw data transfer is to request for _FREERDP_RAW clipboard format while putting the actual formatId into _FREERDP_CLIPRDR property where the requested data is expected to arrive to. Then the clipboard owner will check for the real formatId and deliver the expected data. This stays true, but the check is performed in a more straightforward way, and CF_RAW format (numerically equal to zero) is not considered an unknown destination format when performing (identity) conversions with wClipboard. This is not an issue because wClipboard will allow only identity conversion for CF_RAW, it will fail if something else is going to be converted into CF_RAW. --- client/X11/xf_cliprdr.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index 6edf284a2..a13612a30 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -79,6 +79,7 @@ struct xf_clipboard int requestedFormatId; BYTE* data; + BOOL data_raw_format; UINT32 data_format_id; const char* data_format_name; int data_length; @@ -554,6 +555,10 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa switch (format->formatId) { + case CF_RAW: + srcFormatId = CF_RAW; + break; + case CF_TEXT: case CF_OEMTEXT: case CF_UNICODETEXT: @@ -593,7 +598,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa dstFormatId = format->formatId; } - if (bSuccess && dstFormatId) + if (bSuccess) { DstSize = 0; pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); @@ -774,6 +779,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* XEvent* respond; BYTE* data = NULL; BOOL delayRespond; + BOOL rawTransfer; unsigned long length; unsigned long bytes_left; CLIPRDR_FORMAT* format; @@ -816,6 +822,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* { formatId = format->formatId; formatName = format->formatName; + rawTransfer = FALSE; if (formatId == CF_RAW) { @@ -828,6 +835,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* if (data) { + rawTransfer = TRUE; CopyMemory(&formatId, data, 4); XFree(data); } @@ -859,6 +867,7 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent* clipboard->respond = respond; clipboard->data_format_id = formatId; clipboard->data_format_name = formatName; + clipboard->data_raw_format = rawTransfer; delayRespond = TRUE; xf_cliprdr_send_data_request(clipboard, formatId); @@ -1204,12 +1213,15 @@ static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext* context */ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { + BOOL rawTransfer; xfCliprdrFormat* format = NULL; UINT32 formatId = formatDataRequest->requestedFormatId; xfClipboard* clipboard = (xfClipboard*) context->custom; xfContext* xfc = clipboard->xfc; - if (xf_cliprdr_is_raw_transfer_available(clipboard)) + rawTransfer = xf_cliprdr_is_raw_transfer_available(clipboard); + + if (rawTransfer) { format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW); @@ -1222,7 +1234,7 @@ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, if (!format) return xf_cliprdr_send_data_response(clipboard, NULL, 0); - clipboard->requestedFormatId = formatId; + clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId; XConvertSelection(xfc->display, clipboard->clipboard_atom, format->atom, clipboard->property_atom, xfc->drawable, CurrentTime); @@ -1269,7 +1281,12 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context srcFormatId = 0; dstFormatId = 0; - if (clipboard->data_format_name) + if (clipboard->data_raw_format) + { + srcFormatId = CF_RAW; + dstFormatId = CF_RAW; + } + else if (clipboard->data_format_name) { if (strcmp(clipboard->data_format_name, "HTML Format") == 0) { @@ -1320,7 +1337,7 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context if (!bSuccess) free (pSrcData); - if (bSuccess && dstFormatId) + if (bSuccess) { DstSize = 0; pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize); From 3b0f5b5b48ac9be4e795c6284e34a8e01670da49 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 4 Feb 2016 12:55:11 +0100 Subject: [PATCH 011/128] Removed obsolete APPLE preprocessor switch. --- libfreerdp/crypto/tls.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index e8627e41e..a77f7f130 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -589,12 +589,7 @@ out_free: return NULL; } - -#if defined(__APPLE__) -BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int options, BOOL clientMode) -#else -BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode) -#endif +static BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode) { rdpSettings* settings = tls->settings; From b6b0f57a88d6c6810a1d81fccc533948ce28f606 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 4 Feb 2016 12:57:21 +0100 Subject: [PATCH 012/128] Fixed compiler warning about cast. --- winpr/libwinpr/thread/thread.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/winpr/libwinpr/thread/thread.c b/winpr/libwinpr/thread/thread.c index 54fd38874..39eaa3584 100644 --- a/winpr/libwinpr/thread/thread.c +++ b/winpr/libwinpr/thread/thread.c @@ -663,8 +663,7 @@ DWORD GetCurrentThreadId(VOID) /* Since pthread_t can be 64-bits on some systems, take just the */ /* lower 32-bits of it for the thread ID returned by this function. */ - tid = (long)tid & 0xffffffff; - return (DWORD) tid; + return (DWORD)tid & 0xffffffffUL; } DWORD ResumeThread(HANDLE hThread) From 16699000c4a88a3fb49528a52e77948c2b46d819 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 14 Dec 2015 14:01:12 +0100 Subject: [PATCH 013/128] Fixed allocation issue with common_name. --- libfreerdp/crypto/crypto.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 26c69fdaf..df76070f1 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -404,7 +404,8 @@ char* crypto_cert_subject(X509* xcert) char* crypto_cert_subject_common_name(X509* xcert, int* length) { int index; - BYTE* common_name; + BYTE* common_name_raw; + char* common_name; X509_NAME* subject_name; X509_NAME_ENTRY* entry; ASN1_STRING* entry_data; @@ -429,11 +430,14 @@ char* crypto_cert_subject_common_name(X509* xcert, int* length) if (entry_data == NULL) return NULL; - *length = ASN1_STRING_to_UTF8(&common_name, entry_data); + *length = ASN1_STRING_to_UTF8(&common_name_raw, entry_data); if (*length < 0) return NULL; + common_name = _strdup(common_name_raw); + OPENSSL_free(common_name_raw); + return (char*) common_name; } From cbf2892cccbd1052a45c41c5023c088100403164 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 14 Dec 2015 14:02:49 +0100 Subject: [PATCH 014/128] Implemented temporary certificate accept. Certificates can now be accepted temporarily. The callbacks for certificate validation have been modified to extend the information presented to the user. --- client/Android/android_jni_callback.c | 48 ++++++++++ client/Android/android_jni_callback.h | 1 + client/Wayland/wlfreerdp.c | 77 ++++++++++++---- client/Windows/wf_client.c | 26 ++++++ client/X11/xf_client.c | 126 ++++++++++++++++++-------- client/iOS/FreeRDP/ios_freerdp_ui.h | 11 ++- client/iOS/FreeRDP/ios_freerdp_ui.m | 54 ++++++----- include/freerdp/freerdp.h | 56 ++++++++++-- libfreerdp/crypto/tls.c | 72 +++++++-------- server/shadow/Win/win_rdp.c | 6 +- 10 files changed, 347 insertions(+), 130 deletions(-) diff --git a/client/Android/android_jni_callback.c b/client/Android/android_jni_callback.c index ee4869601..d103b80e2 100644 --- a/client/Android/android_jni_callback.c +++ b/client/Android/android_jni_callback.c @@ -172,6 +172,45 @@ finish: return res; } +/* callback with int result */ +jint java_callback_int(jobject obj, const char * callback, const char* signature, va_list args) +{ + jclass jObjClass; + jmethodID jCallback; + jboolean attached; + jint res = -1; + JNIEnv *env; + + DEBUG_ANDROID("java_callback: %s (%s)", callback, signature); + + attached = jni_attach_thread(&env); + + jObjClass = (*env)->GetObjectClass(env, obj); + + if (!jObjClass) + { + WLog_ERR(TAG, "android_java_callback: failed to get class reference"); + goto finish; + } + + jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature); + + if (!jCallback) + { + WLog_ERR(TAG, "android_java_callback: failed to get method id"); + goto finish; + } + + res = (*env)->CallStaticIntMethodV(env, jObjClass, jCallback, args); + +finish: + if(attached == JNI_TRUE) + jni_detach_thread(); + + return res; +} + + /* callback to freerdp class */ void freerdp_callback(const char * callback, const char * signature, ...) { @@ -189,3 +228,12 @@ jboolean freerdp_callback_bool_result(const char * callback, const char * signat va_end(vl); return res; } + +jint freerdp_callback_int_result(const char * callback, const char * signature, ...) +{ + va_list vl; + va_start(vl, signature); + jint res = java_callback_int(jLibFreeRDPObject, callback, signature, vl); + va_end(vl); + return res; +} diff --git a/client/Android/android_jni_callback.h b/client/Android/android_jni_callback.h index dbe172e72..95d0336ee 100644 --- a/client/Android/android_jni_callback.h +++ b/client/Android/android_jni_callback.h @@ -21,6 +21,7 @@ jboolean jni_attach_thread(JNIEnv** env); void jni_detach_thread(void); void freerdp_callback(const char * callback, const char * signature, ...); jboolean freerdp_callback_bool_result(const char * callback, const char * signature, ...); +jint freerdp_callback_int_result(const char * callback, const char * signature, ...); #endif /* FREERDP_ANDROID_JNI_CALLBACK_H */ diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 456e64ac1..2cc7597da 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -172,44 +172,82 @@ static void wl_post_disconnect(freerdp* instance) wlf_DestroyWindow(context, context->window); } -static BOOL wl_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) +static DWORD wl_accept_certificate(rdpSettings* settings) { char answer; - printf("Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("The above X.509 certificate could not be verified, possibly because you do not have " - "the CA certificate in your certificate store, or the certificate has expired. " - "Please look at the documentation on how to create local certificate store for a private CA.\n"); - while (1) { - printf("Do you trust the above certificate? (Y/N) "); + printf("Do you trust the above certificate? (Y/T/N) "); answer = fgetc(stdin); if (feof(stdin)) { printf("\nError: Could not read answer from stdin."); - if (instance->settings->CredentialsFromStdin) + if (settings->CredentialsFromStdin) printf(" - Run without parameter \"--from-stdin\" to set trust."); printf("\n"); - return FALSE; + return 0; } - if (answer == 'y' || answer == 'Y') + switch(answer) { - return TRUE; - } - else if (answer == 'n' || answer == 'N') - { - break; + case 'y': + case 'Y': + return 1; + case 't': + case 'T': + return 2; + case 'n': + case 'N': + return 0; + default: + break; } printf("\n"); } - return FALSE; + return 0; +} + +static DWORD wl_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) +{ + printf("Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("The above X.509 certificate could not be verified, possibly because you do not have\n" + "the CA certificate in your certificate store, or the certificate has expired.\n" + "Please look at the documentation on how to create local certificate store for a private CA.\n"); + + return wl_accept_certificate(instance->settings); +} + +static DWORD wl_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint) +{ + printf("!!! Certificate has changed !!!\n"); + printf("\n"); + printf("New Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("\n"); + printf("Old Certificate details:\n"); + printf("\tSubject: %s\n", old_subject); + printf("\tIssuer: %s\n", old_issuer); + printf("\tThumbprint: %s\n", old_fingerprint); + printf("\n"); + printf("The above X.509 certificate does not match the certificate used for previous connections.\n" + "This may indicate that the certificate has been tampered with.\n" + "Please contact the administrator of the RDP server and clarify.\n"); + + return wl_accept_certificate(instance->settings); } static int wlfreerdp_run(freerdp* instance) @@ -263,6 +301,7 @@ int main(int argc, char* argv[]) instance->PostConnect = wl_post_connect; instance->PostDisconnect = wl_post_disconnect; instance->VerifyCertificate = wl_verify_certificate; + instance->VerifyChangedCertificate = wl_verify_changed_certificate; instance->ContextSize = sizeof(wlfContext); instance->ContextNew = wl_context_new; diff --git a/client/Windows/wf_client.c b/client/Windows/wf_client.c index e9af71fc1..eb80961d1 100644 --- a/client/Windows/wf_client.c +++ b/client/Windows/wf_client.c @@ -608,6 +608,31 @@ BOOL wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* return TRUE; } +static DWORD wf_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint) +{ + char answer; + + WLog_ERR(TAG, "!!! Certificate has changed !!!"); + WLog_ERR(TAG, "New Certificate details:"); + WLog_ERR(TAG, "\tSubject: %s", subject); + WLog_ERR(TAG, "\tIssuer: %s", issuer); + WLog_ERR(TAG, "\tThumbprint: %s", fingerprint); + WLog_ERR(TAG, "Old Certificate details:"); + WLog_ERR(TAG, "\tSubject: %s", old_subject); + WLog_ERR(TAG, "\tIssuer: %s", old_issuer); + WLog_ERR(TAG, "\tThumbprint: %s", old_fingerprint); + WLog_ERR(TAG, "The above X.509 certificate does not match the certificate used for previous connections. " + "This may indicate that the certificate has been tampered with." + "Please contact the administrator of the RDP server and clarify."); + + return 0; +} + + static BOOL wf_auto_reconnect(freerdp* instance) { wfContext* wfc = (wfContext *)instance->context; @@ -1081,6 +1106,7 @@ BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context) instance->Authenticate = wf_authenticate; instance->GatewayAuthenticate = wf_gw_authenticate; instance->VerifyCertificate = wf_verify_certificate; + instance->VerifyChangedCertificate = wf_verify_changed_certificate; wfc->instance = instance; wfc->settings = instance->settings; diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index 8a885cf63..cfdd2f7d1 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -1458,55 +1458,108 @@ static BOOL xf_gw_authenticate(freerdp* instance, char** username, char** passwo return xf_authenticate_raw(instance, TRUE, username, password, domain); } +static DWORD xf_accept_certificate(rdpSettings* settings) +{ + char answer; + + while (1) + { + printf("Do you trust the above certificate? (Y/T/N) "); + answer = fgetc(stdin); + + if (feof(stdin)) + { + printf("\nError: Could not read answer from stdin."); + if (settings->CredentialsFromStdin) + printf(" - Run without parameter \"--from-stdin\" to set trust."); + printf("\n"); + return 0; + } + + switch(answer) + { + case 'y': + case 'Y': + return 1; + case 't': + case 'T': + return 2; + case 'n': + case 'N': + return 0; + default: + break; + } + printf("\n"); + } + + return 0; +} + /** Callback set in the rdp_freerdp structure, and used to make a certificate validation * when the connection requires it. * This function will actually be called by tls_verify_certificate(). * @see rdp_client_connect() and tls_connect() * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name * @param subject * @param issuer * @param fingerprint - * @return TRUE if the certificate is trusted. FALSE otherwise. + * @param host_mismatch Indicates the certificate host does not match. + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. */ -BOOL xf_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) +static DWORD xf_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) { - char answer; + printf("Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("The above X.509 certificate could not be verified, possibly because you do not have\n" + "the CA certificate in your certificate store, or the certificate has expired.\n" + "Please look at the documentation on how to create local certificate store for a private CA.\n"); - WLog_INFO(TAG, "Certificate details:"); - WLog_INFO(TAG, "\tSubject: %s", subject); - WLog_INFO(TAG, "\tIssuer: %s", issuer); - WLog_INFO(TAG, "\tThumbprint: %s", fingerprint); - WLog_INFO(TAG, "The above X.509 certificate could not be verified, possibly because you do not have " - "the CA certificate in your certificate store, or the certificate has expired. " - "Please look at the documentation on how to create local certificate store for a private CA."); + return xf_accept_certificate(instance->settings); +} - while (1) - { - WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) "); - answer = fgetc(stdin); +/** Callback set in the rdp_freerdp structure, and used to make a certificate validation + * when a stored certificate does not match the remote counterpart. + * This function will actually be called by tls_verify_certificate(). + * @see rdp_client_connect() and tls_connect() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name + * @param subject + * @param issuer + * @param fingerprint + * @param old_subject + * @param old_issuer + * @param old_fingerprint + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +static DWORD xf_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint) +{ + printf("!!! Certificate has changed !!!\n"); + printf("\n"); + printf("New Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("\n"); + printf("Old Certificate details:\n"); + printf("\tSubject: %s\n", old_subject); + printf("\tIssuer: %s\n", old_issuer); + printf("\tThumbprint: %s\n", old_fingerprint); + printf("\n"); + printf("The above X.509 certificate does not match the certificate used for previous connections.\n" + "This may indicate that the certificate has been tampered with.\n" + "Please contact the administrator of the RDP server and clarify.\n"); - if (feof(stdin)) - { - WLog_INFO(TAG, "Error: Could not read answer from stdin."); - if (instance->settings->CredentialsFromStdin) - WLog_INFO(TAG, " - Run without parameter \"--from-stdin\" to set trust."); - WLog_INFO(TAG, ""); - return FALSE; - } - - if (answer == 'y' || answer == 'Y') - { - return TRUE; - } - else if (answer == 'n' || answer == 'N') - { - break; - } - - WLog_INFO(TAG, ""); - } - - return FALSE; + return xf_accept_certificate(instance->settings); } int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) @@ -1959,6 +2012,7 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->Authenticate = xf_authenticate; instance->GatewayAuthenticate = xf_gw_authenticate; instance->VerifyCertificate = xf_verify_certificate; + instance->VerifyChangedCertificate = xf_verify_changed_certificate; instance->LogonErrorInfo = xf_logon_error_info; settings = instance->settings; diff --git a/client/iOS/FreeRDP/ios_freerdp_ui.h b/client/iOS/FreeRDP/ios_freerdp_ui.h index 9da8748e6..91389ddf9 100644 --- a/client/iOS/FreeRDP/ios_freerdp_ui.h +++ b/client/iOS/FreeRDP/ios_freerdp_ui.h @@ -14,8 +14,15 @@ BOOL ios_ui_end_paint(rdpContext * context); BOOL ios_ui_resize_window(rdpContext * context); BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, char** domain); -BOOL ios_ui_check_certificate(freerdp * instance, char * subject, char * issuer, char * fingerprint); -BOOL ios_ui_check_changed_certificate(freerdp * instance, char * subject, char * issuer, char * new_fingerprint, char * old_fingerprint); +DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name, + const char * subject, const char * issuer, + const char * fingerprint, BOOL host_mismatch); +DWORD ios_ui_check_changed_certificate(freerdp * instance, + const char* common_name, + const char * subject, + const char * issuer, + const char * new_fingerprint, + const char * old_fingerprint); void ios_allocate_display_buffer(mfInfo* mfi); void ios_resize_display_buffer(mfInfo* mfi); diff --git a/client/iOS/FreeRDP/ios_freerdp_ui.m b/client/iOS/FreeRDP/ios_freerdp_ui.m index 191b25ec2..cd17da0bc 100644 --- a/client/iOS/FreeRDP/ios_freerdp_ui.m +++ b/client/iOS/FreeRDP/ios_freerdp_ui.m @@ -63,39 +63,47 @@ BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, c return TRUE; } -BOOL ios_ui_check_certificate(freerdp * instance, char * subject, char * issuer, char * fingerprint) +DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name, + const char * subject, const char * issuer, + const char * fingerprint, BOOL host_mismatch) { - // check whether we accept all certificates - if ([[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"] == YES) - return TRUE; - + // check whether we accept all certificates + if ([[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"] == YES) + return 2; + mfInfo* mfi = MFI_FROM_INSTANCE(instance); NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys: - (subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject", - (issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer", - (fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint", - nil]; - - // request certificate verification UI - [mfi->session performSelectorOnMainThread:@selector(sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES]; - - // wait for UI request to be completed - [[mfi->session uiRequestCompleted] lock]; - [[mfi->session uiRequestCompleted] wait]; - [[mfi->session uiRequestCompleted] unlock]; - + (subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject", + (issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer", + (fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint", + nil]; + + // request certificate verification UI + [mfi->session performSelectorOnMainThread:@selector(sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES]; + + // wait for UI request to be completed + [[mfi->session uiRequestCompleted] lock]; + [[mfi->session uiRequestCompleted] wait]; + [[mfi->session uiRequestCompleted] unlock]; + if (![[params valueForKey:@"result"] boolValue]) { mfi->unwanted = YES; - return FALSE; + return 0; } - - return TRUE; + + return 1; } -BOOL ios_ui_check_changed_certificate(freerdp * instance, char * subject, char * issuer, char * new_fingerprint, char * old_fingerprint) +DWORD ios_ui_check_changed_certificate(freerdp * instance, + const char * common_name, + const char * subject, + const char * issuer, + const char * new_fingerprint, + const char * old_fingerprint) { - return ios_ui_check_certificate(instance, subject, issuer, new_fingerprint); + return ios_ui_check_certificate(instance, common_name, subject, issuer, + new_fingerprint, FALSE); } diff --git a/include/freerdp/freerdp.h b/include/freerdp/freerdp.h index cbc539887..22b2b3502 100644 --- a/include/freerdp/freerdp.h +++ b/include/freerdp/freerdp.h @@ -65,13 +65,55 @@ typedef void (*pContextFree)(freerdp* instance, rdpContext* context); typedef BOOL (*pPreConnect)(freerdp* instance); typedef BOOL (*pPostConnect)(freerdp* instance); typedef void (*pPostDisconnect)(freerdp* instance); -typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain); -typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint); -typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject, - char* issuer, char* new_fingerprint, - char* old_subject, char* old_issuer, - char* old_fingerprint); -typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags); +typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, + char** password, char** domain); + +/** @brief Callback used if user interaction is required to accept + * an unknown certificate. + * + * @param common_name The certificate registered hostname. + * @param subject The common name of the certificate. + * @param issuer The issuer of the certificate. + * @param fingerprint The fingerprint of the certificate. + * @param host_mismatch A flag indicating the certificate + * subject does not match the host connecting to. + * + * @return 1 to accept and store a certificate, 2 to accept + * a certificate only for this session, 0 otherwise. + */ +typedef DWORD (*pVerifyCertificate)(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* fingerprint, + BOOL host_mismatch); + +/** @brief Callback used if user interaction is required to accept + * a changed certificate. + * + * @param common_name The certificate registered hostname. + * @param subject The common name of the new certificate. + * @param issuer The issuer of the new certificate. + * @param fingerprint The fingerprint of the new certificate. + * @param old_subject The common name of the old certificate. + * @param old_issuer The issuer of the new certificate. + * @param old_fingerprint The fingerprint of the old certificate. + * + * @return 1 to accept and store a certificate, 2 to accept + * a certificate only for this session, 0 otherwise. + */ + +typedef DWORD (*pVerifyChangedCertificate)(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* new_fingerprint, + const char* old_subject, + const char* old_issuer, + const char* old_fingerprint); +typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, + int length, const char* hostname, + int port, DWORD flags); typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type); diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index e8627e41e..6546115ef 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -1247,31 +1247,16 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por /* if the certificate is valid and the certificate name matches, verification succeeds */ if (certificate_status && hostname_match) - { - if (common_name) - { - free(common_name); - common_name = NULL; - } - verification_status = TRUE; /* success! */ - } - - /* if the certificate is valid but the certificate name does not match, warn user, do not accept */ - if (certificate_status && !hostname_match) - tls_print_certificate_name_mismatch_error(hostname, port, - common_name, alt_names, - alt_names_count); /* verification could not succeed with OpenSSL, use known_hosts file and prompt user for manual verification */ - - if (!certificate_status) + if (!certificate_status || !hostname_match) { char* issuer; char* subject; char* fingerprint; freerdp* instance = (freerdp*) tls->settings->instance; - BOOL accept_certificate = FALSE; + DWORD accept_certificate = 0; issuer = crypto_cert_issuer(cert->px509); subject = crypto_cert_subject(cert->px509); @@ -1290,19 +1275,23 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por alt_names_count); if (instance->VerifyCertificate) - { - accept_certificate = instance->VerifyCertificate(instance, subject, issuer, fingerprint); - } + accept_certificate = instance->VerifyCertificate(instance, common_name, + subject, issuer, fingerprint, !hostname_match); - if (!accept_certificate) + switch(accept_certificate) { - /* user did not accept, abort and do not add entry in known_hosts file */ - verification_status = FALSE; /* failure! */ - } - else - { - /* user accepted certificate, add entry in known_hosts file */ - verification_status = certificate_data_print(tls->certificate_store, certificate_data); + case 1: + /* user accepted certificate, add entry in known_hosts file */ + verification_status = certificate_data_print(tls->certificate_store, certificate_data); + break; + case 2: + /* user did accept temporaty, do not add to known hosts file */ + verification_status = TRUE; + break; + default: + /* user did not accept, abort and do not add entry in known_hosts file */ + verification_status = FALSE; /* failure! */ + break; } } else if (match == -1) @@ -1324,28 +1313,31 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por if (instance->VerifyChangedCertificate) { accept_certificate = instance->VerifyChangedCertificate( - instance, subject, issuer, + instance, common_name, subject, issuer, fingerprint, old_subject, old_issuer, old_fingerprint); } free(old_fingerprint); - if (!accept_certificate) + switch(accept_certificate) { - /* user did not accept, abort and do not change known_hosts file */ - verification_status = FALSE; /* failure! */ - } - else - { - /* user accepted new certificate, add replace fingerprint for this host in known_hosts file */ - verification_status = certificate_data_replace(tls->certificate_store, certificate_data); + case 1: + /* user accepted certificate, add entry in known_hosts file */ + verification_status = certificate_data_replace(tls->certificate_store, certificate_data); + break; + case 2: + /* user did accept temporaty, do not add to known hosts file */ + verification_status = TRUE; + break; + default: + /* user did not accept, abort and do not add entry in known_hosts file */ + verification_status = FALSE; /* failure! */ + break; } } else if (match == 0) - { verification_status = TRUE; /* success! */ - } free(issuer); free(subject); @@ -1354,9 +1346,7 @@ int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int por certificate_data_free(certificate_data); -#ifndef _WIN32 free(common_name); -#endif if (alt_names) crypto_cert_subject_alt_name_free(alt_names_count, alt_names_lengths, diff --git a/server/shadow/Win/win_rdp.c b/server/shadow/Win/win_rdp.c index d9e0b34bb..b254f2aec 100644 --- a/server/shadow/Win/win_rdp.c +++ b/server/shadow/Win/win_rdp.c @@ -99,9 +99,11 @@ BOOL shw_authenticate(freerdp* instance, char** username, char** password, char* return TRUE; } -BOOL shw_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint) +static DWORD shw_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) { - return TRUE; + return 1; } int shw_verify_x509_certificate(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags) From 0e2208e942048601643b31b9157f98d5755b5b89 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 17 Dec 2015 16:43:49 +0100 Subject: [PATCH 015/128] Fixed warning. --- libfreerdp/crypto/crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index df76070f1..d014ec20c 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -435,7 +435,7 @@ char* crypto_cert_subject_common_name(X509* xcert, int* length) if (*length < 0) return NULL; - common_name = _strdup(common_name_raw); + common_name = _strdup((char*)common_name_raw); OPENSSL_free(common_name_raw); return (char*) common_name; From b35f6658b9e1dd2fe6c5cffd2b7b6208cbe49d73 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 17 Dec 2015 16:43:55 +0100 Subject: [PATCH 016/128] Moved common code from cli clients to client lib. --- client/Wayland/wlfreerdp.c | 84 +-------------- client/X11/xf_client.c | 215 +------------------------------------ client/common/client.c | 214 ++++++++++++++++++++++++++++++++++++ include/freerdp/client.h | 12 +++ 4 files changed, 234 insertions(+), 291 deletions(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 2cc7597da..4aeda18cc 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -172,84 +172,6 @@ static void wl_post_disconnect(freerdp* instance) wlf_DestroyWindow(context, context->window); } -static DWORD wl_accept_certificate(rdpSettings* settings) -{ - char answer; - - while (1) - { - printf("Do you trust the above certificate? (Y/T/N) "); - answer = fgetc(stdin); - - if (feof(stdin)) - { - printf("\nError: Could not read answer from stdin."); - if (settings->CredentialsFromStdin) - printf(" - Run without parameter \"--from-stdin\" to set trust."); - printf("\n"); - return 0; - } - - switch(answer) - { - case 'y': - case 'Y': - return 1; - case 't': - case 'T': - return 2; - case 'n': - case 'N': - return 0; - default: - break; - } - printf("\n"); - } - - return 0; -} - -static DWORD wl_verify_certificate(freerdp* instance, const char* common_name, - const char* subject, const char* issuer, - const char* fingerprint, BOOL host_mismatch) -{ - printf("Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("The above X.509 certificate could not be verified, possibly because you do not have\n" - "the CA certificate in your certificate store, or the certificate has expired.\n" - "Please look at the documentation on how to create local certificate store for a private CA.\n"); - - return wl_accept_certificate(instance->settings); -} - -static DWORD wl_verify_changed_certificate(freerdp* instance, const char* common_name, - const char* subject, const char* issuer, - const char* fingerprint, - const char* old_subject, const char* old_issuer, - const char* old_fingerprint) -{ - printf("!!! Certificate has changed !!!\n"); - printf("\n"); - printf("New Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("\n"); - printf("Old Certificate details:\n"); - printf("\tSubject: %s\n", old_subject); - printf("\tIssuer: %s\n", old_issuer); - printf("\tThumbprint: %s\n", old_fingerprint); - printf("\n"); - printf("The above X.509 certificate does not match the certificate used for previous connections.\n" - "This may indicate that the certificate has been tampered with.\n" - "Please contact the administrator of the RDP server and clarify.\n"); - - return wl_accept_certificate(instance->settings); -} - static int wlfreerdp_run(freerdp* instance) { DWORD count; @@ -300,8 +222,10 @@ int main(int argc, char* argv[]) instance->PreConnect = wl_pre_connect; instance->PostConnect = wl_post_connect; instance->PostDisconnect = wl_post_disconnect; - instance->VerifyCertificate = wl_verify_certificate; - instance->VerifyChangedCertificate = wl_verify_changed_certificate; + instance->Authenticate = client_cli_authenticate; + instance->GatewayAuthenticate = client_cli_gw_authenticate; + instance->VerifyCertificate = client_cli_verify_certificate; + instance->VerifyChangedCertificate = client_cli_verify_changed_certificate; instance->ContextSize = sizeof(wlfContext); instance->ContextNew = wl_context_new; diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c index cfdd2f7d1..baaf7e75b 100644 --- a/client/X11/xf_client.c +++ b/client/X11/xf_client.c @@ -102,8 +102,6 @@ #include #define TAG CLIENT_TAG("x11") -static const size_t password_size = 512; - static int (*_def_error_handler)(Display*, XErrorEvent*); static int _xf_error_handler(Display* d, XErrorEvent* ev); static void xf_check_extensions(xfContext* context); @@ -1357,211 +1355,6 @@ static void xf_post_disconnect(freerdp* instance) xf_keyboard_free(xfc); } -/** Callback set in the rdp_freerdp structure, and used to get the user's password, - * if required to establish the connection. - * This function is actually called in credssp_ntlmssp_client_init() - * @see rdp_server_accept_nego() and rdp_check_fds() - * @param instance - pointer to the rdp_freerdp structure that contains the connection settings - * @param username - unused - * @param password - on return: pointer to a character string that will be filled by the password entered by the user. - * Note that this character string will be allocated inside the function, and needs to be deallocated by the caller - * using free(), even in case this function fails. - * @param domain - unused - * @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details. - */ -static BOOL xf_authenticate_raw(freerdp* instance, BOOL gateway, char** username, - char** password, char** domain) -{ - const char* auth[] = - { - "Username: ", - "Domain: ", - "Password: " - }; - const char* gw[] = - { - "GatewayUsername: ", - "GatewayDomain: ", - "GatewayPassword: " - }; - const char** prompt = (gateway) ? gw : auth; - - if (!username || !password || !domain) - return FALSE; - - if (!*username) - { - size_t username_size = 0; - printf("%s", prompt[0]); - if (getline(username, &username_size, stdin) < 0) - { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); - goto fail; - } - - if (*username) - { - *username = StrSep(username, "\r"); - *username = StrSep(username, "\n"); - } - } - - if (!*domain) - { - size_t domain_size = 0; - printf("%s", prompt[1]); - if (getline(domain, &domain_size, stdin) < 0) - { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); - goto fail; - } - - if (*domain) - { - *domain = StrSep(domain, "\r"); - *domain = StrSep(domain, "\n"); - } - } - - if (!*password) - { - *password = calloc(password_size, sizeof(char)); - if (!*password) - goto fail; - - if (freerdp_passphrase_read(prompt[2], *password, password_size, - instance->settings->CredentialsFromStdin) == NULL) - goto fail; - } - - return TRUE; - -fail: - free(*username); - free(*domain); - free(*password); - - *username = NULL; - *domain = NULL; - *password = NULL; - - return FALSE; -} - -static BOOL xf_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - return xf_authenticate_raw(instance, FALSE, username, password, domain); -} - -static BOOL xf_gw_authenticate(freerdp* instance, char** username, char** password, char** domain) -{ - return xf_authenticate_raw(instance, TRUE, username, password, domain); -} - -static DWORD xf_accept_certificate(rdpSettings* settings) -{ - char answer; - - while (1) - { - printf("Do you trust the above certificate? (Y/T/N) "); - answer = fgetc(stdin); - - if (feof(stdin)) - { - printf("\nError: Could not read answer from stdin."); - if (settings->CredentialsFromStdin) - printf(" - Run without parameter \"--from-stdin\" to set trust."); - printf("\n"); - return 0; - } - - switch(answer) - { - case 'y': - case 'Y': - return 1; - case 't': - case 'T': - return 2; - case 'n': - case 'N': - return 0; - default: - break; - } - printf("\n"); - } - - return 0; -} - -/** Callback set in the rdp_freerdp structure, and used to make a certificate validation - * when the connection requires it. - * This function will actually be called by tls_verify_certificate(). - * @see rdp_client_connect() and tls_connect() - * @param instance - pointer to the rdp_freerdp structure that contains the connection settings - * @param common_name - * @param subject - * @param issuer - * @param fingerprint - * @param host_mismatch Indicates the certificate host does not match. - * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. - */ -static DWORD xf_verify_certificate(freerdp* instance, const char* common_name, - const char* subject, const char* issuer, - const char* fingerprint, BOOL host_mismatch) -{ - printf("Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("The above X.509 certificate could not be verified, possibly because you do not have\n" - "the CA certificate in your certificate store, or the certificate has expired.\n" - "Please look at the documentation on how to create local certificate store for a private CA.\n"); - - return xf_accept_certificate(instance->settings); -} - -/** Callback set in the rdp_freerdp structure, and used to make a certificate validation - * when a stored certificate does not match the remote counterpart. - * This function will actually be called by tls_verify_certificate(). - * @see rdp_client_connect() and tls_connect() - * @param instance - pointer to the rdp_freerdp structure that contains the connection settings - * @param common_name - * @param subject - * @param issuer - * @param fingerprint - * @param old_subject - * @param old_issuer - * @param old_fingerprint - * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. - */ -static DWORD xf_verify_changed_certificate(freerdp* instance, const char* common_name, - const char* subject, const char* issuer, - const char* fingerprint, - const char* old_subject, const char* old_issuer, - const char* old_fingerprint) -{ - printf("!!! Certificate has changed !!!\n"); - printf("\n"); - printf("New Certificate details:\n"); - printf("\tSubject: %s\n", subject); - printf("\tIssuer: %s\n", issuer); - printf("\tThumbprint: %s\n", fingerprint); - printf("\n"); - printf("Old Certificate details:\n"); - printf("\tSubject: %s\n", old_subject); - printf("\tIssuer: %s\n", old_issuer); - printf("\tThumbprint: %s\n", old_fingerprint); - printf("\n"); - printf("The above X.509 certificate does not match the certificate used for previous connections.\n" - "This may indicate that the certificate has been tampered with.\n" - "Please contact the administrator of the RDP server and clarify.\n"); - - return xf_accept_certificate(instance->settings); -} - int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type) { xfContext* xfc = (xfContext*) instance->context; @@ -2009,10 +1802,10 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context) instance->PreConnect = xf_pre_connect; instance->PostConnect = xf_post_connect; instance->PostDisconnect = xf_post_disconnect; - instance->Authenticate = xf_authenticate; - instance->GatewayAuthenticate = xf_gw_authenticate; - instance->VerifyCertificate = xf_verify_certificate; - instance->VerifyChangedCertificate = xf_verify_changed_certificate; + instance->Authenticate = client_cli_authenticate; + instance->GatewayAuthenticate = client_cli_gw_authenticate; + instance->VerifyCertificate = client_cli_verify_certificate; + instance->VerifyChangedCertificate = client_cli_verify_changed_certificate; instance->LogonErrorInfo = xf_logon_error_info; settings = instance->settings; diff --git a/client/common/client.c b/client/common/client.c index 4da191912..3a59d5ab6 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -21,14 +21,21 @@ #include "config.h" #endif +#include +#include + #include #include #include #include +#include #include #include +#include +#define TAG CLIENT_TAG("common") + static BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context) { RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints; @@ -296,3 +303,210 @@ int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const c return 0; } +/** Callback set in the rdp_freerdp structure, and used to get the user's password, + * if required to establish the connection. + * This function is actually called in credssp_ntlmssp_client_init() + * @see rdp_server_accept_nego() and rdp_check_fds() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param username - unused + * @param password - on return: pointer to a character string that will be filled by the password entered by the user. + * Note that this character string will be allocated inside the function, and needs to be deallocated by the caller + * using free(), even in case this function fails. + * @param domain - unused + * @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details. + */ +static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway, char** username, + char** password, char** domain) +{ + static const size_t password_size = 512; + const char* auth[] = + { + "Username: ", + "Domain: ", + "Password: " + }; + const char* gw[] = + { + "GatewayUsername: ", + "GatewayDomain: ", + "GatewayPassword: " + }; + const char** prompt = (gateway) ? gw : auth; + + if (!username || !password || !domain) + return FALSE; + + if (!*username) + { + size_t username_size = 0; + printf("%s", prompt[0]); + if (getline(username, &username_size, stdin) < 0) + { + WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); + goto fail; + } + + if (*username) + { + *username = StrSep(username, "\r"); + *username = StrSep(username, "\n"); + } + } + + if (!*domain) + { + size_t domain_size = 0; + printf("%s", prompt[1]); + if (getline(domain, &domain_size, stdin) < 0) + { + WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); + goto fail; + } + + if (*domain) + { + *domain = StrSep(domain, "\r"); + *domain = StrSep(domain, "\n"); + } + } + + if (!*password) + { + *password = calloc(password_size, sizeof(char)); + if (!*password) + goto fail; + + if (freerdp_passphrase_read(prompt[2], *password, password_size, + instance->settings->CredentialsFromStdin) == NULL) + goto fail; + } + + return TRUE; + +fail: + free(*username); + free(*domain); + free(*password); + + *username = NULL; + *domain = NULL; + *password = NULL; + + return FALSE; +} + +BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + return client_cli_authenticate_raw(instance, FALSE, username, password, domain); +} + +BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + return client_cli_authenticate_raw(instance, TRUE, username, password, domain); +} + +static DWORD client_cli_accept_certificate(rdpSettings* settings) +{ + char answer; + + while (1) + { + printf("Do you trust the above certificate? (Y/T/N) "); + answer = fgetc(stdin); + + if (feof(stdin)) + { + printf("\nError: Could not read answer from stdin."); + if (settings->CredentialsFromStdin) + printf(" - Run without parameter \"--from-stdin\" to set trust."); + printf("\n"); + return 0; + } + + switch(answer) + { + case 'y': + case 'Y': + return 1; + case 't': + case 'T': + return 2; + case 'n': + case 'N': + return 0; + default: + break; + } + printf("\n"); + } + + return 0; +} + +/** Callback set in the rdp_freerdp structure, and used to make a certificate validation + * when the connection requires it. + * This function will actually be called by tls_verify_certificate(). + * @see rdp_client_connect() and tls_connect() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name + * @param subject + * @param issuer + * @param fingerprint + * @param host_mismatch Indicates the certificate host does not match. + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) +{ + printf("Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("The above X.509 certificate could not be verified, possibly because you do not have\n" + "the CA certificate in your certificate store, or the certificate has expired.\n" + "Please look at the documentation on how to create local certificate store for a private CA.\n"); + + return client_cli_accept_certificate(instance->settings); +} + +/** Callback set in the rdp_freerdp structure, and used to make a certificate validation + * when a stored certificate does not match the remote counterpart. + * This function will actually be called by tls_verify_certificate(). + * @see rdp_client_connect() and tls_connect() + * @param instance - pointer to the rdp_freerdp structure that contains the connection settings + * @param common_name + * @param subject + * @param issuer + * @param fingerprint + * @param old_subject + * @param old_issuer + * @param old_fingerprint + * @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise. + */ +DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint) +{ + printf("!!! Certificate has changed !!!\n"); + printf("\n"); + printf("New Certificate details:\n"); + printf("\tSubject: %s\n", subject); + printf("\tIssuer: %s\n", issuer); + printf("\tThumbprint: %s\n", fingerprint); + printf("\n"); + printf("Old Certificate details:\n"); + printf("\tSubject: %s\n", old_subject); + printf("\tIssuer: %s\n", old_issuer); + printf("\tThumbprint: %s\n", old_fingerprint); + printf("\n"); + printf("The above X.509 certificate does not match the certificate used for previous connections.\n" + "This may indicate that the certificate has been tampered with.\n" + "Please contact the administrator of the RDP server and clarify.\n"); + + return client_cli_accept_certificate(instance->settings); +} + + diff --git a/include/freerdp/client.h b/include/freerdp/client.h index 39708c77e..f807b2fc2 100644 --- a/include/freerdp/client.h +++ b/include/freerdp/client.h @@ -94,6 +94,18 @@ FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings* FREERDP_API int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const char* filename); +FREERDP_API BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain); +FREERDP_API BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain); + +FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch); + +FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, + const char* old_subject, const char* old_issuer, + const char* old_fingerprint); #ifdef __cplusplus } #endif From 5e46a6e4be8d33e73aa11c31e441214f9cf4ddc1 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 18 Dec 2015 09:45:44 +0100 Subject: [PATCH 017/128] Replaced getline with custom GetLine. --- client/common/client.c | 8 ++++---- winpr/include/winpr/string.h | 2 ++ winpr/libwinpr/crt/string.c | 37 ++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/client/common/client.c b/client/common/client.c index 3a59d5ab6..95e1a84b8 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -340,9 +340,9 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway, char** { size_t username_size = 0; printf("%s", prompt[0]); - if (getline(username, &username_size, stdin) < 0) + if (GetLine(username, &username_size, stdin) < 0) { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); + WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno); goto fail; } @@ -357,9 +357,9 @@ static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway, char** { size_t domain_size = 0; printf("%s", prompt[1]); - if (getline(domain, &domain_size, stdin) < 0) + if (GetLine(domain, &domain_size, stdin) < 0) { - WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno); + WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno); goto fail; } diff --git a/winpr/include/winpr/string.h b/winpr/include/winpr/string.h index 555d05306..439d71380 100644 --- a/winpr/include/winpr/string.h +++ b/winpr/include/winpr/string.h @@ -189,6 +189,8 @@ WINPR_API char* ConvertLineEndingToCRLF(const char* str, int* size); WINPR_API char* StrSep(char** stringp, const char* delim); +WINPR_API INT64 GetLine(char** lineptr, size_t* size, FILE* stream); + #ifdef __cplusplus } #endif diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c index da9185f80..6bc957a61 100644 --- a/winpr/libwinpr/crt/string.c +++ b/winpr/libwinpr/crt/string.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -481,4 +482,40 @@ char* StrSep(char** stringp, const char* delim) return start; } +INT64 GetLine(char** lineptr, size_t* size, FILE* stream) +{ +#if defined(_WIN32) + char c; + char *n; + size_t step = 32; + size_t used = 0; + if (!lineptr || !size) + { + errno = EINVAL; + return -1; + } + + do + { + if (used + 2 >= *size) + { + *size += step; + n = realloc(*lineptr, *size); + if (!n) + { + return -1; + } + *lineptr = n; + } + c = fgetc(stream); + if (c != EOF) + (*lineptr)[used++] = c; + } while((c != '\n') && (c != '\r') && (c != EOF)); + (*lineptr)[used] = '\0'; + + return used; +#else + return getline(lineptr, size, stream); +#endif +} From 6b406bdcdaee512b62d5af92e9581a8bf0deb839 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 18 Dec 2015 10:36:28 +0100 Subject: [PATCH 018/128] Not building GetLine on android and ios. --- winpr/libwinpr/crt/string.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/winpr/libwinpr/crt/string.c b/winpr/libwinpr/crt/string.c index 6bc957a61..d6f4a1bdf 100644 --- a/winpr/libwinpr/crt/string.c +++ b/winpr/libwinpr/crt/string.c @@ -515,7 +515,9 @@ INT64 GetLine(char** lineptr, size_t* size, FILE* stream) (*lineptr)[used] = '\0'; return used; -#else +#elif !defined(ANDROID) && !defined(IOS) return getline(lineptr, size, stream); +#else + return -1; #endif } From 80d7d639f7405db7e5ea3f54d15e302f7772c351 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 5 Feb 2016 02:32:47 +0100 Subject: [PATCH 019/128] Updated android API. --- .../presentation/SessionActivity.java | 39 ++++++++-- .../freerdpcore/services/LibFreeRDP.java | 31 ++++++-- client/Android/android_freerdp.c | 75 +++++++++++++------ client/Android/android_jni_callback.c | 2 +- 4 files changed, 112 insertions(+), 35 deletions(-) diff --git a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/SessionActivity.java b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/SessionActivity.java index 08bc61395..453a0ba07 100644 --- a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/SessionActivity.java +++ b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/SessionActivity.java @@ -1066,12 +1066,10 @@ public class SessionActivity extends ActionBarActivity implements } @Override - public boolean OnVerifiyCertificate(String subject, String issuer, - String fingerprint) { - + public int OnVerifiyCertificate(String commonName, String subject, String issuer, String fingerprint, boolean mismatch) { // see if global settings says accept all if (GlobalSettings.getAcceptAllCertificates()) - return true; + return 0; // this is where the return code of our dialog will be stored callbackDialogResult = false; @@ -1095,7 +1093,38 @@ public class SessionActivity extends ActionBarActivity implements } catch (InterruptedException e) { } - return callbackDialogResult; + return callbackDialogResult ? 1 : 0; + } + + @Override + public int OnVerifiyChangedCertificate(String commonName, String subject, String issuer, String fingerprint, String oldSubject, String oldIssuer, String oldFingerprint) { + // see if global settings says accept all + if (GlobalSettings.getAcceptAllCertificates()) + return 0; + + // this is where the return code of our dialog will be stored + callbackDialogResult = false; + + // set message + String msg = getResources().getString( + R.string.dlg_msg_verify_certificate); + msg = msg + "\n\nSubject: " + subject + "\nIssuer: " + issuer + + "\nFingerprint: " + fingerprint; + dlgVerifyCertificate.setMessage(msg); + + // start dialog in UI thread + uiHandler.sendMessage(Message.obtain(null, UIHandler.SHOW_DIALOG, + dlgVerifyCertificate)); + + // wait for result + try { + synchronized (dlgVerifyCertificate) { + dlgVerifyCertificate.wait(); + } + } catch (InterruptedException e) { + } + + return callbackDialogResult ? 1 : 0; } @Override diff --git a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java index c07a5d26e..0d77c12ff 100644 --- a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java +++ b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java @@ -89,7 +89,12 @@ public class LibFreeRDP { boolean OnAuthenticate(StringBuilder username, StringBuilder domain, StringBuilder password); - boolean OnVerifiyCertificate(String subject, String issuer, String fingerprint); + int OnVerifiyCertificate(String commonName, String subject, + String issuer, String fingerprint, boolean mismatch); + + int OnVerifiyChangedCertificate(String commonName, String subject, + String issuer, String fingerprint, String oldSubject, + String oldIssuer, String oldFingerprint); void OnGraphicsUpdate(int x, int y, int width, int height); @@ -330,14 +335,30 @@ public class LibFreeRDP { return false; } - private static boolean OnVerifyCertificate(int inst, String subject, String issuer, String fingerprint) { + private static int OnVerifyCertificate(int inst, String commonName, String subject, + String issuer, String fingerprint, boolean + hostMismatch) { SessionState s = GlobalApp.getSession(inst); if (s == null) - return false; + return 0; UIEventListener uiEventListener = s.getUIEventListener(); if (uiEventListener != null) - return uiEventListener.OnVerifiyCertificate(subject, issuer, fingerprint); - return false; + return uiEventListener.OnVerifiyCertificate(commonName, subject, issuer, fingerprint, + hostMismatch); + return 0; + } + + private static int OnVerifyCertificate(int inst, String commonName, String subject, + String issuer, String fingerprint, String oldSubject, + String oldIssuer, String oldFingerprint) { + SessionState s = GlobalApp.getSession(inst); + if (s == null) + return 0; + UIEventListener uiEventListener = s.getUIEventListener(); + if (uiEventListener != null) + return uiEventListener.OnVerifiyChangedCertificate(commonName, subject, issuer, + fingerprint, oldSubject, oldIssuer, oldFingerprint); + return 0; } private static void OnGraphicsUpdate(int inst, int x, int y, int width, int height) { diff --git a/client/Android/android_freerdp.c b/client/Android/android_freerdp.c index 2baf0f4a2..8253f30d7 100644 --- a/client/Android/android_freerdp.c +++ b/client/Android/android_freerdp.c @@ -417,37 +417,64 @@ static BOOL android_authenticate(freerdp* instance, char** username, return ((res == JNI_TRUE) ? TRUE : FALSE); } -static BOOL android_verify_certificate(freerdp* instance, char* subject, - char* issuer, char* fingerprint) +static DWORD android_verify_certificate( + freerdp* instance, const char* common_name, + const char* subject, const char* issuer, + const char* fingerprint, BOOL host_mismatch) { - JNIEnv* env; - jboolean attached = jni_attach_thread(&env); - jstring jstr1 = (*env)->NewStringUTF(env, subject); - jstring jstr2 = (*env)->NewStringUTF(env, issuer); - jstring jstr3 = (*env)->NewStringUTF(env, fingerprint); - jboolean res; + WLog_DBG(TAG, "Certificate details:"); + WLog_DBG(TAG, "\tSubject: %s", subject); + WLog_DBG(TAG, "\tIssuer: %s", issuer); + WLog_DBG(TAG, "\tThumbprint: %s", fingerprint); + WLog_DBG(TAG, "The above X.509 certificate could not be verified, possibly because you do not have " + "the CA certificate in your certificate store, or the certificate has expired." + "Please look at the documentation on how to create local certificate store for a private CA.\n"); - res = freerdp_callback_bool_result( - "OnVerifyCertificate", - "(ILjava/lang/String;" - "Ljava/lang/String;" - "Ljava/lang/String;)Z", - instance, jstr1, jstr2, jstr3); + JNIEnv* env; + jboolean attached = jni_attach_thread(&env); + jstring jstr0 = (*env)->NewStringUTF(env, common_name); + jstring jstr1 = (*env)->NewStringUTF(env, subject); + jstring jstr2 = (*env)->NewStringUTF(env, issuer); + jstring jstr3 = (*env)->NewStringUTF(env, fingerprint); - if (attached == JNI_TRUE) - jni_detach_thread(); + jint res = freerdp_callback_int_result("OnVerifyCertificate", + "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I", + instance, jstr0, jstr1, jstr2, jstr3, host_mismatch); - return ((res == JNI_TRUE) ? TRUE : FALSE); + if (attached == JNI_TRUE) + jni_detach_thread(); + + return res; } -static BOOL android_verify_changed_certificate( - freerdp* instance, char* subject, char* issuer, - char* new_fingerprint, char* old_subject, - char* old_issuer, char* old_fingerprint) +static DWORD android_verify_changed_certificate(freerdp* instance, + const char* common_name, + const char* subject, + const char* issuer, + const char* new_fingerprint, + const char* old_subject, + const char* old_issuer, + const char* old_fingerprint) { - return android_verify_certificate( - instance, subject, issuer, - new_fingerprint); + JNIEnv* env; + jboolean attached = jni_attach_thread(&env); + jstring jstr0 = (*env)->NewStringUTF(env, common_name); + jstring jstr1 = (*env)->NewStringUTF(env, subject); + jstring jstr2 = (*env)->NewStringUTF(env, issuer); + jstring jstr3 = (*env)->NewStringUTF(env, new_fingerprint); + jstring jstr4 = (*env)->NewStringUTF(env, old_subject); + jstring jstr5 = (*env)->NewStringUTF(env, old_issuer); + jstring jstr6 = (*env)->NewStringUTF(env, old_fingerprint); + + jint res = freerdp_callback_int_result("OnVerifyChangedCertificate", + "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;" + "Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I", + instance, jstr0, jstr1, jstr2, jstr3, jstr4, jstr5, jstr6); + + if (attached == JNI_TRUE) + jni_detach_thread(); + + return res; } static void* jni_input_thread(void* arg) diff --git a/client/Android/android_jni_callback.c b/client/Android/android_jni_callback.c index d103b80e2..64985d600 100644 --- a/client/Android/android_jni_callback.c +++ b/client/Android/android_jni_callback.c @@ -181,7 +181,7 @@ jint java_callback_int(jobject obj, const char * callback, const char* signature jint res = -1; JNIEnv *env; - DEBUG_ANDROID("java_callback: %s (%s)", callback, signature); + WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature); attached = jni_attach_thread(&env); From f4568295e9878ac159d92f5efc4789d6b68d42ca Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 5 Feb 2016 11:52:07 +0100 Subject: [PATCH 020/128] Fixed API for old openssl versions < 1.0.0 --- libfreerdp/crypto/tls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c index a77f7f130..458f7f9fc 100644 --- a/libfreerdp/crypto/tls.c +++ b/libfreerdp/crypto/tls.c @@ -589,7 +589,11 @@ out_free: return NULL; } +#if OPENSSL_VERSION_NUMBER >= 0x010000000L static BOOL tls_prepare(rdpTls* tls, BIO* underlying, const SSL_METHOD* method, int options, BOOL clientMode) +#else +static BOOL tls_prepare(rdpTls* tls, BIO* underlying, SSL_METHOD* method, int options, BOOL clientMode) +#endif { rdpSettings* settings = tls->settings; From 1f6ba7963c228d0ad7bed3c674d251207dc7643f Mon Sep 17 00:00:00 2001 From: Isaac Richter Date: Wed, 4 Mar 2015 09:37:25 -0500 Subject: [PATCH 021/128] Enable display scaling in client --- client/common/cmdline.c | 55 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 756ae1f3a..b1f64ee0a 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -175,6 +175,12 @@ static COMMAND_LINE_ARGUMENT_A args[] = { "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL, -1, NULL, "print the build configuration" }, { "log-level", COMMAND_LINE_VALUE_REQUIRED, "[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]", NULL, NULL, -1, NULL, "Set the default log level" }, { "log-filters", COMMAND_LINE_VALUE_REQUIRED, ":[, :][, ...]]", NULL, NULL, -1, NULL, "Set logger filters" }, + { "pwidth", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" }, + { "pheight", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Physical height of display (in millimeters)" }, + { "orientation", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "Orientation of display in degrees (0, 90, 180, 270)" }, + { "scale", COMMAND_LINE_VALUE_REQUIRED, "", "100", NULL, -1, NULL, "Scaling factor of the display (value of 100, 140, or 180)" }, + { "scale-desktop", COMMAND_LINE_VALUE_REQUIRED, "", "100", NULL, -1, NULL, "Scaling factor for desktop applications (value between 100 and 500)" }, + { "scale-device", COMMAND_LINE_VALUE_REQUIRED, "", "100", NULL, -1, NULL, "Scaling factor for app store applications (100, 140, or 180)" }, { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; @@ -2289,6 +2295,55 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, if (!(settings->RemoteAssistancePassword = _strdup(arg->Value))) return COMMAND_LINE_ERROR_MEMORY; } + CommandLineSwitchCase(arg, "pwidth") + { + settings->DesktopPhysicalWidth = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "pheight") + { + settings->DesktopPhysicalHeight = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "orientation") + { + settings->DesktopOrientation = atoi(arg->Value); + } + CommandLineSwitchCase(arg, "scale") + { + int scaleFactor = atoi(arg->Value); + if (scaleFactor == 100 || scaleFactor == 140 || scaleFactor == 180) { + settings->DesktopScaleFactor = scaleFactor; + settings->DeviceScaleFactor = scaleFactor; + } else { + WLog_ERR(TAG, "scale: invalid scale factor (%d)", scaleFactor); + return COMMAND_LINE_ERROR; + } + } + CommandLineSwitchCase(arg, "scale-desktop") + { + int desktopScaleFactor = atoi(arg->Value); + if (desktopScaleFactor >= 100 && desktopScaleFactor <= 500) + { + settings->DesktopScaleFactor = desktopScaleFactor; + } + else + { + WLog_ERR(TAG, "scale: invalid desktop scale factor (%d)", desktopScaleFactor); + return COMMAND_LINE_ERROR; + } + } + CommandLineSwitchCase(arg, "scale-device") + { + int deviceScaleFactor = atoi(arg->Value); + if (deviceScaleFactor == 100 || deviceScaleFactor == 140 || deviceScaleFactor == 180) + { + settings->DeviceScaleFactor = deviceScaleFactor; + } + else + { + WLog_ERR(TAG, "scale: invalid device scale factor (%d)", deviceScaleFactor); + return COMMAND_LINE_ERROR; + } + } CommandLineSwitchDefault(arg) { } From d67614a3e60117e34d735d89272327babfc78904 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 8 Feb 2016 14:36:31 +0100 Subject: [PATCH 022/128] Reading unicode from command line. --- client/Windows/cli/wfreerdp.c | 95 +++++++++++++++++++++-------------- 1 file changed, 58 insertions(+), 37 deletions(-) diff --git a/client/Windows/cli/wfreerdp.c b/client/Windows/cli/wfreerdp.c index a9b3c1730..b9a8a54ca 100644 --- a/client/Windows/cli/wfreerdp.c +++ b/client/Windows/cli/wfreerdp.c @@ -40,9 +40,10 @@ #include "wf_client.h" +#include + INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { - int index; int status; HANDLE thread; wfContext* wfc; @@ -50,7 +51,11 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine rdpContext* context; rdpSettings* settings; RDP_CLIENT_ENTRY_POINTS clientEntryPoints; - int ret = 0; + int ret = 1; + int argc = 0, i; + LPWSTR* args; + LPWSTR cmd; + char** argv; ZeroMemory(&clientEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS)); clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS); @@ -59,56 +64,72 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine RdpClientEntry(&clientEntryPoints); context = freerdp_client_context_new(&clientEntryPoints); + if (!context) + return -1; + + cmd = GetCommandLineW(); + if (!cmd) + goto out; + + args = CommandLineToArgvW(cmd, &argc); + if (!args) + goto out; + + argv = calloc(argc, sizeof(char*)); + if (!argv) + goto out; + + for (i=0; isettings; wfc = (wfContext*) context; - - settings->SoftwareGdi = TRUE; - - context->argc = __argc; - context->argv = (char**) malloc(sizeof(char*) * __argc); - if (!context->argv) - { - ret = 1; + if (!settings || !wfc) goto out; - } - for (index = 0; index < context->argc; index++) - { - context->argv[index] = _strdup(__argv[index]); - if (!context->argv[index]) - { - ret = 1; - for (--index; index >= 0; --index) - free(context->argv[index]); - free(context->argv); - context->argv = NULL; - goto out; - } - - } - - status = freerdp_client_settings_parse_command_line(settings, context->argc, context->argv, FALSE); + status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); + if (status) + goto out; status = freerdp_client_settings_command_line_status_print(settings, status, context->argc, context->argv); - if (status) - { - freerdp_client_context_free(context); - return 0; - } + goto out; - freerdp_client_start(context); + if (freerdp_client_start(context) != 0) + goto out; thread = freerdp_client_get_thread(context); + if (thread) + { + if (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0) + { + GetExitCodeThread(thread, &dwExitCode); + ret = dwExitCode; + } + } - WaitForSingleObject(thread, INFINITE); + if (freerdp_client_stop(context) != 0) + goto out; - GetExitCodeThread(thread, &dwExitCode); - - freerdp_client_stop(context); out: freerdp_client_context_free(context); + if (argv) + { + for (i=0; i Date: Tue, 9 Feb 2016 09:36:00 +0100 Subject: [PATCH 023/128] Printing help on invalid command line again. --- client/Windows/cli/wfreerdp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/Windows/cli/wfreerdp.c b/client/Windows/cli/wfreerdp.c index b9a8a54ca..dd9ea55fa 100644 --- a/client/Windows/cli/wfreerdp.c +++ b/client/Windows/cli/wfreerdp.c @@ -97,11 +97,10 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE); if (status) + { + freerdp_client_settings_command_line_status_print(settings, status, argc, argv); goto out; - - status = freerdp_client_settings_command_line_status_print(settings, status, context->argc, context->argv); - if (status) - goto out; + } if (freerdp_client_start(context) != 0) goto out; From 2178245bac2635ba8b06d3b8a6b9d9c0f645c6aa Mon Sep 17 00:00:00 2001 From: pxx02134 Date: Thu, 11 Feb 2016 12:21:11 +0900 Subject: [PATCH 024/128] Update BookmarkDB.java There seems to be two commas forgot. --- .../java/com/freerdp/freerdpcore/services/BookmarkDB.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/BookmarkDB.java b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/BookmarkDB.java index 7796f440a..fddee9de3 100644 --- a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/BookmarkDB.java +++ b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/BookmarkDB.java @@ -76,8 +76,8 @@ public class BookmarkDB extends SQLiteOpenHelper { String sqlInsertDefaultPerfFlags = "INSERT INTO tbl_performance_flags (" + "perf_remotefx, " - + "perf_gfx" - + "perf_gfx_h264" + + "perf_gfx, " + + "perf_gfx_h264, " + "perf_wallpaper, " + "perf_theming, " + "perf_full_window_drag, " From 2bf525d20bb5b5d3d877cc645bf11801b2ff5e40 Mon Sep 17 00:00:00 2001 From: pxx02134 Date: Thu, 11 Feb 2016 12:24:47 +0900 Subject: [PATCH 025/128] Update AndroidManifest.xml ACCESS_NETWORK_STATE statement duplicated. It cause warnings while building. --- client/Android/Studio/freeRDPCore/src/main/AndroidManifest.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/client/Android/Studio/freeRDPCore/src/main/AndroidManifest.xml b/client/Android/Studio/freeRDPCore/src/main/AndroidManifest.xml index cebe55dfe..7860018ae 100644 --- a/client/Android/Studio/freeRDPCore/src/main/AndroidManifest.xml +++ b/client/Android/Studio/freeRDPCore/src/main/AndroidManifest.xml @@ -16,7 +16,6 @@ - Date: Thu, 11 Feb 2016 21:40:50 +0100 Subject: [PATCH 026/128] Several fixes for keyboard type 7 (japanese) --- winpr/include/winpr/input.h | 49 ++++++++++++++++--------------- winpr/libwinpr/input/keycode.c | 4 +-- winpr/libwinpr/input/virtualkey.c | 9 +++--- 3 files changed, 32 insertions(+), 30 deletions(-) diff --git a/winpr/include/winpr/input.h b/winpr/include/winpr/input.h index 6779f30fa..36918847f 100644 --- a/winpr/include/winpr/input.h +++ b/winpr/include/winpr/input.h @@ -80,8 +80,9 @@ #define VK_HANJA 0x19 /* IME Hanja mode */ #define VK_KANJI 0x19 /* IME Kanji mode */ -/* 0x1A is undefined */ +/* 0x1A is undefined, use it for missing Hiragana/Katakana Toggle */ +#define VK_HKTG 0x1A /* Hiragana/Katakana toggle */ #define VK_ESCAPE 0x1B /* ESC key */ #define VK_CONVERT 0x1C /* IME convert */ #define VK_NONCONVERT 0x1D /* IME nonconvert */ @@ -555,7 +556,7 @@ #define KBD7_T0A VK_KEY_9 #define KBD7_T0B VK_KEY_0 #define KBD7_T0C VK_OEM_MINUS -#define KBD7_T0D VK_OEM_7 /* NE */ +#define KBD7_T0D VK_OEM_PLUS #define KBD7_T0E VK_BACK #define KBD7_T0F VK_TAB #define KBD7_T10 VK_KEY_Q @@ -581,8 +582,8 @@ #define KBD7_T24 VK_KEY_J #define KBD7_T25 VK_KEY_K #define KBD7_T26 VK_KEY_L -#define KBD7_T27 VK_OEM_PLUS /* NE */ -#define KBD7_T28 VK_OEM_1 /* NE */ +#define KBD7_T27 VK_OEM_1 +#define KBD7_T28 VK_OEM_7 #define KBD7_T29 VK_OEM_3 /* NE */ #define KBD7_T2A VK_LSHIFT #define KBD7_T2B VK_OEM_5 /* NE */ @@ -600,7 +601,7 @@ #define KBD7_T37 VK_MULTIPLY #define KBD7_T38 VK_LMENU #define KBD7_T39 VK_SPACE -#define KBD7_T3A VK_DBE_ALPHANUMERIC /* NE */ +#define KBD7_T3A VK_CAPITAL #define KBD7_T3B VK_F1 #define KBD7_T3C VK_F2 #define KBD7_T3D VK_F3 @@ -613,22 +614,22 @@ #define KBD7_T44 VK_F10 #define KBD7_T45 VK_NUMLOCK #define KBD7_T46 VK_SCROLL -#define KBD7_T47 VK_HOME -#define KBD7_T48 VK_UP -#define KBD7_T49 VK_PRIOR +#define KBD7_T47 VK_NUMPAD7 /* VK_HOME */ +#define KBD7_T48 VK_NUMPAD8 /* VK_UP */ +#define KBD7_T49 VK_NUMPAD9 /* VK_PRIOR */ #define KBD7_T4A VK_SUBTRACT -#define KBD7_T4B VK_LEFT -#define KBD7_T4C VK_CLEAR -#define KBD7_T4D VK_RIGHT +#define KBD7_T4B VK_NUMPAD4 /* VK_LEFT */ +#define KBD7_T4C VK_NUMPAD5 /* VK_CLEAR */ +#define KBD7_T4D VK_NUMPAD6 /* VK_RIGHT */ #define KBD7_T4E VK_ADD -#define KBD7_T4F VK_END -#define KBD7_T50 VK_DOWN -#define KBD7_T51 VK_NEXT -#define KBD7_T52 VK_INSERT -#define KBD7_T53 VK_DELETE +#define KBD7_T4F VK_NUMPAD1 /* VK_END */ +#define KBD7_T50 VK_NUMPAD2 /* VK_DOWN */ +#define KBD7_T51 VK_NUMPAD3 /* VK_NEXT */ +#define KBD7_T52 VK_NUMPAD0 /* VK_INSERT */ +#define KBD7_T53 VK_DECIMAL /* VK_DELETE */ #define KBD7_T54 VK_SNAPSHOT #define KBD7_T55 VK_NONE -#define KBD7_T56 VK_NONE /* NE */ +#define KBD7_T56 VK_OEM_102 #define KBD7_T57 VK_F11 #define KBD7_T58 VK_F12 #define KBD7_T59 VK_CLEAR @@ -654,27 +655,27 @@ #define KBD7_T6D VK_F22 #define KBD7_T6E VK_F23 #define KBD7_T6F VK_NONE /* NE */ -#define KBD7_T70 VK_DBE_KATAKANA /* NE */ +#define KBD7_T70 VK_HKTG /* NE */ #define KBD7_T71 VK_NONE /* NE */ #define KBD7_T72 VK_NONE -#define KBD7_T73 VK_OEM_102 /* NE */ +#define KBD7_T73 VK_ABNT_C1 #define KBD7_T74 VK_NONE #define KBD7_T75 VK_NONE #define KBD7_T76 VK_F24 -#define KBD7_T77 VK_DBE_SBCSCHAR /* NE */ +#define KBD7_T77 VK_NONE #define KBD7_T78 VK_NONE #define KBD7_T79 VK_CONVERT /* NE */ #define KBD7_T7A VK_NONE #define KBD7_T7B VK_NONCONVERT /* NE */ #define KBD7_T7C VK_TAB -#define KBD7_T7D VK_NONE /* NE */ +#define KBD7_T7D VK_OEM_8 #define KBD7_T7E VK_ABNT_C2 #define KBD7_T7F VK_OEM_PA2 #define KBD7_X10 VK_MEDIA_PREV_TRACK #define KBD7_X19 VK_MEDIA_NEXT_TRACK #define KBD7_X1C VK_RETURN -#define KBD7_X1D VK_RCONTROL /* NE */ +#define KBD7_X1D VK_RCONTROL #define KBD7_X20 VK_VOLUME_MUTE #define KBD7_X21 VK_LAUNCH_APP2 #define KBD7_X22 VK_MEDIA_PLAY_PAUSE @@ -682,10 +683,10 @@ #define KBD7_X2E VK_VOLUME_DOWN #define KBD7_X30 VK_VOLUME_UP #define KBD7_X32 VK_BROWSER_HOME -#define KBD7_X33 VK_OEM_8 /* NE */ +#define KBD7_X33 VK_NONE #define KBD7_X35 VK_DIVIDE #define KBD7_X37 VK_SNAPSHOT -#define KBD7_X38 VK_DBE_HIRAGANA /* NE */ +#define KBD7_X38 VK_RMENU #define KBD7_X42 VK_NONE #define KBD7_X43 VK_NONE #define KBD7_X44 VK_NONE diff --git a/winpr/libwinpr/input/keycode.c b/winpr/libwinpr/input/keycode.c index 3d445cbc4..1c628b2ff 100644 --- a/winpr/libwinpr/input/keycode.c +++ b/winpr/libwinpr/input/keycode.c @@ -405,7 +405,7 @@ DWORD KEYCODE_TO_VKCODE_EVDEV[256] = VK_DBE_KATAKANA, /* 98 */ VK_DBE_HIRAGANA, /* 99 */ VK_CONVERT, /* 100 */ - VK_DBE_HIRAGANA, /* 101 */ + VK_HKTG, /* 101 */ VK_NONCONVERT, /* 102 */ 0, /* 103 */ VK_RETURN | KBDEXT, /* 104 */ @@ -436,7 +436,7 @@ DWORD KEYCODE_TO_VKCODE_EVDEV[256] = VK_ABNT_C2, /* KEY_KPCOMMA 129 */ VK_HANGUL, /* 130 */ VK_HANJA, /* 131 */ - 0, /* 132 */ + VK_OEM_8, /* 132 */ VK_LWIN | KBDEXT, /* 133 */ VK_RWIN | KBDEXT, /* 134 */ VK_APPS | KBDEXT, /* 135 */ diff --git a/winpr/libwinpr/input/virtualkey.c b/winpr/libwinpr/input/virtualkey.c index 64f71f056..94d20fd4c 100644 --- a/winpr/libwinpr/input/virtualkey.c +++ b/winpr/libwinpr/input/virtualkey.c @@ -64,7 +64,7 @@ static const VIRTUAL_KEY_CODE VIRTUAL_KEY_CODE_TABLE[256] = { VK_JUNJA, "VK_JUNJA" }, { VK_FINAL, "VK_FINAL" }, { VK_KANJI, "VK_KANJI" }, /* also VK_HANJA */ - { 0, NULL }, + { VK_HKTG, "VK_HKTG" }, { VK_ESCAPE, "VK_ESCAPE" }, { VK_CONVERT, "VK_CONVERT" }, { VK_NONCONVERT, "VK_NONCONVERT" }, @@ -417,7 +417,7 @@ XKB_KEYNAME XKB_KEYNAME_TABLE[] = { "HENK", VK_CONVERT }, { "MUHE", VK_NONCONVERT }, - { "HKTG", VK_DBE_KATAKANA }, + { "HKTG", VK_HKTG }, // { "AE13", VK_BACKSLASH_JP }, // JP // { "LVL3", 0x54} @@ -425,9 +425,10 @@ XKB_KEYNAME XKB_KEYNAME_TABLE[] = char* GetVirtualKeyName(DWORD vkcode) { - char* vkname; + char* vkname = NULL; - vkname = (char*) VIRTUAL_KEY_CODE_TABLE[vkcode].name; + if (vkcode < ARRAYSIZE(VIRTUAL_KEY_CODE_TABLE)) + vkname = (char*) VIRTUAL_KEY_CODE_TABLE[vkcode].name; if (!vkname) vkname = "VK_NONE"; From d68e58a9dc9b515b521f6354c0be71de36ca4e48 Mon Sep 17 00:00:00 2001 From: Nathan Kidd Date: Thu, 11 Feb 2016 19:34:48 -0500 Subject: [PATCH 027/128] libfreerdp-codec: Make region16_rects() handle NULL nbRects Now matches header documentation. Also cleans up related doc grammar. --- include/freerdp/codec/region.h | 6 +++--- libfreerdp/codec/region.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/freerdp/codec/region.h b/include/freerdp/codec/region.h index bced79140..18b947c2c 100644 --- a/include/freerdp/codec/region.h +++ b/include/freerdp/codec/region.h @@ -73,10 +73,10 @@ FREERDP_API void region16_init(REGION16 *region); /** @return the number of rectangles of this region16 */ FREERDP_API int region16_n_rects(const REGION16 *region); -/** returns a pointer on rectangles and the number of rectangles in this region. - * nbRect can be set to NULL if not interested by the numnber of rectangles. +/** returns a pointer to rectangles and the number of rectangles in this region. + * nbRects can be set to NULL if not interested in the number of rectangles. * @param region the input region - * @param nbRects a pointer that will be filled with the number of rectangles + * @param nbRects if non-NULL returns the number of rectangles * @return a pointer on the rectangles */ FREERDP_API const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects); diff --git a/libfreerdp/codec/region.c b/libfreerdp/codec/region.c index be023b5d7..b3f32af76 100644 --- a/libfreerdp/codec/region.c +++ b/libfreerdp/codec/region.c @@ -94,17 +94,17 @@ const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects) REGION16_DATA *data; assert(region); - assert(region->data); data = region->data; if (!data) { if (nbRects) *nbRects = 0; - return 0; + return NULL; } - *nbRects = data->nbRects; + if (nbRects) + *nbRects = data->nbRects; return (RECTANGLE_16 *)(data + 1); } From 12bd0ec8232b83cd82c27967eec0b0b35a61b591 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 16 Feb 2016 17:39:22 +0100 Subject: [PATCH 028/128] winpr: BUMP the API version to 1.2 This is required that the exported cmake find module can be differentiated from the "old" one. This allows it to have multiple winpr API version installed in parallel. find_package should now be used with an explicit version number set like: find_package(WinPR 1.2 REQUIRED) --- winpr/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index d3bb446fb..0bf1443f9 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -49,7 +49,7 @@ include(CMakePackageConfigHelpers) # Soname versioning set(WINPR_VERSION_MAJOR "1") -set(WINPR_VERSION_MINOR "1") +set(WINPR_VERSION_MINOR "2") set(WINPR_VERSION_REVISION "0") set(WINPR_VERSION "${WINPR_VERSION_MAJOR}.${WINPR_VERSION_MINOR}.${WINPR_VERSION_REVISION}") set(WINPR_VERSION_FULL "${WINPR_VERSION}") From 60fed9d574057f9bea2161e5b38273d4dded5f8b Mon Sep 17 00:00:00 2001 From: David FORT Date: Wed, 3 Feb 2016 10:26:59 +0100 Subject: [PATCH 029/128] Mutualize definitions for the printer channel --- channels/printer/client/printer_main.c | 2 ++ channels/printer/client/printer_main.h | 13 --------- channels/printer/printer.h | 37 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 13 deletions(-) create mode 100644 channels/printer/printer.h diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 561c253f7..fce501a18 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -36,6 +36,8 @@ #include +#include "../printer.h" + #ifdef WITH_CUPS #include "printer_cups.h" #endif diff --git a/channels/printer/client/printer_main.h b/channels/printer/client/printer_main.h index 8a2c85082..3faa3ae7c 100644 --- a/channels/printer/client/printer_main.h +++ b/channels/printer/client/printer_main.h @@ -24,19 +24,6 @@ #include -/* SERVER_PRINTER_CACHE_EVENT.cachedata */ -#define RDPDR_ADD_PRINTER_EVENT 0x00000001 -#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 -#define RDPDR_DELETE_PRINTER_EVENT 0x00000003 -#define RDPDR_RENAME_PRINTER_EVENT 0x00000004 - -/* DR_PRN_DEVICE_ANNOUNCE.Flags */ -#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 - typedef struct rdp_printer_driver rdpPrinterDriver; typedef struct rdp_printer rdpPrinter; typedef struct rdp_print_job rdpPrintJob; diff --git a/channels/printer/printer.h b/channels/printer/printer.h new file mode 100644 index 000000000..237313009 --- /dev/null +++ b/channels/printer/printer.h @@ -0,0 +1,37 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Definition for the printer channel + * + * Copyright 2016 David Fort + * + * 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 __CHANNELS_PRINTER_PRINTER_H_ +#define __CHANNELS_PRINTER_PRINTER_H_ + +/* SERVER_PRINTER_CACHE_EVENT.cachedata */ +#define RDPDR_ADD_PRINTER_EVENT 0x00000001 +#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 +#define RDPDR_DELETE_PRINTER_EVENT 0x00000003 +#define RDPDR_RENAME_PRINTER_EVENT 0x00000004 + +/* DR_PRN_DEVICE_ANNOUNCE.Flags */ +#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 + + +#endif /* __CHANNELS_PRINTER_PRINTER_H_ */ From a53cb8190bdd914980870f5c48a1ec0cca09c14e Mon Sep 17 00:00:00 2001 From: David FORT Date: Thu, 11 Feb 2016 22:45:30 +0100 Subject: [PATCH 030/128] Added missing checks --- libfreerdp/core/rdp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 2675a22f5..942bb62f7 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -671,8 +671,7 @@ BOOL rdp_recv_set_error_info_data_pdu(rdpRdp* rdp, wStream* s) return FALSE; Stream_Read_UINT32(s, errorInfo); /* errorInfo (4 bytes) */ - rdp_set_error_info(rdp, errorInfo); - return TRUE; + return rdp_set_error_info(rdp, errorInfo); } BOOL rdp_recv_server_auto_reconnect_status_pdu(rdpRdp* rdp, wStream* s) @@ -1415,6 +1414,8 @@ BOOL rdp_send_error_info(rdpRdp* rdp) return TRUE; s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; Stream_Write_UINT32(s, rdp->errorInfo); /* error id (4 bytes) */ From 1b2b1c4ac14ac43f4e475488763d8659bd934eb6 Mon Sep 17 00:00:00 2001 From: David FORT Date: Thu, 18 Feb 2016 14:19:36 +0100 Subject: [PATCH 031/128] Add support for saveSessionInfo PDU This patch adds some callbacks so that the client can have access to the informations stored in this packet. Server-side implementation is also there, so that a server can send these informations to the client. --- include/freerdp/session.h | 48 +++++++ include/freerdp/update.h | 5 +- libfreerdp/core/info.c | 280 ++++++++++++++++++++++++++++++++++---- libfreerdp/core/info.h | 20 +-- libfreerdp/core/rdp.c | 3 +- libfreerdp/core/update.c | 3 + 6 files changed, 315 insertions(+), 44 deletions(-) create mode 100644 include/freerdp/session.h diff --git a/include/freerdp/session.h b/include/freerdp/session.h new file mode 100644 index 000000000..3d81f4a7c --- /dev/null +++ b/include/freerdp/session.h @@ -0,0 +1,48 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Client Session Info + * + * Copyright 2016 David FORT + * + * 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 __FREERDP_SESSION_H__ +#define __FREERDP_SESSION_H__ + +#include + +/* Logon Information Types */ +#define INFO_TYPE_LOGON 0x00000000 +#define INFO_TYPE_LOGON_LONG 0x00000001 +#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 +#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 + +struct rdp_logon_info { + UINT32 sessionId; + char *username; + char *domain; +}; +typedef struct rdp_logon_info logon_info; + +struct rdp_logon_info_ex { + BOOL haveCookie; + UINT32 LogonId; + BYTE ArcRandomBits[16]; + + BOOL haveErrorInfo; + UINT32 ErrorNotificationType; + UINT32 ErrorNotificationData; +}; +typedef struct rdp_logon_info_ex logon_info_ex; + +#endif /* __FREERDP_SESSION_H__ */ diff --git a/include/freerdp/update.h b/include/freerdp/update.h index 16829b167..3847d7ab3 100644 --- a/include/freerdp/update.h +++ b/include/freerdp/update.h @@ -156,6 +156,8 @@ typedef BOOL (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* s typedef BOOL (*pSurfaceFrameBits)(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId); typedef BOOL (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId); +typedef BOOL (*pSaveSessionInfo)(rdpContext *context, UINT32 type, void *data); + struct rdp_update { rdpContext* context; /* 0 */ @@ -189,7 +191,8 @@ struct rdp_update pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */ pSurfaceFrameBits SurfaceFrameBits; /* 67 */ pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */ - UINT32 paddingE[80 - 69]; /* 69 */ + pSaveSessionInfo SaveSessionInfo; /* 69 */ + UINT32 paddingE[80 - 70]; /* 70 */ /* internal */ diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 6fbff79da..1c12303c0 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "timezone.h" @@ -90,7 +91,7 @@ BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) * @param settings settings */ -BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) +BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s, logon_info_ex *info) { BYTE* p; ARC_SC_PRIVATE_PACKET* autoReconnectCookie; @@ -102,16 +103,16 @@ BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) return FALSE; Stream_Read_UINT32(s, autoReconnectCookie->cbLen); /* cbLen (4 bytes) */ - Stream_Read_UINT32(s, autoReconnectCookie->version); /* Version (4 bytes) */ - Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ - Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* ArcRandomBits (16 bytes) */ - if (autoReconnectCookie->cbLen != 28) { WLog_ERR(TAG, "ServerAutoReconnectCookie.cbLen != 28"); return FALSE; } + Stream_Read_UINT32(s, autoReconnectCookie->version); /* Version (4 bytes) */ + Stream_Read_UINT32(s, autoReconnectCookie->logonId); /* LogonId (4 bytes) */ + Stream_Read(s, autoReconnectCookie->arcRandomBits, 16); /* ArcRandomBits (16 bytes) */ + p = autoReconnectCookie->arcRandomBits; WLog_DBG(TAG, "ServerAutoReconnectCookie: Version: %d LogonId: %d SecurityVerifier: " @@ -120,6 +121,9 @@ BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s) p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15]); + info->LogonId = autoReconnectCookie->logonId; + CopyMemory(info->ArcRandomBits, p, 16); + if ((settings->PrintReconnectCookie) && (autoReconnectCookie->cbLen > 0)) { char* base64; @@ -660,31 +664,46 @@ BOOL rdp_send_client_info(rdpRdp* rdp) return status; } -BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) { UINT32 cbDomain; UINT32 cbUserName; - UINT32 SessionId; if (Stream_GetRemainingLength(s) < 576) return FALSE; Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ + if (cbDomain > 52) + return FALSE; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); + if (!info->domain) + return FALSE; Stream_Seek(s, 52); /* domain (52 bytes) */ - Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ - Stream_Seek(s, 512); /* userName (512 bytes) */ - Stream_Read_UINT32(s, SessionId); /* SessionId (4 bytes) */ - WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", SessionId); + Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ + if (cbUserName > 512) + goto error_username; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); + if (!info->username) + goto error_username; + Stream_Seek(s, 512); /* userName (512 bytes) */ + + Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */ + + WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", info->sessionId); return TRUE; + +error_username: + free(info->domain); + info->domain = NULL; + return FALSE; } -BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) { UINT16 Version; UINT32 Size; - UINT32 SessionId; UINT32 cbDomain; UINT32 cbUserName; @@ -693,7 +712,7 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, Version); /* Version (2 bytes) */ Stream_Read_UINT32(s, Size); /* Size (4 bytes) */ - Stream_Read_UINT32(s, SessionId); /* SessionId (4 bytes) */ + Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */ Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ Stream_Seek(s, 558); /* pad (558 bytes) */ @@ -701,10 +720,21 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s) if (Stream_GetRemainingLength(s) < (cbDomain + cbUserName)) return FALSE; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); + if (!info->domain) + return FALSE; Stream_Seek(s, cbDomain); /* domain */ + + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); + if (!info->username) + { + free(info->domain); + info->domain = NULL; + return FALSE; + } Stream_Seek(s, cbUserName); /* userName */ - WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", SessionId); + WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", info->sessionId); return TRUE; } @@ -721,7 +751,7 @@ BOOL rdp_recv_logon_plain_notify(rdpRdp* rdp, wStream* s) return TRUE; } -BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s, logon_info_ex *info) { UINT32 errorNotificationType; UINT32 errorNotificationData; @@ -737,10 +767,12 @@ BOOL rdp_recv_logon_error_info(rdpRdp* rdp, wStream* s) IFCALL(rdp->instance->LogonErrorInfo, rdp->instance, errorNotificationData, errorNotificationType); + info->ErrorNotificationType = errorNotificationType; + info->ErrorNotificationData = errorNotificationData; return TRUE; } -BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) +BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s, logon_info_ex *info) { UINT32 cbFieldData; UINT32 fieldsPresent; @@ -752,7 +784,7 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, Length); /* Length (2 bytes) */ Stream_Read_UINT32(s, fieldsPresent); /* fieldsPresent (4 bytes) */ - if (Stream_GetRemainingLength(s) < (Length - 6)) + if ((Length < 6) || (Stream_GetRemainingLength(s) < (Length - 6))) return FALSE; WLog_DBG(TAG, "LogonInfoExtended: fieldsPresent: 0x%04X", fieldsPresent); @@ -764,20 +796,28 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) if (Stream_GetRemainingLength(s) < 4) return FALSE; + info->haveCookie = TRUE; Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */ - if (!rdp_read_server_auto_reconnect_cookie(rdp, s)) + if (Stream_GetRemainingLength(s) < cbFieldData) + return FALSE; + + if (!rdp_read_server_auto_reconnect_cookie(rdp, s, info)) return FALSE; } if (fieldsPresent & LOGON_EX_LOGONERRORS) { + info->haveErrorInfo = TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; Stream_Read_UINT32(s, cbFieldData); /* cbFieldData (4 bytes) */ - if (!rdp_recv_logon_error_info(rdp, s)) + if (Stream_GetRemainingLength(s) < cbFieldData) + return FALSE; + + if (!rdp_recv_logon_error_info(rdp, s, info)) return FALSE; } @@ -792,7 +832,11 @@ BOOL rdp_recv_logon_info_extended(rdpRdp* rdp, wStream* s) BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s) { UINT32 infoType; - BOOL status = FALSE; + BOOL status; + logon_info logonInfo; + logon_info_ex logonInfoEx; + rdpContext *context = rdp->context; + rdpUpdate *update = rdp->context->update; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -802,22 +846,39 @@ BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s) switch (infoType) { case INFO_TYPE_LOGON: - status = rdp_recv_logon_info_v1(rdp, s); + ZeroMemory(&logonInfo, sizeof(logonInfo)); + status = rdp_recv_logon_info_v1(rdp, s, &logonInfo); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, &logonInfo); + free(logonInfo.domain); + free(logonInfo.username); break; case INFO_TYPE_LOGON_LONG: - status = rdp_recv_logon_info_v2(rdp, s); + ZeroMemory(&logonInfo, sizeof(logonInfo)); + status = rdp_recv_logon_info_v2(rdp, s, &logonInfo); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, &logonInfo); + free(logonInfo.domain); + free(logonInfo.username); break; case INFO_TYPE_LOGON_PLAIN_NOTIFY: status = rdp_recv_logon_plain_notify(rdp, s); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, NULL); break; case INFO_TYPE_LOGON_EXTENDED_INF: - status = rdp_recv_logon_info_extended(rdp, s); + ZeroMemory(&logonInfoEx, sizeof(logonInfoEx)); + status = rdp_recv_logon_info_extended(rdp, s, &logonInfoEx); + if (status && update->SaveSessionInfo) + status = update->SaveSessionInfo(context, infoType, &logonInfoEx); break; default: + WLog_ERR(TAG, "Unhandled saveSessionInfo type 0x%x", infoType); + status = TRUE; break; } @@ -830,3 +891,174 @@ BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s) return status; } +static BOOL rdp_write_logon_info_v1(wStream *s, logon_info *info) +{ + int sz = 4 + 52 + 4 + 512 + 4; + int len; + WCHAR *wString = NULL; + + if (!Stream_EnsureRemainingCapacity(s, sz)) + return FALSE; + + /* domain */ + len = ConvertToUnicode(CP_UTF8, 0, info->domain, -1, &wString, 0); + if (len < 0) + return FALSE; + len *= 2; + if (len > 52) + return FALSE; + + Stream_Write_UINT32(s, len); + Stream_Write(s, wString, len); + Stream_Seek(s, 52 - len); + free(wString); + + /* username */ + len = ConvertToUnicode(CP_UTF8, 0, info->username, -1, &wString, 0); + if (len < 0) + return FALSE; + + len *= 2; + if (len > 512) + return FALSE; + + Stream_Write_UINT32(s, len); + Stream_Write(s, wString, len); + Stream_Seek(s, 512 - len); + free(wString); + + /* sessionId */ + Stream_Write_UINT32(s, info->sessionId); + + return TRUE; +} + +static BOOL rdp_write_logon_info_v2(wStream *s, logon_info *info) +{ + int Size = 2 + 4 + 4 + 4 + 4 + 558; + int domainLen, usernameLen, len; + WCHAR *wString; + + if (!Stream_EnsureRemainingCapacity(s, Size)) + return FALSE; + + Stream_Write_UINT16(s, SAVE_SESSION_PDU_VERSION_ONE); + Stream_Write_UINT32(s, Size); + Stream_Write_UINT32(s, info->sessionId); + + domainLen = strlen(info->domain); + Stream_Write_UINT32(s, (domainLen + 1) * 2); + + usernameLen = strlen(info->username); + Stream_Write_UINT32(s, (usernameLen + 1) * 2); + + Stream_Seek(s, 558); + + len = ConvertToUnicode(CP_UTF8, 0, info->domain, -1, &wString, 0); + if (len < 0) + return FALSE; + + Stream_Write(s, wString, len * 2); + free(wString); + + len = ConvertToUnicode(CP_UTF8, 0, info->username, -1, &wString, 0); + if (len < 0) + return FALSE; + + Stream_Write(s, wString, len * 2); + free(wString); + return TRUE; +} + +static BOOL rdp_write_logon_info_plain(wStream *s) +{ + if (!Stream_EnsureRemainingCapacity(s, 576)) + return FALSE; + + Stream_Seek(s, 576); + return TRUE; +} + +static BOOL rdp_write_logon_info_ex(wStream *s, logon_info_ex *info) +{ + UINT32 FieldsPresent = 0; + UINT16 Size = 2 + 4 + 570; + + if (info->haveCookie) + { + FieldsPresent |= LOGON_EX_AUTORECONNECTCOOKIE; + Size += 28; + } + + if (info->haveErrorInfo) + { + FieldsPresent |= LOGON_EX_LOGONERRORS; + Size += 8; + } + + if (!Stream_EnsureRemainingCapacity(s, Size)) + return FALSE; + + Stream_Write_UINT16(s, Size); + Stream_Write_UINT32(s, FieldsPresent); + + if (info->haveCookie) + { + Stream_Write_UINT32(s, 28); /* cbFieldData (4 bytes) */ + + Stream_Write_UINT32(s, 28); /* cbLen (4 bytes) */ + Stream_Write_UINT32(s, AUTO_RECONNECT_VERSION_1); /* Version (4 bytes) */ + Stream_Write_UINT32(s, info->LogonId); /* LogonId (4 bytes) */ + Stream_Write(s, info->ArcRandomBits, 16); /* ArcRandomBits (16 bytes) */ + } + + if (info->haveErrorInfo) + { + Stream_Write_UINT32(s, 8); /* cbFieldData (4 bytes) */ + + Stream_Write_UINT32(s, info->ErrorNotificationType); /* ErrorNotificationType (4 bytes) */ + Stream_Write_UINT32(s, info->ErrorNotificationData); /* ErrorNotificationData (4 bytes) */ + } + + Stream_Seek(s, 570); + return TRUE; +} + +BOOL rdp_send_save_session_info(rdpContext *context, UINT32 type, void *data) +{ + wStream *s; + BOOL status; + rdpRdp *rdp = context->rdp; + + s = rdp_data_pdu_init(rdp); + if (!s) + return FALSE; + + Stream_Write_UINT32(s, type); + + switch (type) + { + case INFO_TYPE_LOGON: + status = rdp_write_logon_info_v1(s, (logon_info *)data); + break; + case INFO_TYPE_LOGON_LONG: + status = rdp_write_logon_info_v2(s, (logon_info *)data); + break; + case INFO_TYPE_LOGON_PLAIN_NOTIFY: + status = rdp_write_logon_info_plain(s); + break; + case INFO_TYPE_LOGON_EXTENDED_INF: + status = rdp_write_logon_info_ex(s, (logon_info_ex *)data); + break; + default: + WLog_ERR(TAG, "saveSessionInfo type 0x%x not handled", type); + status = FALSE; + break; + } + + if (status) + status = rdp_send_data_pdu(rdp, s, DATA_PDU_TYPE_SAVE_SESSION_INFO, rdp->mcs->userId); + else + Stream_Free(s, TRUE); + return status; +} diff --git a/libfreerdp/core/info.h b/libfreerdp/core/info.h index 82bc9dac2..631fbc71c 100644 --- a/libfreerdp/core/info.h +++ b/libfreerdp/core/info.h @@ -26,11 +26,6 @@ #include -#define INFO_TYPE_LOGON 0x00000000 -#define INFO_TYPE_LOGON_LONG 0x00000001 -#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 -#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 - /* Client Address Family */ #define ADDRESS_FAMILY_INET 0x0002 #define ADDRESS_FAMILY_INET6 0x0017 @@ -56,23 +51,13 @@ #define INFO_VIDEO_DISABLE 0x00400000 #define INFO_HIDEF_RAIL_SUPPORTED 0x02000000 -/* Logon Information Types */ -#define INFO_TYPE_LOGON 0x00000000 -#define INFO_TYPE_LOGON_LONG 0x00000001 -#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 -#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 - /* Extended Logon Info */ #define LOGON_EX_AUTORECONNECTCOOKIE 0x00000001 #define LOGON_EX_LOGONERRORS 0x00000002 -/* Logon Error Info */ -#define LOGON_FAILED_BAD_PASSWORD 0x00000000 -#define LOGON_FAILED_UPDATE_PASSWORD 0x00000001 -#define LOGON_FAILED_OTHER 0x00000002 -#define LOGON_WARNING 0x00000003 +#define SAVE_SESSION_PDU_VERSION_ONE 0x0001 + -BOOL rdp_read_server_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); BOOL rdp_read_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); void rdp_write_client_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); void rdp_write_auto_reconnect_cookie(rdpRdp* rdp, wStream* s); @@ -83,5 +68,6 @@ void rdp_write_info_packet(rdpRdp* rdp, wStream* s); BOOL rdp_recv_client_info(rdpRdp* rdp, wStream* s); BOOL rdp_send_client_info(rdpRdp* rdp); BOOL rdp_recv_save_session_info(rdpRdp* rdp, wStream* s); +BOOL rdp_send_save_session_info(rdpContext *context, UINT32 type, void *data); #endif /* __INFO_H */ diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 942bb62f7..a1ceeffb0 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -204,8 +204,7 @@ static int rdp_security_stream_init(rdpRdp* rdp, wStream* s, BOOL sec_header) int rdp_init_stream(rdpRdp* rdp, wStream* s) { Stream_Seek(s, RDP_PACKET_HEADER_MAX_LENGTH); - rdp_security_stream_init(rdp, s, FALSE); - return 0; + return rdp_security_stream_init(rdp, s, FALSE); } wStream* rdp_send_stream_init(rdpRdp* rdp) diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c index 90e183e1c..f8b2dad02 100644 --- a/libfreerdp/core/update.c +++ b/libfreerdp/core/update.c @@ -30,11 +30,13 @@ #include "update.h" #include "surface.h" #include "message.h" +#include "info.h" #include #include #include + #define TAG FREERDP_TAG("core.update") const char* const UPDATE_TYPE_STRINGS[] = @@ -1905,6 +1907,7 @@ void update_register_server_callbacks(rdpUpdate* update) update->SurfaceFrameBits = update_send_surface_frame_bits; update->PlaySound = update_send_play_sound; update->SetKeyboardIndicators = update_send_set_keyboard_indicators; + update->SaveSessionInfo = rdp_send_save_session_info; update->primary->DstBlt = update_send_dstblt; update->primary->PatBlt = update_send_patblt; update->primary->ScrBlt = update_send_scrblt; From ae4a1ee342530205dab1edfbfa4925988e99914b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 19 Feb 2016 10:22:38 +0100 Subject: [PATCH 032/128] Abort certificate accept if password is read from stdin. --- client/common/client.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/common/client.c b/client/common/client.c index 95e1a84b8..a847c9b34 100644 --- a/client/common/client.c +++ b/client/common/client.c @@ -409,6 +409,9 @@ static DWORD client_cli_accept_certificate(rdpSettings* settings) { char answer; + if (settings->CredentialsFromStdin) + return 0; + while (1) { printf("Do you trust the above certificate? (Y/T/N) "); From 1dea98026ad8c6d1bd811a40effe7db889945a05 Mon Sep 17 00:00:00 2001 From: Giovanni Panozzo Date: Sun, 21 Feb 2016 17:52:52 +0100 Subject: [PATCH 033/128] Fix char signedness in glyph offset calculation, fixes #2137 --- libfreerdp/cache/glyph.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/cache/glyph.c b/libfreerdp/cache/glyph.c index 0157d40bc..412c1146c 100644 --- a/libfreerdp/cache/glyph.c +++ b/libfreerdp/cache/glyph.c @@ -57,7 +57,7 @@ void update_process_glyph(rdpContext* context, BYTE* data, int* index, if (offset & 0x80) { - offset = data[*index + 1] | ((int)((char)data[*index + 2]) << 8); + offset = data[*index + 1] | ((int)((signed char)data[*index + 2]) << 8); (*index)++; (*index)++; } From 6c8de27d8a83aed091ec880d950de7414ebab180 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 22 Feb 2016 10:27:50 +0100 Subject: [PATCH 034/128] Installing debug symbols only if activated. --- rdtk/librdtk/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rdtk/librdtk/CMakeLists.txt b/rdtk/librdtk/CMakeLists.txt index e12f162b6..b6caf80c4 100644 --- a/rdtk/librdtk/CMakeLists.txt +++ b/rdtk/librdtk/CMakeLists.txt @@ -65,7 +65,7 @@ endif() target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT RdTkTargets) -if (MSVC AND BUILD_SHARED_LIBS) +if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS) install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols) endif() From e6f013eac7204ff4a26e5fd3aa18f85a55708bdb Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 22 Feb 2016 17:01:43 +0100 Subject: [PATCH 035/128] fix spelling replace occured with occurred Fixes #3142 --- channels/drive/client/dirent.h | 2 +- channels/urbdrc/client/urbdrc_main.c | 2 +- .../com/freerdp/freerdpcore/presentation/BookmarkActivity.java | 2 +- client/common/cmdline.c | 2 +- libfreerdp/core/errconnect.c | 2 +- libfreerdp/core/tcp.c | 2 +- winpr/include/winpr/error.h | 1 + winpr/include/winpr/nt.h | 1 + winpr/libwinpr/comm/comm_serial_sys.c | 2 +- 9 files changed, 9 insertions(+), 7 deletions(-) diff --git a/channels/drive/client/dirent.h b/channels/drive/client/dirent.h index 9a293daa1..d9efa36a9 100644 --- a/channels/drive/client/dirent.h +++ b/channels/drive/client/dirent.h @@ -286,7 +286,7 @@ static struct dirent *readdir(DIR *dirp) return NULL; } if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) { - /* the very last entry has been processed or an error occured */ + /* the very last entry has been processed or an error occurred */ FindClose (dirp->search_handle); dirp->search_handle = INVALID_HANDLE_VALUE; return NULL; diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 78cd77da0..1e4c0a771 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -1026,7 +1026,7 @@ static void* urbdrc_search_usb_device(void* arg) } else { - WLog_ERR(TAG, "No Device from receive_device(). An error occured."); + WLog_ERR(TAG, "No Device from receive_device(). An error occurred."); } } } diff --git a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/BookmarkActivity.java b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/BookmarkActivity.java index 9c8140ecb..e78bb2a9b 100644 --- a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/BookmarkActivity.java +++ b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/presentation/BookmarkActivity.java @@ -575,7 +575,7 @@ public class BookmarkActivity extends PreferenceActivity implements if (!verifyFailed && sharedPreferences.getInt("bookmark.port", -1) <= 0) verifyFailed = true; - // if an error occured - display toast and return false + // if an error occurred - display toast and return false return (!verifyFailed); } diff --git a/client/common/cmdline.c b/client/common/cmdline.c index b1f64ee0a..510ef716e 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -1684,7 +1684,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings, { id = (unsigned long int) freerdp_map_keyboard_layout_name_to_id(arg->Value); if (id == -1) - WLog_ERR(TAG, "A problem occured while mapping the layout name to id"); + WLog_ERR(TAG, "A problem occurred while mapping the layout name to id"); else if (id == 0) { WLog_ERR(TAG, "Could not identify keyboard layout: %s", arg->Value); diff --git a/libfreerdp/core/errconnect.c b/libfreerdp/core/errconnect.c index a52912b08..cd983b464 100644 --- a/libfreerdp/core/errconnect.c +++ b/libfreerdp/core/errconnect.c @@ -38,7 +38,7 @@ "A configuration error prevented a connection to be established." #define ERRCONNECT_CONNECT_UNDEFINED_STRING \ - "A undefined connection error occured." + "A undefined connection error occurred." #define ERRCONNECT_POST_CONNECT_FAILED_STRING \ "The connection attempt was aborted due to post connect configuration errors." diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index 24bbcd05d..afd7015d0 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -489,7 +489,7 @@ static int transport_bio_buffered_write(BIO* bio, const char* buf, int num) */ if (buf && num && !ringbuffer_write(&ptr->xmitBuffer, (const BYTE*) buf, num)) { - WLog_ERR(TAG, "an error occured when writing (num: %d)", num); + WLog_ERR(TAG, "an error occurred when writing (num: %d)", num); return -1; } diff --git a/winpr/include/winpr/error.h b/winpr/include/winpr/error.h index e84b8f7bc..0a1511b0f 100644 --- a/winpr/include/winpr/error.h +++ b/winpr/include/winpr/error.h @@ -518,6 +518,7 @@ #define ERROR_DEVICE_ENUMERATION_ERROR 0x00000288 #define ERROR_MOUNT_POINT_NOT_RESOLVED 0x00000289 #define ERROR_INVALID_DEVICE_OBJECT_PARAMETER 0x0000028A +/* The following is not a typo. It's the same spelling as in the Microsoft headers */ #define ERROR_MCA_OCCURED 0x0000028B #define ERROR_DRIVER_DATABASE_ERROR 0x0000028C #define ERROR_SYSTEM_HIVE_TOO_LARGE 0x0000028D diff --git a/winpr/include/winpr/nt.h b/winpr/include/winpr/nt.h index d0761ebea..68bccc67d 100644 --- a/winpr/include/winpr/nt.h +++ b/winpr/include/winpr/nt.h @@ -977,6 +977,7 @@ #define STATUS_WAIT_FOR_OPLOCK ((NTSTATUS)0x00000367) #define STATUS_MOUNT_POINT_NOT_RESOLVED ((NTSTATUS)0xC0000368) #define STATUS_INVALID_DEVICE_OBJECT_PARAMETER ((NTSTATUS)0xC0000369) +/* The following is not a typo. It's the same spelling as in the Microsoft headers */ #define STATUS_MCA_OCCURED ((NTSTATUS)0xC000036A) #define STATUS_DRIVER_BLOCKED_CRITICAL ((NTSTATUS)0xC000036B) #define STATUS_DRIVER_BLOCKED ((NTSTATUS)0xC000036C) diff --git a/winpr/libwinpr/comm/comm_serial_sys.c b/winpr/libwinpr/comm/comm_serial_sys.c index 5c8b0277f..04e11da4b 100644 --- a/winpr/libwinpr/comm/comm_serial_sys.c +++ b/winpr/libwinpr/comm/comm_serial_sys.c @@ -1344,7 +1344,7 @@ static BOOL _get_commstatus(WINPR_COMM *pComm, SERIAL_STATUS *pCommstatus) } else { - /* FIXME: "is 80 percent full" from the specs is ambiguous, need to track when it previously occured? */ + /* FIXME: "is 80 percent full" from the specs is ambiguous, need to track when it previously * occurred? */ pComm->PendingEvents &= ~SERIAL_EV_RX80FULL; } From 93fc349ce6174ccdae300ffd248e18151daa48d1 Mon Sep 17 00:00:00 2001 From: ilammy Date: Tue, 23 Feb 2016 00:14:30 +0200 Subject: [PATCH 036/128] client/X11: harden xf_cliprdr_parse_server_format_list() * Make sure that numFormats has reasonable value This will help catching errors like writing -1 as an unsigned number of formats into the serialized stream, or trying to read the property after someone else erroneosly messed with it, or other similar mistakes which would result into reading and then sending garbage to the server. We read the list xf_cliprdr_get_raw_server_formats() from an X window property. Properties generally cannot be larger than 4 KB and each format requires at least 5 bytes (most of them are named, though), which gives us 512-ish limit on the number of formats we can squeeze into the property. However, it's hard to find an application that provides more than 20 formats (I've seen like 15 for MS Office apps), thus I believe we can safely assume than anything that does not fit into a byte means that we are reading garbage rather than a good format list. * Check for the end of stream when reading format names This also prevents reading garbage and getting segmentation faults and Valgrind warnings when somebody somewhere sometimes forgets to put a terminating null character where it belongs. strnlen() and strndup() functions are provided by POSIX.1-2008 which we can reasonably expect to be available in 2016. --- client/X11/xf_cliprdr.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c index a13612a30..569f4484e 100644 --- a/client/X11/xf_cliprdr.c +++ b/client/X11/xf_cliprdr.c @@ -44,6 +44,8 @@ #define TAG CLIENT_TAG("x11") +#define MAX_CLIPBOARD_FORMATS 255 + struct xf_cliprdr_format { Atom atom; @@ -341,6 +343,12 @@ static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data, size_t le Stream_Read_UINT32(s, *numFormats); + if (*numFormats > MAX_CLIPBOARD_FORMATS) + { + WLog_ERR(TAG, "unexpectedly large number of formats: %u", *numFormats); + goto error; + } + if (!(formats = (CLIPRDR_FORMAT*) calloc(*numFormats, sizeof(CLIPRDR_FORMAT)))) { WLog_ERR(TAG, "failed to allocate format list"); @@ -349,6 +357,9 @@ static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data, size_t le for (i = 0; i < *numFormats; i++) { + const char* formatName = NULL; + size_t formatNameLength = 0; + if (Stream_GetRemainingLength(s) < sizeof(UINT32)) { WLog_ERR(TAG, "unexpected end of serialized format list"); @@ -356,8 +367,18 @@ static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data, size_t le } Stream_Read_UINT32(s, formats[i].formatId); - formats[i].formatName = strdup((char*) Stream_Pointer(s)); - Stream_Seek(s, strlen((char*) Stream_Pointer(s)) + 1); + + formatName = (const char*) Stream_Pointer(s); + formatNameLength = strnlen(formatName, Stream_GetRemainingLength(s)); + + if (formatNameLength == Stream_GetRemainingLength(s)) + { + WLog_ERR(TAG, "missing terminating null byte, %zu bytes left to read", formatNameLength); + goto error; + } + + formats[i].formatName = strndup(formatName, formatNameLength); + Stream_Seek(s, formatNameLength + 1); } Stream_Free(s, FALSE); From 1b881e47d3124b684f32a171d193a70527a1ee9a Mon Sep 17 00:00:00 2001 From: Martin Fleisz Date: Tue, 23 Feb 2016 09:55:55 +0100 Subject: [PATCH 037/128] winpr/file: Add missing include (io.h) for windows builds --- winpr/libwinpr/file/file.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 77cdf4638..862703b3e 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -24,7 +24,11 @@ #include -#ifndef _WIN32 +#ifdef _WIN32 + +#include + +#else /* _WIN32 */ #include "../log.h" #define TAG WINPR_TAG("file") @@ -577,9 +581,9 @@ BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle) HANDLE GetFileHandleForFileDescriptor(int fd) { -#ifdef WIN32 +#ifdef _WIN32 return (HANDLE)_get_osfhandle(fd); -#else /* WIN32 */ +#else /* _WIN32 */ WINPR_FILE *pFile; FILE* fp; int flags; @@ -607,7 +611,7 @@ HANDLE GetFileHandleForFileDescriptor(int fd) return INVALID_HANDLE_VALUE; return (HANDLE)pFile; -#endif /* WIN32 */ +#endif /* _WIN32 */ } From ded17d9d0c46fb6bf7959e049714fdcbd5b6603e Mon Sep 17 00:00:00 2001 From: David FORT Date: Wed, 6 Jan 2016 23:56:05 +0100 Subject: [PATCH 038/128] Move wayland client to UWAC --- client/Wayland/CMakeLists.txt | 14 +-- client/Wayland/wlf_display.c | 112 ----------------- client/Wayland/wlf_display.h | 43 ------- client/Wayland/wlf_input.c | 204 +++++-------------------------- client/Wayland/wlf_input.h | 25 ++-- client/Wayland/wlf_window.c | 220 ---------------------------------- client/Wayland/wlf_window.h | 58 --------- client/Wayland/wlfreerdp.c | 169 +++++++++++++++++++------- client/Wayland/wlfreerdp.h | 12 +- cmake/FindWayland.cmake | 68 +++++------ 10 files changed, 203 insertions(+), 722 deletions(-) delete mode 100644 client/Wayland/wlf_display.c delete mode 100644 client/Wayland/wlf_display.h delete mode 100644 client/Wayland/wlf_window.c delete mode 100644 client/Wayland/wlf_window.h diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt index 66cb0d18b..232989104 100644 --- a/client/Wayland/CMakeLists.txt +++ b/client/Wayland/CMakeLists.txt @@ -2,6 +2,7 @@ # FreeRDP Wayland Client cmake build script # # Copyright 2014 Manuel Bachmann +# Copyright 2015 David Fort # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -18,22 +19,19 @@ set(MODULE_NAME "wlfreerdp") set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND") -include_directories(${WAYLAND_INCLUDE_DIRS}) +include_directories(${UWAC_INCLUDE_DIRS}) set(${MODULE_PREFIX}_SRCS - wlf_display.c - wlf_display.h - wlf_window.c - wlf_window.h + wlfreerdp.c + wlfreerdp.h wlf_input.c wlf_input.h - wlfreerdp.c - wlfreerdp.h) + ) add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS}) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBRARIES} freerdp-client freerdp) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${UWAC_LIBS} freerdp-client freerdp) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client) diff --git a/client/Wayland/wlf_display.c b/client/Wayland/wlf_display.c deleted file mode 100644 index 4ab971284..000000000 --- a/client/Wayland/wlf_display.c +++ /dev/null @@ -1,112 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Displays - * - * Copyright 2014 Manuel Bachmann - * - * 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 -#include - -#include "wlf_display.h" - -static void wl_registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char *interface, uint32_t version) -{ - wlfDisplay* display = data; - - if (strcmp(interface, "wl_compositor") == 0) - display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1); - else if (strcmp(interface, "wl_shell") == 0) - display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1); - else if (strcmp(interface, "wl_shm") == 0) - display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); - else if (strcmp(interface, "wl_seat") == 0) - display->seat = wl_registry_bind(registry, id, &wl_seat_interface, 1); -} - -static void wl_registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name) -{ - -} - -static const struct wl_registry_listener wl_registry_listener = -{ - wl_registry_handle_global, - wl_registry_handle_global_remove -}; - - -wlfDisplay* wlf_CreateDisplay(void) -{ - wlfDisplay* display; - - display = (wlfDisplay*) calloc(1, sizeof(wlfDisplay)); - - if (display) - { - display->display = wl_display_connect(NULL); - - if (!display->display) - { - WLog_ERR(TAG, "wl_pre_connect: failed to connect to Wayland compositor"); - WLog_ERR(TAG, "Please check that the XDG_RUNTIME_DIR environment variable is properly set."); - free(display); - return NULL; - } - - display->registry = wl_display_get_registry(display->display); - wl_registry_add_listener(display->registry, &wl_registry_listener, display); - wl_display_roundtrip(display->display); - - if (!display->compositor || !display->shell || !display->shm) - { - WLog_ERR(TAG, "wl_pre_connect: failed to find needed compositor interfaces"); - free(display); - return NULL; - } - } - - return display; -} - -BOOL wlf_RefreshDisplay(wlfDisplay* display) -{ - if (wl_display_dispatch(display->display) == -1) - return FALSE; - return TRUE; -} - -void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display) -{ - if (display == NULL) - return; - - if (wlfc->display == display) - wlfc->display = NULL; - - if (display->seat) - wl_seat_destroy(display->seat); - if (display->shm) - wl_shm_destroy(display->shm); - if (display->shell) - wl_shell_destroy(display->shell); - if (display->compositor) - wl_compositor_destroy(display->compositor); - if (display->registry) - wl_registry_destroy(display->registry); - wl_display_disconnect(display->display); - - free(display); -} diff --git a/client/Wayland/wlf_display.h b/client/Wayland/wlf_display.h deleted file mode 100644 index d92d8991d..000000000 --- a/client/Wayland/wlf_display.h +++ /dev/null @@ -1,43 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Displays - * - * Copyright 2014 Manuel Bachmann - * - * 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 __WLF_DISPLAY_H -#define __WLF_DISPLAY_H - -#include - -typedef struct wlf_display wlfDisplay; - -#include "wlfreerdp.h" - -struct wlf_display -{ - struct wl_display* display; - struct wl_registry* registry; - struct wl_compositor* compositor; - struct wl_shell* shell; - struct wl_shm* shm; - struct wl_seat* seat; -}; - -wlfDisplay* wlf_CreateDisplay(void); -BOOL wlf_RefreshDisplay(wlfDisplay* display); -void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display); - -#endif /* __WLF_DISPLAY_H */ diff --git a/client/Wayland/wlf_input.c b/client/Wayland/wlf_input.c index 76ab5552a..00435ffff 100644 --- a/client/Wayland/wlf_input.c +++ b/client/Wayland/wlf_input.c @@ -3,6 +3,7 @@ * Wayland Input * * Copyright 2014 Manuel Bachmann + * Copyright 2015 David Fort * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,50 +25,30 @@ #include "wlf_input.h" -static void wl_pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ +BOOL wlf_handle_pointer_enter(freerdp *instance, UwacPointerEnterLeaveEvent *ev) { + rdpInput* input = instance->input; + return input->MouseEvent(input, PTR_FLAGS_MOVE, ev->x, ev->y); } -static void wl_pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface) -{ - +BOOL wlf_handle_pointer_motion(freerdp *instance, UwacPointerMotionEvent *ev) { + rdpInput* input = instance->input; + + return input->MouseEvent(input, PTR_FLAGS_MOVE, ev->x, ev->y); } -static void wl_pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w) -{ - wlfInput* input_w = data; +BOOL wlf_handle_pointer_buttons(freerdp *instance, UwacPointerButtonEvent *ev) { rdpInput* input; - UINT16 x; - UINT16 y; - - input = input_w->input; - - x = (UINT16) wl_fixed_to_int(sx_w); - y = (UINT16) wl_fixed_to_int(sy_w); - - input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); - - input_w->last_x = x; - input_w->last_y = y; -} - -static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) -{ - wlfInput* input_w = data; - rdpInput* input; - UINT16 x; - UINT16 y; UINT16 flags; - input = input_w->input; + input = instance->input; - if (state == WL_POINTER_BUTTON_STATE_PRESSED) + if (ev->state == WL_POINTER_BUTTON_STATE_PRESSED) flags = PTR_FLAGS_DOWN; else flags = 0; - switch (button) + switch (ev->button) { case BTN_LEFT: flags |= PTR_FLAGS_BUTTON1; @@ -79,175 +60,50 @@ static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t s flags |= PTR_FLAGS_BUTTON3; break; default: - return; + return TRUE; } - x = input_w->last_x; - y = input_w->last_y; - - input->MouseEvent(input, flags, x, y); + return input->MouseEvent(input, flags, ev->x, ev->y); } -static void wl_pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value) -{ - wlfInput* input_w = data; + +BOOL wlf_handle_pointer_axis(freerdp *instance, UwacPointerAxisEvent *ev) { rdpInput* input; UINT16 flags; int direction; - input = input_w->input; + input = instance->input; flags = PTR_FLAGS_WHEEL; - if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) + if (ev->axis == WL_POINTER_AXIS_VERTICAL_SCROLL) { - direction = wl_fixed_to_int(value); + direction = wl_fixed_to_int(ev->value); if (direction < 0) flags |= 0x0078; else flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088; } - input->MouseEvent(input, flags, 0, 0); + return input->MouseEvent(input, flags, ev->x, ev->y); } -static const struct wl_pointer_listener wl_pointer_listener = -{ - wl_pointer_enter, - wl_pointer_leave, - wl_pointer_motion, - wl_pointer_button, - wl_pointer_axis -}; - -static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size) -{ - -} - -static void wl_keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys) -{ - wlfInput* input_w = data; - rdpInput* input; - UINT16 x; - UINT16 y; - - input = input_w->input; - - x = input_w->last_x; - y = input_w->last_y; - - input->FocusInEvent(input, 0); - input->MouseEvent(input, PTR_FLAGS_MOVE, x, y); -} - -static void wl_keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface) -{ - -} - -static void wl_keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) -{ - wlfInput* input_w = data; - rdpInput* input; - BOOL key_down; +BOOL wlf_handle_key(freerdp *instance, UwacKeyEvent *ev) { + rdpInput* input = instance->input; DWORD rdp_scancode; - input = input_w->input; - - if (state == WL_KEYBOARD_KEY_STATE_PRESSED) - key_down = TRUE; - else - key_down = FALSE; - - rdp_scancode = (DWORD) key; + rdp_scancode = (DWORD) ev->raw_key; if (rdp_scancode == RDP_SCANCODE_UNKNOWN) - return; + return TRUE; - freerdp_input_send_keyboard_event_ex(input, key_down, rdp_scancode); + return freerdp_input_send_keyboard_event_ex(input, ev->pressed, rdp_scancode); } -static void wl_keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t mods_depr, uint32_t mods_latch, uint32_t mods_lock, uint32_t group) -{ +BOOL wlf_keyboard_enter(freerdp *instance, UwacKeyboardEnterLeaveEvent *ev) { + rdpInput* input = instance->input; + + return input->FocusInEvent(input, 0) && + input->MouseEvent(input, PTR_FLAGS_MOVE, 0, 0); } - -static const struct wl_keyboard_listener wl_keyboard_listener = -{ - wl_keyboard_keymap, - wl_keyboard_enter, - wl_keyboard_leave, - wl_keyboard_key, - wl_keyboard_modifiers -}; - -static void wl_seat_handle_capabilities(void* data, struct wl_seat* seat, enum wl_seat_capability capabilities) -{ - wlfInput* input = data; - struct wl_pointer* pointer; - struct wl_keyboard* keyboard; - - if (capabilities & WL_SEAT_CAPABILITY_POINTER) - { - pointer = wl_seat_get_pointer(seat); - - input->pointer = pointer; - wl_pointer_add_listener(pointer, &wl_pointer_listener, input); - } - - if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD) - { - keyboard = wl_seat_get_keyboard(seat); - - input->keyboard = keyboard; - wl_keyboard_add_listener(keyboard, &wl_keyboard_listener, input); - } - -} - -static const struct wl_seat_listener wl_seat_listener = { - wl_seat_handle_capabilities -}; - - -wlfInput* wlf_CreateInput(wlfContext* wlfc) -{ - wlfInput* input; - struct wl_seat* seat; - - if (!wlfc->display) - return NULL; - if (!wlfc->display->seat) - return NULL; - seat = wlfc->display->seat; - - input = (wlfInput*) calloc(1, sizeof(wlfInput)); - - if (input) - { - input->input = wlfc->context.input; - input->last_x = 0; - input->last_y = 0; - - wl_seat_add_listener(seat, &wl_seat_listener, input); - } - - return input; -} - -void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input) -{ - if (input == NULL) - return; - - if (wlfc->input == input) - wlfc->input = NULL; - - if (input->pointer) - wl_pointer_release(input->pointer); - if (input->keyboard) - wl_keyboard_release(input->keyboard); - - free(input); -} diff --git a/client/Wayland/wlf_input.h b/client/Wayland/wlf_input.h index 46f2447d7..0529f0179 100644 --- a/client/Wayland/wlf_input.h +++ b/client/Wayland/wlf_input.h @@ -3,6 +3,7 @@ * Wayland Input * * Copyright 2014 Manuel Bachmann + * Copyright 2015 David Fort * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,23 +21,15 @@ #ifndef __WLF_INPUT_H #define __WLF_INPUT_H -#include +#include +#include -typedef struct wlf_input wlfInput; +BOOL wlf_handle_pointer_enter(freerdp* instance, UwacPointerEnterLeaveEvent *ev); +BOOL wlf_handle_pointer_motion(freerdp* instance, UwacPointerMotionEvent *ev); +BOOL wlf_handle_pointer_buttons(freerdp* instance, UwacPointerButtonEvent *ev); +BOOL wlf_handle_pointer_axis(freerdp* instance, UwacPointerAxisEvent *ev); -#include "wlfreerdp.h" - -struct wlf_input -{ - rdpInput* input; - UINT16 last_x; - UINT16 last_y; - - struct wl_pointer* pointer; - struct wl_keyboard* keyboard; -}; - -wlfInput* wlf_CreateInput(wlfContext* wlfc); -void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input); +BOOL wlf_handle_key(freerdp* instance, UwacKeyEvent *ev); +BOOL wlf_keyboard_enter(freerdp *instance, UwacKeyboardEnterLeaveEvent *ev); #endif /* __WLF_INPUT_H */ diff --git a/client/Wayland/wlf_window.c b/client/Wayland/wlf_window.c deleted file mode 100644 index 72b57eaf3..000000000 --- a/client/Wayland/wlf_window.c +++ /dev/null @@ -1,220 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Windows - * - * Copyright 2014 Manuel Bachmann - * - * 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 -#include -#include -#include -#include - -#include "wlf_window.h" - -static void wl_shell_surface_handle_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial) -{ - wl_shell_surface_pong(shell_surface, serial); -} - -static void wl_shell_surface_handle_configure(void* data, struct wl_shell_surface* shell_surface, unsigned int edges, int32_t width, int32_t height) -{ - wlfWindow* window = data; - - window->width = width; - window->height = height; -} - -static const struct wl_shell_surface_listener wl_shell_surface_listener = -{ - wl_shell_surface_handle_ping, - wl_shell_surface_handle_configure, - NULL -}; - -static void wl_buffer_release(void* data, struct wl_buffer* wl_buffer) -{ - wlfBuffer* buffer = data; - - buffer->busy = FALSE; -} - -static const struct wl_buffer_listener wl_buffer_listener = -{ - wl_buffer_release -}; - -static const struct wl_callback_listener wl_callback_listener; - -static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t time) -{ - wlfWindow* window = data; - wlfBuffer* buffer; - struct wl_shm_pool* shm_pool; - void* shm_data; - void* free_data; - int fd; - int fdt; - - if (!window->buffers[0].busy) - buffer = &window->buffers[0]; - else if (!window->buffers[1].busy) - buffer = &window->buffers[1]; - else - return; - - if (!buffer->buffer) { - fd = shm_open("/wlfreerdp_shm", O_CREAT | O_RDWR, 0666); - fdt = ftruncate(fd, window->width * window->height * 4); - if (fdt != 0) - { - WLog_ERR(TAG, "window_redraw: could not allocate memory"); - close(fd); - return; - } - - shm_data = mmap(NULL, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - if (shm_data == MAP_FAILED) - { - WLog_ERR(TAG, "window_redraw: failed to memory map buffer"); - close(fd); - return; - } - - shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4); - buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888); - wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer); - wl_shm_pool_destroy(shm_pool); - shm_unlink("/wlfreerdp_shm"); - close(fd); - - free_data = buffer->shm_data; - buffer->shm_data = shm_data; - munmap(free_data, window->width * window->height * 4); - } - - /* this is the real surface data */ - memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4); - wl_surface_attach(window->surface, buffer->buffer, 0, 0); - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - - if (callback) wl_callback_destroy(callback); - window->callback = wl_surface_frame(window->surface); - wl_callback_add_listener(window->callback, &wl_callback_listener, window); - wl_surface_commit(window->surface); - - buffer->busy = TRUE; -} - -static const struct wl_callback_listener wl_callback_listener = -{ - wl_callback_done -}; - - -wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations) -{ - wlfWindow* window; - - window = (wlfWindow*) calloc(1, sizeof(wlfWindow)); - - if (window) - { - window->width = width; - window->height = height; - window->fullscreen = FALSE; - window->buffers[0].busy = FALSE; - window->buffers[1].busy = FALSE; - window->callback = NULL; - window->display = wlfc->display; - - window->surface = wl_compositor_create_surface(window->display->compositor); - window->shell_surface = wl_shell_get_shell_surface(window->display->shell, window->surface); - wl_shell_surface_add_listener(window->shell_surface, &wl_shell_surface_listener, window); - wl_shell_surface_set_toplevel(window->shell_surface); - - wlf_ResizeDesktopWindow(wlfc, window, width, height); - - wl_surface_damage(window->surface, 0, 0, window->width, window->height); - - wlf_SetWindowText(wlfc, window, name); - } - - return window; -} - -void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height) -{ - window->width = width; - window->height = height; -} - -void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name) -{ - wl_shell_surface_set_title(window->shell_surface, name); -} - -void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscreen) -{ - if (fullscreen) - { - wl_shell_surface_set_fullscreen(window->shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL); - window->fullscreen = TRUE; - } -} - -void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state) -{ - switch (state) - { - case WINDOW_HIDE: - case WINDOW_SHOW_MINIMIZED: - /* xdg_surface_set_minimized(window->xdg_surface); */ - break; - case WINDOW_SHOW_MAXIMIZED: - wl_shell_surface_set_maximized(window->shell_surface, NULL); - break; - case WINDOW_SHOW: - wl_shell_surface_set_toplevel(window->shell_surface); - break; - } -} - -void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height) -{ - wl_callback_done(window, NULL, 0); -} - -void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window) -{ - if (window == NULL) - return; - - if (wlfc->window == window) - wlfc->window = NULL; - - if (window->buffers[0].buffer) - wl_buffer_destroy(window->buffers[0].buffer); - if (window->buffers[1].buffer) - wl_buffer_destroy(window->buffers[1].buffer); - if (window->shell_surface) - wl_shell_surface_destroy(window->shell_surface); - if (window->surface) - wl_surface_destroy(window->surface); - - free(window->data); - free(window); -} diff --git a/client/Wayland/wlf_window.h b/client/Wayland/wlf_window.h deleted file mode 100644 index df3628909..000000000 --- a/client/Wayland/wlf_window.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Wayland Windows - * - * Copyright 2014 Manuel Bachmann - * - * 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 __WLF_WINDOW_H -#define __WLF_WINDOW_H - -#include - -typedef struct wlf_window wlfWindow; - -#include "wlfreerdp.h" - -struct wlf_buffer -{ - struct wl_buffer* buffer; - void* shm_data; - BOOL busy; -}; -typedef struct wlf_buffer wlfBuffer; - -struct wlf_window -{ - int width; - int height; - struct wl_surface* surface; - struct wl_shell_surface* shell_surface; - struct wl_callback* callback; - wlfBuffer buffers[2]; - wlfDisplay* display; - void* data; - BOOL fullscreen; -}; - -wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations); -void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height); -void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name); -void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscree); -void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state); -void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height); -void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window); - -#endif /* __WLF_WINDOW_H */ diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 4aeda18cc..6c61ae4da 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -23,8 +23,13 @@ #include #include #include +#include #include "wlfreerdp.h" +#include "wlf_input.h" + +UwacDisplay *g_display; +HANDLE g_displayHandle; static BOOL wl_context_new(freerdp* instance, rdpContext* context) { @@ -44,6 +49,18 @@ static void wl_context_free(freerdp* instance, rdpContext* context) } } +BOOL wl_update_content(wlfContext *context_w) +{ + if (!context_w->waitingFrameDone && context_w->haveDamage) + { + UwacWindowSubmitBuffer(context_w->window, true); + context_w->waitingFrameDone = TRUE; + context_w->haveDamage = FALSE; + } + + return TRUE; +} + static BOOL wl_begin_paint(rdpContext* context) { rdpGdi* gdi; @@ -53,12 +70,12 @@ static BOOL wl_begin_paint(rdpContext* context) return TRUE; } + static BOOL wl_end_paint(rdpContext* context) { rdpGdi* gdi; - wlfDisplay* display; - wlfWindow* window; - wlfContext* context_w; + char *data; + wlfContext *context_w; INT32 x, y; UINT32 w, h; int i; @@ -73,21 +90,23 @@ static BOOL wl_end_paint(rdpContext* context) h = gdi->primary->hdc->hwnd->invalid->h; context_w = (wlfContext*) context; - display = context_w->display; - window = context_w->window; + data = UwacWindowGetDrawingBuffer(context_w->window); for (i = 0; i < h; i++) - memcpy(window->data + ((i+y)*(gdi->width*4)) + x*4, + { + memcpy(data + ((i+y)*(gdi->width*4)) + x*4, gdi->primary_buffer + ((i+y)*(gdi->width*4)) + x*4, w*4); + } - return wlf_RefreshDisplay(display); + UwacWindowAddDamage(context_w->window, x, y, w, h); + context_w->haveDamage = TRUE; + return wl_update_content(context_w); } + static BOOL wl_pre_connect(freerdp* instance) { - wlfDisplay* display; - wlfInput* input; wlfContext* context; if (freerdp_channels_pre_connect(instance->context->channels, instance)) @@ -97,17 +116,7 @@ static BOOL wl_pre_connect(freerdp* instance) if (!context) return FALSE; - display = wlf_CreateDisplay(); - if (!display) - return FALSE; - - context->display = display; - - input = wlf_CreateInput(context); - if (!input) - return FALSE; - - context->input = input; + context->display = g_display; return TRUE; } @@ -115,7 +124,7 @@ static BOOL wl_pre_connect(freerdp* instance) static BOOL wl_post_connect(freerdp* instance) { rdpGdi* gdi; - wlfWindow* window; + UwacWindow* window; wlfContext* context; if (!gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP, NULL)) @@ -126,28 +135,23 @@ static BOOL wl_post_connect(freerdp* instance) return FALSE; context = (wlfContext*) instance->context; - window = wlf_CreateDesktopWindow(context, "FreeRDP", gdi->width, gdi->height, FALSE); + context->window = window = UwacCreateWindowShm(context->display, gdi->width, gdi->height, WL_SHM_FORMAT_XRGB8888); if (!window) return FALSE; - /* fill buffer with first image here */ - window->data = malloc (gdi->width * gdi->height *4); - if (!window->data) - return FALSE; + UwacWindowSetTitle(window, "FreeRDP"); - memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4); instance->update->BeginPaint = wl_begin_paint; instance->update->EndPaint = wl_end_paint; - /* put Wayland data in the context here */ - context->window = window; - if (freerdp_channels_post_connect(instance->context->channels, instance) < 0) return FALSE; - wlf_UpdateWindowArea(context, window, 0, 0, gdi->width, gdi->height); - return TRUE; + memcpy(UwacWindowGetDrawingBuffer(context->window), gdi->primary_buffer, gdi->width * gdi->height * 4); + UwacWindowAddDamage(context->window, 0, 0, gdi->width, gdi->height); + context->haveDamage = TRUE; + return wl_update_content(context); } static void wl_post_disconnect(freerdp* instance) @@ -161,15 +165,67 @@ static void wl_post_disconnect(freerdp* instance) context = (wlfContext*) instance->context; - if (context->display) - wlf_DestroyDisplay(context, context->display); - - if (context->input) - wlf_DestroyInput(context, context->input); - gdi_free(instance); if (context->window) - wlf_DestroyWindow(context, context->window); + UwacDestroyWindow(&context->window); + + if (context->display) + UwacCloseDisplay(&context->display); + +} + +static BOOL handle_uwac_events(freerdp* instance, UwacDisplay *display) { + UwacEvent event; + wlfContext *context; + + if (UwacDisplayDispatch(display, 1) < 0) + return FALSE; + + while (UwacHasEvent(display)) + { + if (UwacNextEvent(display, &event) != UWAC_SUCCESS) + return FALSE; + + /*printf("UWAC event type %d\n", event.type);*/ + switch (event.type) { + case UWAC_EVENT_FRAME_DONE: + if (!instance) + continue; + + context = (wlfContext *)instance->context; + context->waitingFrameDone = FALSE; + if (context->haveDamage && !wl_end_paint(instance->context)) + return FALSE; + break; + case UWAC_EVENT_POINTER_ENTER: + if (!wlf_handle_pointer_enter(instance, &event.mouse_enter_leave)) + return FALSE; + break; + case UWAC_EVENT_POINTER_MOTION: + if (!wlf_handle_pointer_motion(instance, &event.mouse_motion)) + return FALSE; + break; + case UWAC_EVENT_POINTER_BUTTONS: + if (!wlf_handle_pointer_buttons(instance, &event.mouse_button)) + return FALSE; + break; + case UWAC_EVENT_POINTER_AXIS: + if (!wlf_handle_pointer_axis(instance, &event.mouse_axis)) + return FALSE; + break; + case UWAC_EVENT_KEY: + if (!wlf_handle_key(instance, &event.key)) + return FALSE; + break; + case UWAC_EVENT_KEYBOARD_ENTER: + if (!wlf_keyboard_enter(instance, &event.keyboard_enter_leave)) + return FALSE; + break; + default: + break; + } + } + return TRUE; } static int wlfreerdp_run(freerdp* instance) @@ -184,27 +240,39 @@ static int wlfreerdp_run(freerdp* instance) return -1; } + handle_uwac_events(instance, g_display); + while (!freerdp_shall_disconnect(instance)) { - count = freerdp_get_event_handles(instance->context, handles, 64); + handles[0] = g_displayHandle; + + count = freerdp_get_event_handles(instance->context, &handles[1], 63); if (!count) { printf("Failed to get FreeRDP file descriptor\n"); break; } - status = WaitForMultipleObjects(count, handles, FALSE, INFINITE); + status = WaitForMultipleObjects(count+1, handles, FALSE, INFINITE); if (WAIT_FAILED == status) { printf("%s: WaitForMultipleObjects failed\n", __FUNCTION__); break; } - if (freerdp_check_event_handles(instance->context) != TRUE) - { - printf("Failed to check FreeRDP file descriptor\n"); + if (!handle_uwac_events(instance, g_display)) { + printf("error handling UWAC events\n"); break; } + + //if (WaitForMultipleObjects(count, &handles[1], FALSE, INFINITE)) { + if (freerdp_check_event_handles(instance->context) != TRUE) + { + printf("Failed to check FreeRDP file descriptor\n"); + break; + } + //} + } freerdp_channels_disconnect(instance->context->channels, instance); @@ -215,9 +283,20 @@ static int wlfreerdp_run(freerdp* instance) int main(int argc, char* argv[]) { - int status; + UwacReturnCode status; freerdp* instance; + g_display = UwacOpenDisplay(NULL, &status); + if (!g_display) + exit(1); + + g_displayHandle = CreateFileDescriptorEvent(NULL, FALSE, FALSE, UwacDisplayGetFd(g_display), WINPR_FD_READ); + if (!g_displayHandle) + exit(1); + + //if (!handle_uwac_events(NULL, g_display)) + // exit(1); + instance = freerdp_new(); instance->PreConnect = wl_pre_connect; instance->PostConnect = wl_post_connect; diff --git a/client/Wayland/wlfreerdp.h b/client/Wayland/wlfreerdp.h index bf4da6faf..575d7e46b 100644 --- a/client/Wayland/wlfreerdp.h +++ b/client/Wayland/wlfreerdp.h @@ -23,22 +23,22 @@ #include #include #include +#include #define TAG CLIENT_TAG("wayland") typedef struct wlf_context wlfContext; -#include "wlf_display.h" -#include "wlf_window.h" -#include "wlf_input.h" struct wlf_context { rdpContext context; - wlfDisplay* display; - wlfWindow* window; - wlfInput* input; + UwacDisplay *display; + UwacWindow *window; + + BOOL waitingFrameDone; + BOOL haveDamage; }; #endif /* __WLFREERDP_H */ diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index a34fdb2d5..76ec854d8 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -1,19 +1,14 @@ -# - Find Wayland -# Find the Wayland libraries +# - Finds UWAC +# Find the UWAC libraries and its dependencies # # This module defines the following variables: -# WAYLAND_FOUND - true if WAYLAND_INCLUDE_DIR & WAYLAND_LIBRARY are found -# WAYLAND_LIBRARIES - Set when WAYLAND_LIBRARY is found -# WAYLAND_INCLUDE_DIRS - Set when WAYLAND_INCLUDE_DIR is found -# -# WAYLAND_INCLUDE_DIR - where to find wayland-client.h, etc. -# WAYLAND_LIBRARY - the Wayland client library -# WAYLAND_VERSION - wayland client version if found and pkg-config was used +# UWAC_FOUND - true if UWAC has been found +# UWAC_LIBS - Set to the full path to UWAC libraries and its dependencies +# UWAC_INCLUDE_DIRS - Set to the include directories for UWAC # #============================================================================= -# Copyright 2014 Manuel Bachmann -# Copyright 2015 Bernhard Miklautz +# Copyright 2015 David Fort # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,38 +23,31 @@ # limitations under the License. #============================================================================= -set(REQUIRED_WAYLAND_CLIENT_VERSION 1.3.0) include(FindPkgConfig) if(PKG_CONFIG_FOUND) - pkg_check_modules(WAYLAND wayland-client) + pkg_check_modules(UWAC uwac) + + # find the complete path to each dependant library + set(UWAC_LIBS, "") + foreach(libname ${UWAC_LIBRARIES}) + find_library(FOUND_LIB NAMES ${libname} + PATHS ${UWAC_LIBRARY_DIRS} + ) + + if (FOUND_LIB) + list(APPEND UWAC_LIBS ${FOUND_LIB}) + endif() + unset(FOUND_LIB CACHE) + endforeach() + + + find_path(UWAC_INCLUDE_DIR NAMES uwac/uwac.h + PATHS ${UWAC_INCLUDE_DIRS} + DOC "The UWAC include directory" + ) + endif() -find_path(WAYLAND_INCLUDE_DIR NAMES wayland-client.h - PATHS ${WAYLAND_INCLUDE_DIRS} - DOC "The Wayland include directory" -) - -find_library(WAYLAND_LIBRARY NAMES wayland-client - PATHS ${WAYLAND_LIBRARY_DIRS} - DOC "The Wayland client library" -) - include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARY WAYLAND_INCLUDE_DIR) - -if(WAYLAND_VERSION) - if (${WAYLAND_VERSION} VERSION_LESS ${REQUIRED_WAYLAND_CLIENT_VERSION}) - message(WARNING "Installed wayland version ${WAYLAND_VERSION} is too old - minimum required version ${REQUIRED_WAYLAND_CLIENT_VERSION}") - set(WAYLAND_FOUND FALSE) - endif() -else() - message(WARNING "Couldn't detect wayland version - no version check is done") -endif() - -if(WAYLAND_FOUND) - set(WAYLAND_LIBRARIES ${WAYLAND_LIBRARY}) - set(WAYLAND_INCLUDE_DIRS ${WAYLAND_INCLUDE_DIR}) -endif() - -mark_as_advanced(WAYLAND_INCLUDE_DIR WAYLAND_LIBRARY WAYLAND_VERSION) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(UWAC DEFAULT_MSG UWAC_LIBS UWAC_INCLUDE_DIR) From bc31c008658499b70553d8e310843ebd43825d88 Mon Sep 17 00:00:00 2001 From: David FORT Date: Tue, 12 Jan 2016 22:29:38 +0100 Subject: [PATCH 039/128] Fixed detection of UWAC library --- cmake/FindWayland.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index 76ec854d8..0414bdf8f 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -50,4 +50,4 @@ if(PKG_CONFIG_FOUND) endif() include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(UWAC DEFAULT_MSG UWAC_LIBS UWAC_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG UWAC_LIBS UWAC_INCLUDE_DIR) From 87d6caa69a40c24a33669ea17dc767dcbf5ad186 Mon Sep 17 00:00:00 2001 From: David FORT Date: Mon, 18 Jan 2016 15:55:33 +0100 Subject: [PATCH 040/128] Integrate UWAC in to the FreeRDP source tree So the wayland client can still be built without installing UWAC as a dependency. --- CMakeLists.txt | 4 + client/Wayland/CMakeLists.txt | 4 +- cmake/FindWayland.cmake | 60 +- uwac/CMakeLists.txt | 20 + uwac/include/CMakeLists.txt | 20 + uwac/include/uwac/uwac-tools.h | 60 ++ uwac/include/uwac/uwac.h | 480 ++++++++++++++++ uwac/libuwac/.gitignore | 7 + uwac/libuwac/CMakeLists.txt | 79 +++ uwac/libuwac/uwac-display.c | 631 +++++++++++++++++++++ uwac/libuwac/uwac-input.c | 831 ++++++++++++++++++++++++++++ uwac/libuwac/uwac-os.c | 236 ++++++++ uwac/libuwac/uwac-os.h | 45 ++ uwac/libuwac/uwac-output.c | 126 +++++ uwac/libuwac/uwac-priv.h | 237 ++++++++ uwac/libuwac/uwac-tools.c | 93 ++++ uwac/libuwac/uwac-utils.c | 63 +++ uwac/libuwac/uwac-utils.h | 53 ++ uwac/libuwac/uwac-window.c | 616 +++++++++++++++++++++ uwac/protocols/fullscreen-shell.xml | 206 +++++++ uwac/protocols/ivi-application.xml | 100 ++++ uwac/protocols/xdg-shell.xml | 608 ++++++++++++++++++++ 22 files changed, 4550 insertions(+), 29 deletions(-) create mode 100644 uwac/CMakeLists.txt create mode 100644 uwac/include/CMakeLists.txt create mode 100644 uwac/include/uwac/uwac-tools.h create mode 100644 uwac/include/uwac/uwac.h create mode 100644 uwac/libuwac/.gitignore create mode 100644 uwac/libuwac/CMakeLists.txt create mode 100644 uwac/libuwac/uwac-display.c create mode 100644 uwac/libuwac/uwac-input.c create mode 100644 uwac/libuwac/uwac-os.c create mode 100644 uwac/libuwac/uwac-os.h create mode 100644 uwac/libuwac/uwac-output.c create mode 100644 uwac/libuwac/uwac-priv.h create mode 100644 uwac/libuwac/uwac-tools.c create mode 100644 uwac/libuwac/uwac-utils.c create mode 100644 uwac/libuwac/uwac-utils.h create mode 100644 uwac/libuwac/uwac-window.c create mode 100644 uwac/protocols/fullscreen-shell.xml create mode 100644 uwac/protocols/ivi-application.xml create mode 100644 uwac/protocols/xdg-shell.xml diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e2ca5d12..2982da5d3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -789,6 +789,10 @@ include_directories("${CMAKE_BINARY_DIR}/rdtk/include") add_subdirectory(rdtk) +if(WAYLAND_FOUND) + add_subdirectory(uwac) +endif() + if(BSD) if(IS_DIRECTORY /usr/local/include) include_directories(/usr/local/include) diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt index 232989104..315be7dc2 100644 --- a/client/Wayland/CMakeLists.txt +++ b/client/Wayland/CMakeLists.txt @@ -19,7 +19,7 @@ set(MODULE_NAME "wlfreerdp") set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND") -include_directories(${UWAC_INCLUDE_DIRS}) +include_directories(${CMAKE_SOURCE_DIR}/uwac/include) set(${MODULE_PREFIX}_SRCS wlfreerdp.c @@ -31,7 +31,7 @@ set(${MODULE_PREFIX}_SRCS add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS}) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${UWAC_LIBS} freerdp-client freerdp) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp uwac) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index 0414bdf8f..e1a7030b4 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -1,10 +1,12 @@ -# - Finds UWAC -# Find the UWAC libraries and its dependencies +# - Finds Wayland +# Find the Wayland libraries that are needed for UWAC # # This module defines the following variables: -# UWAC_FOUND - true if UWAC has been found -# UWAC_LIBS - Set to the full path to UWAC libraries and its dependencies -# UWAC_INCLUDE_DIRS - Set to the include directories for UWAC +# WAYLAND_FOUND - true if UWAC has been found +# WAYLAND_LIBS - Set to the full path to wayland client libraries +# WAYLAND_INCLUDE_DIR - Set to the include directories for wayland +# XKBCOMMON_LIBS - Set to the full path to xkbcommon libraries +# XKBCOMMON_INCLUDE_DIR - Set to the include directories for xkbcommon # #============================================================================= @@ -26,28 +28,32 @@ include(FindPkgConfig) if(PKG_CONFIG_FOUND) - pkg_check_modules(UWAC uwac) - - # find the complete path to each dependant library - set(UWAC_LIBS, "") - foreach(libname ${UWAC_LIBRARIES}) - find_library(FOUND_LIB NAMES ${libname} - PATHS ${UWAC_LIBRARY_DIRS} - ) - - if (FOUND_LIB) - list(APPEND UWAC_LIBS ${FOUND_LIB}) - endif() - unset(FOUND_LIB CACHE) - endforeach() - - - find_path(UWAC_INCLUDE_DIR NAMES uwac/uwac.h - PATHS ${UWAC_INCLUDE_DIRS} - DOC "The UWAC include directory" - ) - + pkg_check_modules(WAYLAND_SCANNER_PKG wayland-scanner) + pkg_check_modules(WAYLAND_CLIENT wayland-client) + pkg_check_modules(XKBCOMMON xkbcommon) endif() +find_program(WAYLAND_SCANNER wayland-scanner + HINTS "${WAYLAND_SCANNER_PREFIX}/bin" +) + +find_path(WAYLAND_INCLUDE_DIR wayland-client.h + HINTS ${WAYLAND_CLIENT_INCLUDE_DIRS} +) + +find_library(WAYLAND_LIBS + NAMES "wayland-client" + HINTS "${WAYLAND_CLIENT_LIBRARIES}" +) + +find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h + HINTS ${XKBCOMMON_INCLUDE_DIRS} +) + +find_library(XKBCOMMON_LIBS + NAMES xkbcommon + HINTS "${XKBCOMMON_LIBRARIES}" +) + include(FindPackageHandleStandardArgs) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG UWAC_LIBS UWAC_INCLUDE_DIR) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_SCANNER WAYLAND_INCLUDE_DIR WAYLAND_LIBS XKBCOMMON_INCLUDE_DIR XKBCOMMON_LIBS) diff --git a/uwac/CMakeLists.txt b/uwac/CMakeLists.txt new file mode 100644 index 000000000..cbfecb86a --- /dev/null +++ b/uwac/CMakeLists.txt @@ -0,0 +1,20 @@ +# UWAC: Using Wayland As Client +# cmake build script +# +# Copyright 2015 David FORT +# +# 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. + +add_subdirectory(include) +add_subdirectory(libuwac) + diff --git a/uwac/include/CMakeLists.txt b/uwac/include/CMakeLists.txt new file mode 100644 index 000000000..b6e7129b1 --- /dev/null +++ b/uwac/include/CMakeLists.txt @@ -0,0 +1,20 @@ +# UWAC: Using Wayland As Client +# cmake build script +# +# Copyright 2015 David FORT +# +# 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. + +file(GLOB UWAC_HEADERS "uwac/*.h") +install(FILES ${UWAC_HEADERS} DESTINATION include/uwac COMPONENT headers) + diff --git a/uwac/include/uwac/uwac-tools.h b/uwac/include/uwac/uwac-tools.h new file mode 100644 index 000000000..600727b5a --- /dev/null +++ b/uwac/include/uwac/uwac-tools.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_TOOLS_H_ +#define __UWAC_TOOLS_H_ + +#include +#include + +/** @brief */ +struct uwac_touch_point { + uint32_t id; + wl_fixed_t x, y; +}; +typedef struct uwac_touch_point UwacTouchPoint; + +struct uwac_touch_automata; +typedef struct uwac_touch_automata UwacTouchAutomata; + +/** + * + * @param automata + */ +void UwacTouchAutomataInit(UwacTouchAutomata *automata); + +/** + * + * @param automata + */ +void UwacTouchAutomataReset(UwacTouchAutomata *automata); + + +/** + * + * @param automata + * @param event + * @return + */ +bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event); + +#endif /* __UWAC_TOOLS_H_ */ diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h new file mode 100644 index 000000000..39fafa68e --- /dev/null +++ b/uwac/include/uwac/uwac.h @@ -0,0 +1,480 @@ +/* + * Copyright © 2014-2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_H_ +#define __UWAC_H_ + +#include +#include + +typedef struct uwac_size UwacSize; +typedef struct uwac_display UwacDisplay; +typedef struct uwac_output UwacOutput; +typedef struct uwac_window UwacWindow; +typedef struct uwac_seat UwacSeat; + + +/** @brief error codes */ +typedef enum { + UWAC_SUCCESS = 0, + UWAC_ERROR_NOMEMORY, + UWAC_ERROR_UNABLE_TO_CONNECT, + UWAC_ERROR_INVALID_DISPLAY, + UWAC_NOT_ENOUGH_RESOURCES, + UWAC_TIMEDOUT, + UWAC_NOT_FOUND, + UWAC_ERROR_CLOSED, + UWAC_ERROR_INTERNAL, + + UWAC_ERROR_LAST, +} UwacReturnCode; + +/** @brief input modifiers */ +enum { + UWAC_MOD_SHIFT_MASK = 0x01, + UWAC_MOD_ALT_MASK = 0x02, + UWAC_MOD_CONTROL_MASK = 0x04, +}; + +/** @brief a rectangle size measure */ +struct uwac_size { + int width; + int height; +}; + + +/** @brief event types */ +enum { + UWAC_EVENT_NEW_SEAT = 0, + UWAC_EVENT_REMOVED_SEAT, + UWAC_EVENT_NEW_OUTPUT, + UWAC_EVENT_CONFIGURE, + UWAC_EVENT_POINTER_ENTER, + UWAC_EVENT_POINTER_LEAVE, + UWAC_EVENT_POINTER_MOTION, + UWAC_EVENT_POINTER_BUTTONS, + UWAC_EVENT_POINTER_AXIS, + UWAC_EVENT_KEYBOARD_ENTER, + UWAC_EVENT_KEY, + UWAC_EVENT_TOUCH_FRAME_BEGIN, + UWAC_EVENT_TOUCH_UP, + UWAC_EVENT_TOUCH_DOWN, + UWAC_EVENT_TOUCH_MOTION, + UWAC_EVENT_TOUCH_CANCEL, + UWAC_EVENT_TOUCH_FRAME_END, + UWAC_EVENT_FRAME_DONE, + UWAC_EVENT_CLOSE, +}; + +/** @brief window states */ +enum { + UWAC_WINDOW_MAXIMIZED = 0x1, + UWAC_WINDOW_RESIZING = 0x2, + UWAC_WINDOW_FULLSCREEN = 0x4, + UWAC_WINDOW_ACTIVATED = 0x8, +}; + +struct uwac_new_output_event { + int type; + UwacOutput *output; +}; +typedef struct uwac_new_output_event UwacOutputNewEvent; + +struct uwac_new_seat_event { + int type; + UwacSeat *seat; +}; +typedef struct uwac_new_seat_event UwacSeatNewEvent; + +typedef struct uwac_new_seat_event UwacSeatRemovedEvent; + +struct uwac_keyboard_enter_event { + int type; + UwacWindow *window; + UwacSeat *seat; +}; +typedef struct uwac_keyboard_enter_event UwacKeyboardEnterLeaveEvent; + +struct uwac_pointer_enter_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; +}; +typedef struct uwac_pointer_enter_event UwacPointerEnterLeaveEvent; + +struct uwac_pointer_motion_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; +}; +typedef struct uwac_pointer_motion_event UwacPointerMotionEvent; + +struct uwac_pointer_button_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; + uint32_t button; + enum wl_pointer_button_state state; +}; +typedef struct uwac_pointer_button_event UwacPointerButtonEvent; + +struct uwac_pointer_axis_event { + int type; + UwacWindow *window; + UwacSeat *seat; + uint32_t x, y; + uint32_t axis; + wl_fixed_t value; +}; +typedef struct uwac_pointer_axis_event UwacPointerAxisEvent; + +struct uwac_touch_frame_event { + int type; + UwacWindow *window; + UwacSeat *seat; +}; +typedef struct uwac_touch_frame_event UwacTouchFrameBegin; +typedef struct uwac_touch_frame_event UwacTouchFrameEnd; +typedef struct uwac_touch_frame_event UwacTouchCancel; + +struct uwac_touch_data { + int type; + UwacWindow *window; + UwacSeat *seat; + int32_t id; + wl_fixed_t x; + wl_fixed_t y; +}; +typedef struct uwac_touch_data UwacTouchUp; +typedef struct uwac_touch_data UwacTouchDown; +typedef struct uwac_touch_data UwacTouchMotion; + +struct uwac_frame_done_event { + int type; + UwacWindow *window; +}; +typedef struct uwac_frame_done_event UwacFrameDoneEvent; + +struct uwac_configure_event { + int type; + UwacWindow *window; + int32_t width; + int32_t height; + int states; +}; +typedef struct uwac_configure_event UwacConfigureEvent; + +struct uwac_key_event { + int type; + UwacWindow *window; + uint32_t raw_key; + uint32_t sym; + bool pressed; +}; +typedef struct uwac_key_event UwacKeyEvent; + +struct uwac_close_event { + int type; + UwacWindow *window; +}; +typedef struct uwac_close_event UwacCloseEvent; + + +/** @brief */ +union uwac_event { + int type; + UwacOutputNewEvent output_new; + UwacSeatNewEvent seat_new; + UwacPointerEnterLeaveEvent mouse_enter_leave; + UwacPointerMotionEvent mouse_motion; + UwacPointerButtonEvent mouse_button; + UwacPointerAxisEvent mouse_axis; + UwacKeyboardEnterLeaveEvent keyboard_enter_leave; + UwacKeyEvent key; + UwacTouchFrameBegin touchFrameBegin; + UwacTouchUp touchUp; + UwacTouchDown touchDown; + UwacTouchMotion touchMotion; + UwacTouchFrameEnd touchFrameEnd; + UwacTouchCancel touchCancel; + UwacFrameDoneEvent frame_done; + UwacConfigureEvent configure; + UwacCloseEvent close; +}; +typedef union uwac_event UwacEvent; + +typedef bool (*UwacErrorHandler)(UwacDisplay *d, UwacReturnCode code, const char *msg, ...); + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * install a handler that will be called when UWAC encounter internal errors. The + * handler is supposed to answer if the execution can continue. I can also be used + * to log things. + * + * @param handler + */ +void UwacInstallErrorHandler(UwacErrorHandler handler); + + +/** + * Opens the corresponding wayland display, using NULL you will open the default + * display. + * + * @param name the name of the display to open + * @return the created UwacDisplay object + */ +UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err); + +/** + * closes the corresponding UwacDisplay + * + * @param pdisplay a pointer on the display to close + * @return UWAC_SUCCESS if the operation was successful, the corresponding error otherwise + */ +UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay); + +/** + * Returns the file descriptor associated with the UwacDisplay, this is useful when + * you want to poll that file descriptor for activity. + * + * @param display an opened UwacDisplay + * @return the corresponding descriptor + */ +int UwacDisplayGetFd(UwacDisplay *display); + +/** + * Returns a human readable form of a Uwac error code + * + * @param error the error number + * @return the associated string + */ +const char *UwacErrorString(UwacReturnCode error); + +/** + * returns the last error that occurred on a display + * + * @param display the display + * @return the last error that have been set for this display + */ +UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display); + +/** + * retrieves the version of a given interface + * + * @param display the display connection + * @param name the name of the interface + * @param version the output variable for the version + * @return UWAC_SUCCESS if the interface was found, UWAC_NOT_FOUND otherwise + */ +UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version); + +/** + * returns the number SHM formats that have been reported by the compositor + * + * @param display a connected UwacDisplay + * @return the number of SHM formats supported + */ +uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display); + +/** + * returns the supported ShmFormats + * + * @param display a connected UwacDisplay + * @param formats a pointer on an array of wl_shm_format with enough place for formats_size items + * @param formats_size the size of the formats array + * @param filled the number of filled entries in the formats array + * @return UWAC_SUCCESS on success, an error otherwise + */ +UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled); + +/** + * returns the number of registered outputs + * + * @param display the display to query + * @return the number of outputs + */ +uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display); + +/** + * retrieve a particular UwacOutput object + * + * @param display the display to query + * @param index index of the output + * @return the given UwacOutput, NULL if something failed (so you should query UwacDisplayGetLastError() to have the reason) + */ +UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index); + +/** + * retrieve the resolution of a given UwacOutput + * + * @param output the UwacOutput + * @param resolution a pointer on the + * @return UWAC_SUCCESS on success + */ +UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution); + + +/** + * creates a window using a SHM surface + * + * @param display the display to attach the window to + * @param width the width of the window + * @param height the heigh of the window + * @param format format to use for the SHM surface + * @return the created UwacWindow, NULL if something failed (use UwacDisplayGetLastError() to know more about this) + */ +UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format); + +/** + * destroys the corresponding UwacWindow + * + * @param window a pointer on the UwacWindow to destroy + * @return if the operation completed successfully + */ +UwacReturnCode UwacDestroyWindow(UwacWindow **window); + +/** + * Sets the region that should be considered opaque to the compositor. + * + * @param window the UwacWindow + * @param x + * @param y + * @param width + * @param height + * @return UWAC_SUCCESS on success, an error otherwise + */ +UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + +/** + * Sets the region of the window that can trigger input events + * + * @param window the UwacWindow + * @param x + * @param y + * @param width + * @param height + * @return + */ +UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + +/** + * retrieves a pointer on the current window content to draw a frame + * @param window the UwacWindow + * @return a pointer on the current window content + */ +void *UwacWindowGetDrawingBuffer(UwacWindow *window); + +/** + * sets a rectangle as dirty for the next frame of a window + * + * @param window the UwacWindow + * @param x left coordinate + * @param y top coordinate + * @param width the width of the dirty rectangle + * @param height the height of the dirty rectangle + * @return UWAC_SUCCESS on success, an Uwac error otherwise + */ +UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); + +/** + * Sends a frame to the compositor with the content of the drawing buffer + * + * @param window the UwacWindow to refresh + * @param copyContentForNextFrame if true the content to display is copied in the next drawing buffer + * @return UWAC_SUCCESS if the operation was successful + */ +UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame); + +/** + * returns the geometry of the given UwacWindows + * + * @param window the UwacWindow + * @param geometry the geometry to fill + * @return UWAC_SUCCESS on success, an Uwac error otherwise + */ +UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry); + +/** + * Sets or unset the fact that the window is set fullscreen. After this call the + * application should get prepared to receive a configure event. The output is used + * only when going fullscreen, it is optional and not used when exiting fullscreen. + * + * @param window the UwacWindow + * @param output an optional UwacOutput to put the window fullscreen on + * @param isFullscreen set or unset fullscreen + * @return UWAC_SUCCESS if the operation was a success + */ +UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen); + +/** + * When possible (depending on the shell) sets the title of the UwacWindow + * + * @param window the UwacWindow + * @param name title + */ +void UwacWindowSetTitle(UwacWindow *window, const char *name); + +/** + * + * @param display + * @param timeout + * @return + */ +int UwacDisplayDispatch(UwacDisplay *display, int timeout); + +/** + * Returns if you have some pending events, and you can UwacNextEvent() without blocking + * + * @param display the UwacDisplay + * @return if there's some pending events + */ +bool UwacHasEvent(UwacDisplay *display); + +/** Waits until an event occurs, and when it's there copy the event from the queue to + * event. + * + * @param display the Uwac display + * @param event the event to fill + * @return if the operation completed successfully + */ +UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event); + + +/** + * returns the name of the given UwacSeat + * + * @param seat the UwacSeat + * @return the name of the seat + */ +const char *UwacSeatGetName(const UwacSeat *seat); + +#ifdef __cplusplus +} +#endif + +#endif /* __UWAC_H_ */ diff --git a/uwac/libuwac/.gitignore b/uwac/libuwac/.gitignore new file mode 100644 index 000000000..11b3543b4 --- /dev/null +++ b/uwac/libuwac/.gitignore @@ -0,0 +1,7 @@ +fullscreen-shell-client-protocol.h +fullscreen-shell-protocol.c +ivi-application-client-protocol.h +ivi-application-protocol.c +xdg-shell-client-protocol.h +xdg-shell-protocol.c + diff --git a/uwac/libuwac/CMakeLists.txt b/uwac/libuwac/CMakeLists.txt new file mode 100644 index 000000000..b8219bba2 --- /dev/null +++ b/uwac/libuwac/CMakeLists.txt @@ -0,0 +1,79 @@ +# UWAC: Using Wayland As Client +# +# Copyright 2015 David FORT +# +# 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. + +set(MODULE_NAME "uwac") +set(MODULE_PREFIX "UWAC") + + +set(GENERATED_SOURCES "") +macro(generate_protocol_file PROTO) + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c" + COMMAND ${WAYLAND_SCANNER} code < ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml > ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c + DEPENDS ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml + ) + + add_custom_command( + OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h" + COMMAND ${WAYLAND_SCANNER} client-header < ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml > ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h + DEPENDS ${CMAKE_SOURCE_DIR}/uwac/protocols/${PROTO}.xml + ) + + list(APPEND GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-client-protocol.h) + list(APPEND GENERATED_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/${PROTO}-protocol.c) +endmacro() + +generate_protocol_file(xdg-shell) +generate_protocol_file(ivi-application) +generate_protocol_file(fullscreen-shell) + +include_directories(${WAYLAND_INCLUDE_DIR}) +include_directories(${XKBCOMMON_INCLUDE_DIR}) +include_directories("${CMAKE_SOURCE_DIR}/uwac/include") +include_directories("${CMAKE_BINARY_DIR}/uwac/include") + +add_definitions(-DBUILD_IVI -DBUILD_FULLSCREEN_SHELL -DENABLE_XKBCOMMON) + +set(${MODULE_PREFIX}_SRCS + ${GENERATED_SOURCES} + uwac-display.c + uwac-input.c + uwac-os.c + uwac-os.h + uwac-output.c + uwac-priv.h + uwac-tools.c + uwac-utils.c + uwac-window.c) + + +add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + + +if (WITH_LIBRARY_VERSIONING) + #set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${UWAC_VERSION} SOVERSION ${UWAC_API_VERSION}) +endif() + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBS} ${XKBCOMMON_LIBS}) + +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT Uwac) + + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "uwac") + +if(BUILD_TESTING) +# add_subdirectory(test) +endif() diff --git a/uwac/libuwac/uwac-display.c b/uwac/libuwac/uwac-display.c new file mode 100644 index 000000000..2fa20b490 --- /dev/null +++ b/uwac/libuwac/uwac-display.c @@ -0,0 +1,631 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "uwac-os.h" + +#define TARGET_COMPOSITOR_INTERFACE 3 +#define TARGET_SHM_INTERFACE 1 +#define TARGET_SHELL_INTERFACE 1 +#define TARGET_DDM_INTERFACE 1 +#define TARGET_SEAT_INTERFACE 5 +#define TARGET_XDG_VERSION 5 /* The version of xdg-shell that we implement */ + +static const char *event_names[] = { + "new seat", + "removed seat", + "new output", + "configure", + "pointer enter", + "pointer leave", + "pointer motion", + "pointer buttons", + "pointer axis", + "keyboard enter", + "key", + "touch frame begin", + "touch up", + "touch down", + "touch motion", + "touch cancel", + "touch frame end", + "frame done", + "close", + NULL +}; + +bool uwac_default_error_handler(UwacDisplay *display, UwacReturnCode code, const char *msg, ...) { + va_list args; + va_start(args, msg); + + vfprintf(stderr, "%s", args); + return false; +} + +UwacErrorHandler uwacErrorHandler = uwac_default_error_handler; + +void UwacInstallErrorHandler(UwacErrorHandler handler) { + if (handler) + uwacErrorHandler = handler; + else + uwacErrorHandler = uwac_default_error_handler; +} + + +static void cb_shm_format(void *data, struct wl_shm *wl_shm, uint32_t format) +{ + UwacDisplay *d = data; + + if (format == WL_SHM_FORMAT_RGB565) + d->has_rgb565 = true; + + d->shm_formats_nb++; + d->shm_formats = xrealloc((void *)d->shm_formats, sizeof(enum wl_shm_format) * d->shm_formats_nb); + d->shm_formats[d->shm_formats_nb - 1] = format; +} + + +struct wl_shm_listener shm_listener = { + cb_shm_format +}; + +static void xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial) +{ + xdg_shell_pong(shell, serial); +} + +static const struct xdg_shell_listener xdg_shell_listener = { + xdg_shell_ping, +}; + +#ifdef BUILD_FULLSCREEN_SHELL +static void fullscreen_capability(void *data, struct _wl_fullscreen_shell *_wl_fullscreen_shell, + uint32_t capabilty) +{ +} + +static const struct _wl_fullscreen_shell_listener fullscreen_shell_listener = { + fullscreen_capability, +}; +#endif + + +static UwacSeat *display_destroy_seat(UwacDisplay *d, uint32_t name) +{ + UwacSeat *seat; + + wl_list_for_each(seat, &d->seats, link) { + if (seat->seat_id == name) { + UwacSeatDestroy(seat); + return seat; + } + } + + return NULL; +} + +static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, + const char *interface, uint32_t version) +{ + UwacDisplay *d = data; + UwacGlobal *global; + + global = xmalloc(sizeof *global); + global->name = id; + global->interface = xstrdup(interface); + global->version = version; + wl_list_insert(d->globals.prev, &global->link); + + if (strcmp(interface, "wl_compositor") == 0) { + d->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, min(TARGET_COMPOSITOR_INTERFACE, version)); + } else if (strcmp(interface, "wl_shm") == 0) { + d->shm = wl_registry_bind(registry, id, &wl_shm_interface, min(TARGET_SHM_INTERFACE, version)); + wl_shm_add_listener(d->shm, &shm_listener, d); + } else if (strcmp(interface, "wl_output") == 0) { + UwacOutput *output; + UwacOutputNewEvent *ev; + + output = UwacCreateOutput(d, id, version); + if (!output) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create output\n")); + return; + } + + ev = (UwacOutputNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_OUTPUT); + if (ev) + ev->output = output; + + } else if (strcmp(interface, "wl_seat") == 0) { + UwacSeatNewEvent *ev; + UwacSeat *seat; + + seat = UwacSeatNew(d, id, min(version, TARGET_SEAT_INTERFACE)); + if (!seat) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat\n")); + return; + } + + ev = (UwacSeatNewEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_NEW_SEAT); + if (!ev) { + assert(uwacErrorHandler(d, UWAC_ERROR_NOMEMORY, "unable to create new seat event\n")); + return; + } + + ev->seat = seat; + } else if (strcmp(interface, "wl_data_device_manager") == 0) { + d->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, min(TARGET_DDM_INTERFACE, version)); + } else if (strcmp(interface, "wl_shell") == 0) { + d->shell = wl_registry_bind(registry, id, &wl_shell_interface, min(TARGET_SHELL_INTERFACE, version)); + } else if (strcmp(interface, "xdg_shell") == 0) { + d->xdg_shell = wl_registry_bind(registry, id, &xdg_shell_interface, 1); + xdg_shell_use_unstable_version(d->xdg_shell, TARGET_XDG_VERSION); + xdg_shell_add_listener(d->xdg_shell, &xdg_shell_listener, d); +#if BUILD_IVI + } else if (strcmp(interface, "ivi_application") == 0) { + d->ivi_application = wl_registry_bind(registry, id, &ivi_application_interface, 1); +#endif +#if BUILD_FULLSCREEN_SHELL + } else if (strcmp(interface, "_wl_fullscreen_shell") == 0) { + d->fullscreen_shell = wl_registry_bind(registry, id, &_wl_fullscreen_shell_interface, 1); + _wl_fullscreen_shell_add_listener(d->fullscreen_shell, &fullscreen_shell_listener, d); +#endif +#if 0 + } else if (strcmp(interface, "text_cursor_position") == 0) { + d->text_cursor_position = wl_registry_bind(registry, id, &text_cursor_position_interface, 1); + } else if (strcmp(interface, "workspace_manager") == 0) { + //init_workspace_manager(d, id); + } else if (strcmp(interface, "wl_subcompositor") == 0) { + d->subcompositor = wl_registry_bind(registry, id, &wl_subcompositor_interface, 1); +#endif + } +} + +static void registry_handle_global_remove(void *data, struct wl_registry *registry, uint32_t name) { + UwacDisplay *d = data; + UwacGlobal *global; + UwacGlobal *tmp; + + wl_list_for_each_safe(global, tmp, &d->globals, link) { + if (global->name != name) + continue; + +#if 0 + if (strcmp(global->interface, "wl_output") == 0) + display_destroy_output(d, name); +#endif + + if (strcmp(global->interface, "wl_seat") == 0) { + UwacSeatRemovedEvent *ev; + UwacSeat *seat; + + seat = display_destroy_seat(d, name); + ev = (UwacSeatRemovedEvent *)UwacDisplayNewEvent(d, UWAC_EVENT_REMOVED_SEAT); + if (ev) + ev->seat = seat; + } + + + wl_list_remove(&global->link); + free(global->interface); + free(global); + } +} + +void UwacDestroyGlobal(UwacGlobal *global) { + free(global->interface); + wl_list_remove(&global->link); + free(global); +} + +void *display_bind(UwacDisplay *display, uint32_t name, const struct wl_interface *interface, uint32_t version) { + return wl_registry_bind(display->registry, name, interface, version); +} + +static const struct wl_registry_listener registry_listener = { + registry_handle_global, + registry_handle_global_remove +}; + + +int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task) { + struct epoll_event ep; + + ep.events = events; + ep.data.ptr = task; + return epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep); +} + +void UwacDisplayUnwatchFd(UwacDisplay *display, int fd) { + epoll_ctl(display->epoll_fd, EPOLL_CTL_DEL, fd, NULL); +} + +static void display_exit(UwacDisplay *display) { + display->running = false; +} + +static void display_dispatch_events(UwacTask *task, uint32_t events) +{ + UwacDisplay *display = container_of(task, UwacDisplay, dispatch_fd_task); + struct epoll_event ep; + int ret; + + display->display_fd_events = events; + + if ((events & EPOLLERR) || (events & EPOLLHUP)) { + display_exit(display); + return; + } + + if (events & EPOLLIN) { + ret = wl_display_dispatch(display->display); + if (ret == -1) { + display_exit(display); + return; + } + } + + if (events & EPOLLOUT) { + ret = wl_display_flush(display->display); + if (ret == 0) { + ep.events = EPOLLIN | EPOLLERR | EPOLLHUP; + ep.data.ptr = &display->dispatch_fd_task; + epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep); + } else if (ret == -1 && errno != EAGAIN) { + display_exit(display); + return; + } + } +} + + +UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err) { + UwacDisplay *ret; + + ret = (UwacDisplay *)calloc(1, sizeof(*ret)); + if (!ret) { + *err = UWAC_ERROR_NOMEMORY; + return NULL; + } + + wl_list_init(&ret->globals); + wl_list_init(&ret->seats); + wl_list_init(&ret->outputs); + wl_list_init(&ret->windows); + + ret->display = wl_display_connect(name); + if (ret->display == NULL) { + fprintf(stderr, "failed to connect to Wayland display %s: %m\n", name); + *err = UWAC_ERROR_UNABLE_TO_CONNECT; + goto out_free; + } + + ret->epoll_fd = uwac_os_epoll_create_cloexec(); + if (ret->epoll_fd < 0) { + *err = UWAC_NOT_ENOUGH_RESOURCES; + goto out_disconnect; + } + + ret->display_fd = wl_display_get_fd(ret->display); + + ret->registry = wl_display_get_registry(ret->display); + if (!ret->registry) { + *err = UWAC_ERROR_NOMEMORY; + goto out_close_epoll; + } + + wl_registry_add_listener(ret->registry, ®istry_listener, ret); + + if ((wl_display_roundtrip(ret->display) < 0) || (wl_display_roundtrip(ret->display) < 0)) { + uwacErrorHandler(ret, UWAC_ERROR_UNABLE_TO_CONNECT, "Failed to process Wayland connection: %m\n"); + *err = UWAC_ERROR_UNABLE_TO_CONNECT; + goto out_free_registry; + } + + ret->dispatch_fd_task.run = display_dispatch_events; + if (UwacDisplayWatchFd(ret, ret->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP, &ret->dispatch_fd_task) < 0) { + uwacErrorHandler(ret, UWAC_ERROR_INTERNAL, "unable to watch display fd: %m\n"); + *err = UWAC_ERROR_INTERNAL; + goto out_free_registry; + } + + ret->running = true; + ret->last_error = *err = UWAC_SUCCESS; + return ret; + +out_free_registry: + wl_registry_destroy(ret->registry); +out_close_epoll: + close(ret->epoll_fd); +out_disconnect: + wl_display_disconnect(ret->display); +out_free: + free(ret); + return NULL; +} + +int UwacDisplayDispatch(UwacDisplay *display, int timeout) { + int ret, count, i; + UwacTask *task; + struct epoll_event ep[16]; + + wl_display_dispatch_pending(display->display); + + if (!display->running) + return 0; + + ret = wl_display_flush(display->display); + if (ret < 0 && errno == EAGAIN) { + ep[0].events = (EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLHUP); + ep[0].data.ptr = &display->dispatch_fd_task; + + epoll_ctl(display->epoll_fd, EPOLL_CTL_MOD, display->display_fd, &ep[0]); + } else if (ret < 0) { + return -1; + } + + count = epoll_wait(display->epoll_fd, ep, ARRAY_LENGTH(ep), timeout); + for (i = 0; i < count; i++) { + task = ep[i].data.ptr; + task->run(task, ep[i].events); + } + + return 1; +} + + + +UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display) { + return display->last_error; +} + +UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay) { + UwacDisplay *display; + UwacSeat *seat, *tmpSeat; + UwacWindow *window, *tmpWindow; + UwacOutput *output, *tmpOutput; + UwacGlobal *global, *tmpGlobal; + + assert(pdisplay); + display = *pdisplay; + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + /* destroy windows */ + wl_list_for_each_safe(window, tmpWindow, &display->windows, link) { + UwacDestroyWindow(&window); + } + + /* destroy seats */ + wl_list_for_each_safe(seat, tmpSeat, &display->seats, link) { + UwacSeatDestroy(seat); + } + + /* destroy output */ + wl_list_for_each_safe(output, tmpOutput, &display->outputs, link) { + UwacDestroyOutput(output); + } + + /* destroy globals */ + wl_list_for_each_safe(global, tmpGlobal, &display->globals, link) { + UwacDestroyGlobal(global); + } + + if (display->compositor) + wl_compositor_destroy(display->compositor); +#ifdef BUILD_FULLSCREEN_SHELL + if (display->fullscreen_shell) + _wl_fullscreen_shell_destroy(display->fullscreen_shell); +#endif +#ifdef BUILD_IVI + if (display->ivi_application) + ivi_application_destroy(display->ivi_application); +#endif + if (display->xdg_shell) + xdg_shell_destroy(display->xdg_shell); + if (display->shell) + wl_shell_destroy(display->shell); + if (display->shm) + wl_shm_destroy(display->shm); + if (display->subcompositor) + wl_subcompositor_destroy(display->subcompositor); + if (display->data_device_manager) + wl_data_device_manager_destroy(display->data_device_manager); + + free(display->shm_formats); + wl_registry_destroy(display->registry); + + close(display->epoll_fd); + + wl_display_disconnect(display->display); + + /* cleanup the event queue */ + while (display->push_queue) { + UwacEventListItem *item = display->push_queue; + + display->push_queue = item->tail; + free(item); + } + + free(display); + *pdisplay = NULL; + return UWAC_SUCCESS; +} + +int UwacDisplayGetFd(UwacDisplay *display) { + return display->epoll_fd; +} + +static const char *errorStrings[] = { + "success", + "out of memory error", + "unable to connect to wayland display", + "invalid UWAC display", + "not enough resources", + "timed out", + "not found", + "closed connection", + + "internal error", +}; + +const char *UwacErrorString(UwacReturnCode error) { + if (error < 0 || error >= UWAC_ERROR_LAST) + return "invalid error code"; + + return errorStrings[error]; +} + +UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version) { + const UwacGlobal *global; + + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + wl_list_for_each(global, &display->globals, link) { + if (strcmp(global->interface, name) == 0) { + if (version) + *version = global->version; + return UWAC_SUCCESS; + } + } + + return UWAC_NOT_FOUND; +} + +uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display) { + if (!display) { + display->last_error = UWAC_ERROR_INVALID_DISPLAY; + return 0; + } + + if (!display->shm) { + display->last_error = UWAC_NOT_FOUND; + return 0; + } + + display->last_error = UWAC_SUCCESS; + return display->shm_formats_nb; +} + + +UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled) { + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + *filled = min(display->shm_formats_nb, formats_size); + memcpy(formats, (const void *)display->shm_formats, *filled * sizeof(enum wl_shm_format)); + + return UWAC_SUCCESS; +} + +uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display) { + return wl_list_length(&display->outputs); +} + +UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index) { + struct wl_list *l; + int i; + + for (i = 0, l = &display->outputs; l && i < index; i++, l = l->next) + ; + + if (!l) { + display->last_error = UWAC_NOT_FOUND; + return NULL; + } + + display->last_error = UWAC_SUCCESS; + return container_of(l, UwacOutput, link); +} + +UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution) { + *resolution = output->resolution; + return UWAC_SUCCESS; +} + + +UwacEvent *UwacDisplayNewEvent(UwacDisplay *display, int type) { + UwacEventListItem *ret; + + if (!display) { + display->last_error = UWAC_ERROR_INVALID_DISPLAY; + return 0; + } + + ret = zalloc(sizeof(UwacEventListItem)); + if (!ret) { + assert(uwacErrorHandler(display, UWAC_ERROR_NOMEMORY, "unable to allocate a '%s' event", event_names[type])); + display->last_error = UWAC_ERROR_NOMEMORY; + return 0; + } + + ret->event.type = type; + ret->tail = display->push_queue; + if (ret->tail) + ret->tail->head = ret; + else + display->pop_queue = ret; + display->push_queue = ret; + return &ret->event; +} + +bool UwacHasEvent(UwacDisplay *display) { + return display->pop_queue != NULL; +} + + +UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event) { + UwacEventListItem *prevItem; + int ret; + + if (!display) + return UWAC_ERROR_INVALID_DISPLAY; + + while (!display->pop_queue) { + ret = UwacDisplayDispatch(display, 1 * 1000); + if (ret < 0) + return UWAC_ERROR_INTERNAL; + else if (ret == 0) + return UWAC_ERROR_CLOSED; + } + + prevItem = display->pop_queue->head; + *event = display->pop_queue->event; + free(display->pop_queue); + display->pop_queue = prevItem; + if (prevItem) + prevItem->tail = NULL; + else + display->push_queue = NULL; + return UWAC_SUCCESS; +} diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c new file mode 100644 index 000000000..c7dbb83bf --- /dev/null +++ b/uwac/libuwac/uwac-input.c @@ -0,0 +1,831 @@ +/* + * Copyright © 2014-2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +static void keyboard_repeat_func(UwacTask *task, uint32_t events) +{ + UwacSeat *input = container_of(task, UwacSeat, repeat_task); + UwacWindow *window = input->keyboard_focus; + uint64_t exp; + + if (read(input->repeat_timer_fd, &exp, sizeof exp) != sizeof exp) + /* If we change the timer between the fd becoming + * readable and getting here, there'll be nothing to + * read and we get EAGAIN. */ + return; + + if (window) { + UwacKeyEvent *key; + + key = (UwacKeyEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY); + if (!key) + return; + + key->window = window; + key->sym = input->repeat_sym; + key->pressed = true; + } + +} + +static void keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard, + uint32_t format, int fd, uint32_t size) +{ + UwacSeat *input = data; + struct xkb_keymap *keymap; + struct xkb_state *state; + char *map_str; + + if (!data) { + close(fd); + return; + } + + if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) { + close(fd); + return; + } + + map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (map_str == MAP_FAILED) { + close(fd); + return; + } + + keymap = xkb_keymap_new_from_string(input->xkb_context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); + munmap(map_str, size); + close(fd); + + if (!keymap) { + assert(uwacErrorHandler(input->display, UWAC_ERROR_INTERNAL, "failed to compile keymap\n")); + return; + } + + state = xkb_state_new(keymap); + if (!state) { + assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "failed to create XKB state\n")); + xkb_keymap_unref(keymap); + return; + } + + xkb_keymap_unref(input->xkb.keymap); + xkb_state_unref(input->xkb.state); + input->xkb.keymap = keymap; + input->xkb.state = state; + + input->xkb.control_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Control"); + input->xkb.alt_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Mod1"); + input->xkb.shift_mask = 1 << xkb_keymap_mod_get_index(input->xkb.keymap, "Shift"); +} + +static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state_w); + +static void keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, uint32_t serial, + struct wl_surface *surface, struct wl_array *keys) +{ + uint32_t *key, *pressedKey; + UwacSeat *input = (UwacSeat *)data; + int i, found; + UwacKeyboardEnterLeaveEvent *event; + + event = (UwacKeyboardEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEYBOARD_ENTER); + if (!event) + return; + + event->window = input->keyboard_focus = (UwacWindow *)wl_surface_get_user_data(surface); + + /* look for keys that have been released */ + found = false; + for (pressedKey = input->pressed_keys.data, i = 0; i < input->pressed_keys.size; i += sizeof(uint32_t)) { + wl_array_for_each(key, keys) { + if (*key == *pressedKey) { + found = true; + break; + } + } + + if (!found) { + keyboard_handle_key(data, keyboard, serial, 0, *pressedKey, WL_KEYBOARD_KEY_STATE_RELEASED); + } else { + pressedKey++; + } + } + + /* handle keys that are now pressed */ + wl_array_for_each(key, keys) { + keyboard_handle_key(data, keyboard, serial, 0, *key, WL_KEYBOARD_KEY_STATE_PRESSED); + } +} + +static void keyboard_handle_leave(void *data, struct wl_keyboard *keyboard, uint32_t serial, + struct wl_surface *surface) +{ + struct itimerspec its; + UwacSeat *input; + UwacPointerEnterLeaveEvent *event; + + input = (UwacSeat *)data; + + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 0; + timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); + + event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE); + if (!event) + return; + + event->window = input->keyboard_focus; +} + +static int update_key_pressed(UwacSeat *seat, uint32_t key) { + uint32_t *keyPtr; + + /* check if the key is not already pressed */ + wl_array_for_each(keyPtr, &seat->pressed_keys) { + if (*keyPtr == key) + return 1; + } + + keyPtr = wl_array_add(&seat->pressed_keys, sizeof(uint32_t)); + if (!keyPtr) + return -1; + + *keyPtr = key; + return 0; +} + +static int update_key_released(UwacSeat *seat, uint32_t key) { + uint32_t *keyPtr; + int i, toMove; + bool found = false; + + for (i = 0, keyPtr = seat->pressed_keys.data; i < seat->pressed_keys.size; i++, keyPtr++) { + if (*keyPtr == key) { + found = true; + break; + } + } + + if (found) { + toMove = seat->pressed_keys.size - ((i + 1) * sizeof(uint32_t)); + if (toMove) + memmove(keyPtr, keyPtr+1, toMove); + + seat->pressed_keys.size -= sizeof(uint32_t); + } + return 1; + +} + +static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, + uint32_t serial, uint32_t time, uint32_t key, + uint32_t state_w) +{ + UwacSeat *input = (UwacSeat *)data; + UwacWindow *window = input->keyboard_focus; + UwacKeyEvent *keyEvent; + + uint32_t code, num_syms; + enum wl_keyboard_key_state state = state_w; + const xkb_keysym_t *syms; + xkb_keysym_t sym; + struct itimerspec its; + + if (state_w == WL_KEYBOARD_KEY_STATE_PRESSED) + update_key_pressed(input, key); + else + update_key_released(input, key); + + input->display->serial = serial; + code = key + 8; + if (!window || !input->xkb.state) + return; + + /* We only use input grabs for pointer events for now, so just + * ignore key presses if a grab is active. We expand the key + * event delivery mechanism to route events to widgets to + * properly handle key grabs. In the meantime, this prevents + * key event delivery while a grab is active. */ + /*if (input->grab && input->grab_button == 0) + return;*/ + + num_syms = xkb_state_key_get_syms(input->xkb.state, code, &syms); + + sym = XKB_KEY_NoSymbol; + if (num_syms == 1) + sym = syms[0]; + + if (state == WL_KEYBOARD_KEY_STATE_RELEASED && key == input->repeat_key) { + its.it_interval.tv_sec = 0; + its.it_interval.tv_nsec = 0; + its.it_value.tv_sec = 0; + its.it_value.tv_nsec = 0; + timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); + } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED && xkb_keymap_key_repeats(input->xkb.keymap, code)) { + input->repeat_sym = sym; + input->repeat_key = key; + input->repeat_time = time; + its.it_interval.tv_sec = input->repeat_rate_sec; + its.it_interval.tv_nsec = input->repeat_rate_nsec; + its.it_value.tv_sec = input->repeat_delay_sec; + its.it_value.tv_nsec = input->repeat_delay_nsec; + timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); + } + + keyEvent = (UwacKeyEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_KEY); + if (!keyEvent) + return; + + keyEvent->window = window; + keyEvent->sym = sym; + keyEvent->raw_key = key; + keyEvent->pressed = (state == WL_KEYBOARD_KEY_STATE_PRESSED); +} + +static void keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard, uint32_t serial, + uint32_t mods_depressed, uint32_t mods_latched, uint32_t mods_locked, uint32_t group) +{ + UwacSeat *input = data; + xkb_mod_mask_t mask; + + /* If we're not using a keymap, then we don't handle PC-style modifiers */ + if (!input->xkb.keymap) + return; + + xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched, mods_locked, 0, 0, group); + mask = xkb_state_serialize_mods(input->xkb.state, XKB_STATE_MODS_DEPRESSED | XKB_STATE_MODS_LATCHED); + input->modifiers = 0; + if (mask & input->xkb.control_mask) + input->modifiers |= UWAC_MOD_CONTROL_MASK; + if (mask & input->xkb.alt_mask) + input->modifiers |= UWAC_MOD_ALT_MASK; + if (mask & input->xkb.shift_mask) + input->modifiers |= UWAC_MOD_SHIFT_MASK; +} + +static void set_repeat_info(UwacSeat *input, int32_t rate, int32_t delay) +{ + input->repeat_rate_sec = input->repeat_rate_nsec = 0; + input->repeat_delay_sec = input->repeat_delay_nsec = 0; + + /* a rate of zero disables any repeating, regardless of the delay's + * value */ + if (rate == 0) + return; + + if (rate == 1) + input->repeat_rate_sec = 1; + else + input->repeat_rate_nsec = 1000000000 / rate; + + input->repeat_delay_sec = delay / 1000; + delay -= (input->repeat_delay_sec * 1000); + input->repeat_delay_nsec = delay * 1000 * 1000; +} + + +static void keyboard_handle_repeat_info(void *data, struct wl_keyboard *keyboard, + int32_t rate, int32_t delay) +{ + UwacSeat *input = data; + + set_repeat_info(input, rate, delay); +} + +static const struct wl_keyboard_listener keyboard_listener = { + keyboard_handle_keymap, + keyboard_handle_enter, + keyboard_handle_leave, + keyboard_handle_key, + keyboard_handle_modifiers, + keyboard_handle_repeat_info +}; + +static bool touch_send_start_frame(UwacSeat *seat) { + UwacTouchFrameBegin *ev; + + ev = (UwacTouchFrameBegin *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_BEGIN); + if (!ev) + return false; + + seat->touch_frame_started = true; + return true; +} + +static void touch_handle_down(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, struct wl_surface *surface, + int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + UwacSeat *seat = data; + UwacTouchDown *tdata; + + seat->display->serial = serial; + if (!seat->touch_frame_started && !touch_send_start_frame(seat)) + return; + + tdata = (UwacTouchDown *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_DOWN); + if (!tdata) + return; + + tdata->seat = seat; + tdata->id = id; + tdata->x = x_w; + tdata->y = y_w; + +#if 0 + struct widget *widget; + float sx = wl_fixed_to_double(x); + float sy = wl_fixed_to_double(y); + + + input->touch_focus = wl_surface_get_user_data(surface); + if (!input->touch_focus) { + DBG("Failed to find to touch focus for surface %p\n", surface); + return; + } + + if (surface != input->touch_focus->main_surface->surface) { + DBG("Ignoring input event from subsurface %p\n", surface); + input->touch_focus = NULL; + return; + } + + if (input->grab) + widget = input->grab; + else + widget = window_find_widget(input->touch_focus, + wl_fixed_to_double(x), + wl_fixed_to_double(y)); + if (widget) { + struct touch_point *tp = xmalloc(sizeof *tp); + if (tp) { + tp->id = id; + tp->widget = widget; + tp->x = sx; + tp->y = sy; + wl_list_insert(&input->touch_point_list, &tp->link); + + if (widget->touch_down_handler) + (*widget->touch_down_handler)(widget, input, + serial, time, id, + sx, sy, + widget->user_data); + } + } +#endif +} + +static void touch_handle_up(void *data, struct wl_touch *wl_touch, + uint32_t serial, uint32_t time, int32_t id) +{ + UwacSeat *seat = data; + UwacTouchUp *tdata; + + if (!seat->touch_frame_started && !touch_send_start_frame(seat)) + return; + + tdata = (UwacTouchUp *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_UP); + if (!tdata) + return; + + tdata->seat = seat; + tdata->id = id; + + +#if 0 + struct touch_point *tp, *tmp; + + if (!input->touch_focus) { + DBG("No touch focus found for touch up event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->id != id) + continue; + + if (tp->widget->touch_up_handler) + (*tp->widget->touch_up_handler)(tp->widget, input, serial, + time, id, + tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + + return; + } +#endif +} + +static void touch_handle_motion(void *data, struct wl_touch *wl_touch, + uint32_t time, int32_t id, wl_fixed_t x_w, wl_fixed_t y_w) +{ + UwacSeat *seat = data; + UwacTouchMotion *tdata; + + if (!seat->touch_frame_started && !touch_send_start_frame(seat)) + return; + + tdata = (UwacTouchMotion *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_MOTION); + if (!tdata) + return; + + tdata->seat = seat; + tdata->id = id; + tdata->x = x_w; + tdata->y = y_w; + +#if 0 + struct touch_point *tp; + float sx = wl_fixed_to_double(x); + float sy = wl_fixed_to_double(y); + + DBG("touch_handle_motion: %i %i\n", id, wl_list_length(&seat->touch_point_list)); + + if (!seat->touch_focus) { + DBG("No touch focus found for touch motion event!\n"); + return; + } + + wl_list_for_each(tp, &seat->touch_point_list, link) { + if (tp->id != id) + continue; + + tp->x = sx; + tp->y = sy; + if (tp->widget->touch_motion_handler) + (*tp->widget->touch_motion_handler)(tp->widget, seat, time, + id, sx, sy, + tp->widget->user_data); + return; + } +#endif +} + +static void touch_handle_frame(void *data, struct wl_touch *wl_touch) +{ + UwacSeat *seat = data; + UwacTouchFrameEnd *ev; + + ev = (UwacTouchFrameEnd *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_FRAME_END); + if (!ev) + return; + + ev->seat = seat; + seat->touch_frame_started = false; +} + +static void touch_handle_cancel(void *data, struct wl_touch *wl_touch) +{ + UwacSeat *seat = data; + UwacTouchCancel *ev; + + ev = (UwacTouchCancel *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_TOUCH_CANCEL); + if (!ev) + return; + + ev->seat = seat; + seat->touch_frame_started = false; + +#if 0 + struct touch_point *tp, *tmp; + + DBG("touch_handle_cancel\n"); + + if (!input->touch_focus) { + DBG("No touch focus found for touch cancel event!\n"); + return; + } + + wl_list_for_each_safe(tp, tmp, &input->touch_point_list, link) { + if (tp->widget->touch_cancel_handler) + (*tp->widget->touch_cancel_handler)(tp->widget, input, + tp->widget->user_data); + + wl_list_remove(&tp->link); + free(tp); + } +#endif +} + +static const struct wl_touch_listener touch_listener = { + touch_handle_down, + touch_handle_up, + touch_handle_motion, + touch_handle_frame, + touch_handle_cancel, +}; + + +static void pointer_handle_enter(void *data, struct wl_pointer *pointer, uint32_t serial, + struct wl_surface *surface, wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + UwacSeat *input = data; + UwacWindow *window; + UwacPointerEnterLeaveEvent *event; + + float sx = wl_fixed_to_double(sx_w); + float sy = wl_fixed_to_double(sy_w); + + if (!surface) { + /* enter event for a window we've just destroyed */ + return; + } + + input->display->serial = serial; + window = wl_surface_get_user_data(surface); + if (window) + window->pointer_enter_serial = serial; + input->pointer_focus = window; + input->sx = sx; + input->sy = sy; + + event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_ENTER); + if (!event) + return; + + event->seat = input; + event->window = window; + event->x = sx; + event->y = sy; +} + +static void pointer_handle_leave(void *data, struct wl_pointer *pointer, uint32_t serial, + struct wl_surface *surface) +{ + UwacPointerEnterLeaveEvent *event; + UwacWindow *window; + UwacSeat *input = data; + + input->display->serial = serial; + + event = (UwacPointerEnterLeaveEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_LEAVE); + if (!event) + return; + + window = wl_surface_get_user_data(surface); + + event->seat = input; + event->window = window; + +#if 0 + input_remove_pointer_focus(input); +#endif +} + +static void pointer_handle_motion(void *data, struct wl_pointer *pointer, uint32_t time, + wl_fixed_t sx_w, wl_fixed_t sy_w) +{ + UwacPointerMotionEvent *motion_event; + UwacSeat *input = data; + UwacWindow *window = input->pointer_focus; + + float sx = wl_fixed_to_double(sx_w); + float sy = wl_fixed_to_double(sy_w); + + if (!window) + return; + + input->sx = sx; + input->sy = sy; + + motion_event = (UwacPointerMotionEvent *)UwacDisplayNewEvent(input->display, UWAC_EVENT_POINTER_MOTION); + if (!motion_event) + return; + + motion_event->seat = input; + motion_event->window = window; + motion_event->x = wl_fixed_to_int(sx_w); + motion_event->y = wl_fixed_to_int(sy_w); +} + +static void pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial, + uint32_t time, uint32_t button, uint32_t state_w) +{ + UwacPointerButtonEvent *event; + UwacSeat *seat = data; + UwacWindow *window = seat->pointer_focus; + + seat->display->serial = serial; + + event = (UwacPointerButtonEvent *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_BUTTONS); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->x = seat->sx; + event->y = seat->sy; + event->button = button; + event->state = (enum wl_pointer_button_state)state_w; +} + +static void pointer_handle_axis(void *data, struct wl_pointer *pointer, uint32_t time, + uint32_t axis, wl_fixed_t value) +{ + UwacPointerAxisEvent *event; + UwacSeat *seat = data; + UwacWindow *window = seat->pointer_focus; + + if (!window) + return; + + event = (UwacPointerAxisEvent *)UwacDisplayNewEvent(seat->display, UWAC_EVENT_POINTER_AXIS); + if (!event) + return; + + event->seat = seat; + event->window = window; + event->x = seat->sx; + event->y = seat->sy; + event->axis = axis; + event->value = value; +} + +static const struct wl_pointer_listener pointer_listener = { + pointer_handle_enter, + pointer_handle_leave, + pointer_handle_motion, + pointer_handle_button, + pointer_handle_axis, +}; + + + +static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) +{ + UwacSeat *input = data; + + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) { + input->pointer = wl_seat_get_pointer(seat); + wl_pointer_set_user_data(input->pointer, input); + wl_pointer_add_listener(input->pointer, &pointer_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) { + if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) + wl_pointer_release(input->pointer); + else + wl_pointer_destroy(input->pointer); + input->pointer = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) { + input->keyboard = wl_seat_get_keyboard(seat); + wl_keyboard_set_user_data(input->keyboard, input); + wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) { + if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) + wl_keyboard_release(input->keyboard); + else + wl_keyboard_destroy(input->keyboard); + input->keyboard = NULL; + } + + if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) { + input->touch = wl_seat_get_touch(seat); + wl_touch_set_user_data(input->touch, input); + wl_touch_add_listener(input->touch, &touch_listener, input); + } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { + if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) + wl_touch_release(input->touch); + else + wl_touch_destroy(input->touch); + input->touch = NULL; + } +} + +static void +seat_handle_name(void *data, struct wl_seat *seat, const char *name) +{ + UwacSeat *input = data; + if (input->name) + free(input->name); + + input->name = strdup(name); +} + +static const struct wl_seat_listener seat_listener = { + seat_handle_capabilities, + seat_handle_name, +}; + + +UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version) { + UwacSeat *ret; + + ret = zalloc(sizeof(UwacSeat)); + ret->display = d; + ret->seat_id = id; + ret->seat_version = version; + + wl_array_init(&ret->pressed_keys); + ret->xkb_context = xkb_context_new(0); + if (!ret->xkb_context) { + fprintf(stderr, "%s: unable to allocate a xkb_context\n", __FUNCTION__); + goto error_xkb_context; + } + + ret->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, version); + wl_seat_add_listener(ret->seat, &seat_listener, ret); + wl_seat_set_user_data(ret->seat, ret); + + ret->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK); + if (ret->repeat_timer_fd < 0) { + fprintf(stderr, "%s: error creating repeat timer\n", __FUNCTION__); + goto error_timer_fd; + } + ret->repeat_task.run = keyboard_repeat_func; + if (UwacDisplayWatchFd(d, ret->repeat_timer_fd, EPOLLIN, &ret->repeat_task) < 0) { + fprintf(stderr, "%s: error polling repeat timer\n", __FUNCTION__); + goto error_watch_timerfd; + } + + wl_list_insert(d->seats.prev, &ret->link); + return ret; + +error_watch_timerfd: + close(ret->repeat_timer_fd); +error_timer_fd: + wl_seat_destroy(ret->seat); +error_xkb_context: + free(ret); + return NULL; +} + +void UwacSeatDestroy(UwacSeat *s) { + if (s->seat) { + if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION) + wl_seat_release(s->seat); + else + wl_seat_destroy(s->seat); + } + s->seat = NULL; + + free(s->name); + wl_array_release(&s->pressed_keys); + + xkb_state_unref(s->xkb.state); + xkb_context_unref(s->xkb_context); + + if (s->pointer) { + if (s->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) + wl_pointer_release(s->pointer); + else + wl_pointer_destroy(s->pointer); + } + + if (s->touch) { + if (s->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) + wl_touch_release(s->touch); + else + wl_touch_destroy(s->touch); + } + + if (s->keyboard) { + if (s->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) + wl_keyboard_release(s->keyboard); + else + wl_keyboard_destroy(s->keyboard); + } + + wl_list_remove(&s->link); + free(s); +} + +const char *UwacSeatGetName(const UwacSeat *seat) { + return seat->name; +} diff --git a/uwac/libuwac/uwac-os.c b/uwac/libuwac/uwac-os.c new file mode 100644 index 000000000..ec9efe47b --- /dev/null +++ b/uwac/libuwac/uwac-os.c @@ -0,0 +1,236 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * This file is an adaptation of src/wayland-os.h from the wayland project and + * shared/os-compatiblity.h from the weston project. + * + * Functions have been renamed just to prevent name clashes. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../config.h" +#include "uwac-os.h" + +static int set_cloexec_or_close(int fd) +{ + long flags; + + if (fd == -1) + return -1; + + flags = fcntl(fd, F_GETFD); + if (flags == -1) + goto err; + + if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) + goto err; + + return fd; + +err: + close(fd); + return -1; +} + +int uwac_os_socket_cloexec(int domain, int type, int protocol) +{ + int fd; + + fd = socket(domain, type | SOCK_CLOEXEC, protocol); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; + + fd = socket(domain, type, protocol); + return set_cloexec_or_close(fd); +} + +int uwac_os_dupfd_cloexec(int fd, long minfd) +{ + int newfd; + + newfd = fcntl(fd, F_DUPFD_CLOEXEC, minfd); + if (newfd >= 0) + return newfd; + if (errno != EINVAL) + return -1; + + newfd = fcntl(fd, F_DUPFD, minfd); + return set_cloexec_or_close(newfd); +} + +static ssize_t recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags) +{ + ssize_t len; + struct cmsghdr *cmsg; + unsigned char *data; + int *fd; + int *end; + + len = recvmsg(sockfd, msg, flags); + if (len == -1) + return -1; + + if (!msg->msg_control || msg->msg_controllen == 0) + return len; + + cmsg = CMSG_FIRSTHDR(msg); + for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) { + if (cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) + continue; + + data = CMSG_DATA(cmsg); + end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0)); + for (fd = (int *)data; fd < end; ++fd) + *fd = set_cloexec_or_close(*fd); + } + + return len; +} + +ssize_t uwac_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags) +{ + ssize_t len; + + len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC); + if (len >= 0) + return len; + if (errno != EINVAL) + return -1; + + return recvmsg_cloexec_fallback(sockfd, msg, flags); +} + +int uwac_os_epoll_create_cloexec(void) +{ + int fd; + +#ifdef EPOLL_CLOEXEC + fd = epoll_create1(EPOLL_CLOEXEC); + if (fd >= 0) + return fd; + if (errno != EINVAL) + return -1; +#endif + + fd = epoll_create(1); + return set_cloexec_or_close(fd); +} + +static int create_tmpfile_cloexec(char *tmpname) +{ + int fd; + +#ifdef HAVE_MKOSTEMP + fd = mkostemp(tmpname, O_CLOEXEC); + if (fd >= 0) + unlink(tmpname); +#else + fd = mkstemp(tmpname); + if (fd >= 0) { + fd = set_cloexec_or_close(fd); + unlink(tmpname); + } +#endif + + return fd; +} + +/* + * Create a new, unique, anonymous file of the given size, and + * return the file descriptor for it. The file descriptor is set + * CLOEXEC. The file is immediately suitable for mmap()'ing + * the given size at offset zero. + * + * The file should not have a permanent backing store like a disk, + * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. + * + * The file name is deleted from the file system. + * + * The file is suitable for buffer sharing between processes by + * transmitting the file descriptor over Unix sockets using the + * SCM_RIGHTS methods. + * + * If the C library implements posix_fallocate(), it is used to + * guarantee that disk space is available for the file at the + * given size. If disk space is insufficient, errno is set to ENOSPC. + * If posix_fallocate() is not supported, program may receive + * SIGBUS on accessing mmap()'ed file contents instead. + */ +int uwac_create_anonymous_file(off_t size) +{ + static const char template[] = "/weston-shared-XXXXXX"; + const char *path; + char *name; + int fd; + int ret; + + path = getenv("XDG_RUNTIME_DIR"); + if (!path) { + errno = ENOENT; + return -1; + } + + name = malloc(strlen(path) + sizeof(template)); + if (!name) + return -1; + + strcpy(name, path); + strcat(name, template); + + fd = create_tmpfile_cloexec(name); + + free(name); + + if (fd < 0) + return -1; + +#ifdef HAVE_POSIX_FALLOCATE + ret = posix_fallocate(fd, 0, size); + if (ret != 0) { + close(fd); + errno = ret; + return -1; + } +#else + ret = ftruncate(fd, size); + if (ret < 0) { + close(fd); + return -1; + } +#endif + + return fd; +} diff --git a/uwac/libuwac/uwac-os.h b/uwac/libuwac/uwac-os.h new file mode 100644 index 000000000..be927df7d --- /dev/null +++ b/uwac/libuwac/uwac-os.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +/* + * This file is an adaptation of src/wayland-os.h from the wayland project and + * shared/os-compatiblity.h from the weston project. + * + * Functions have been renamed just to prevent name clashes. + */ + +#ifndef __UWAC_OS_H +#define __UWAC_OS_H + +#include + +int uwac_os_socket_cloexec(int domain, int type, int protocol); + +int uwac_os_dupfd_cloexec(int fd, long minfd); + +ssize_t uwac_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags); + +int uwac_os_epoll_create_cloexec(void); + +int uwac_create_anonymous_file(off_t size); +#endif /* __UWAC_OS_H */ diff --git a/uwac/libuwac/uwac-output.c b/uwac/libuwac/uwac-output.c new file mode 100644 index 000000000..0da871c1c --- /dev/null +++ b/uwac/libuwac/uwac-output.c @@ -0,0 +1,126 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include "uwac-priv.h" +#include "uwac-utils.h" + +#include +#include +#include +#include + +#define TARGET_OUTPUT_INTERFACE 2 + +static void output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y, + int physical_width, int physical_height, int subpixel, + const char *make, const char *model, int transform) +{ + UwacOutput *output = data; + +/* output->allocation.x = x; + output->allocation.y = y;*/ + output->transform = transform; + + if (output->make) + free(output->make); + output->make = strdup(make); + if (!output->make) { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup make\n", __FUNCTION__)); + } + + if (output->model) + free(output->model); + output->model = strdup(model); + if (!output->model) { + assert(uwacErrorHandler(output->display, UWAC_ERROR_NOMEMORY, "%s: unable to strdup model\n", __FUNCTION__)); + } +} + +static void output_handle_done(void *data, struct wl_output *wl_output) +{ + UwacOutput *output = data; + + output->doneReceived = true; +} + +static void output_handle_scale(void *data, struct wl_output *wl_output, int32_t scale) +{ + UwacOutput *output = data; + + output->scale = scale; +} + +static void output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags, + int width, int height, int refresh) +{ + UwacOutput *output = data; + //UwacDisplay *display = output->display; + + if (output->doneNeeded && output->doneReceived) { + /* TODO: we should clear the mode list */ + } + + if (flags & WL_OUTPUT_MODE_CURRENT) { + output->resolution.width = width; + output->resolution.height = height; + /* output->allocation.width = width; + output->allocation.height = height; + if (display->output_configure_handler) + (*display->output_configure_handler)( + output, display->user_data);*/ + } +} + +static const struct wl_output_listener output_listener = { + output_handle_geometry, + output_handle_mode, + output_handle_done, + output_handle_scale +}; + +UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version) { + UwacOutput *o; + + o = zalloc(sizeof *o); + if (!o) + return NULL; + + o->display = d; + o->server_output_id = id; + o->doneNeeded = (version > 1); + o->doneReceived = false; + o->output = wl_registry_bind(d->registry, id, &wl_output_interface, min(TARGET_OUTPUT_INTERFACE, version)); + wl_output_add_listener(o->output, &output_listener, o); + + wl_list_insert(d->outputs.prev, &o->link); + return o; +} + +int UwacDestroyOutput(UwacOutput *output) { + free(output->make); + free(output->model); + + wl_output_destroy(output->output); + wl_list_remove(&output->link); + free(output); + + return UWAC_SUCCESS; +} diff --git a/uwac/libuwac/uwac-priv.h b/uwac/libuwac/uwac-priv.h new file mode 100644 index 000000000..8b0324d23 --- /dev/null +++ b/uwac/libuwac/uwac-priv.h @@ -0,0 +1,237 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_PRIV_H_ +#define __UWAC_PRIV_H_ + +#include "config.h" + +#include +#include +#include "xdg-shell-client-protocol.h" +#ifdef BUILD_IVI +#include "ivi-application-client-protocol.h" +#endif +#ifdef BUILD_FULLSCREEN_SHELL +#include "fullscreen-shell-client-protocol.h" +#endif + +#ifdef HAVE_PIXMAN_REGION +#include +#else +#include +#endif + +#include + +#include + + +extern UwacErrorHandler uwacErrorHandler; + +typedef struct uwac_task UwacTask; + +/** @brief */ +struct uwac_task { + void (*run)(UwacTask *task, uint32_t events); + struct wl_list link; +}; + +/** @brief a global registry object */ +struct uwac_global { + uint32_t name; + char *interface; + uint32_t version; + struct wl_list link; +}; +typedef struct uwac_global UwacGlobal; + +struct uwac_event_list_item; +typedef struct uwac_event_list_item UwacEventListItem; + +/** @brief */ +struct uwac_event_list_item { + UwacEvent event; + UwacEventListItem *tail, *head; +}; + + +/** @brief main connection object to a wayland display */ +struct uwac_display { + struct wl_list globals; + + struct wl_display *display; + struct wl_registry *registry; + struct wl_compositor *compositor; + struct wl_subcompositor *subcompositor; + struct wl_shell *shell; + struct xdg_shell *xdg_shell; +#ifdef BUILD_IVI + struct ivi_application *ivi_application; +#endif +#ifdef BUILD_FULLSCREEN_SHELL + struct _wl_fullscreen_shell *fullscreen_shell; +#endif + + struct wl_shm *shm; + enum wl_shm_format *shm_formats; + uint32_t shm_formats_nb; + bool has_rgb565; + + struct wl_data_device_manager *data_device_manager; + struct text_cursor_position *text_cursor_position; + struct workspace_manager *workspace_manager; + + struct wl_list seats; + + int display_fd; + UwacReturnCode last_error; + uint32_t display_fd_events; + int epoll_fd; + bool running; + UwacTask dispatch_fd_task; + uint32_t serial; + + struct wl_cursor_theme *cursor_theme; + struct wl_cursor **cursors; + + struct wl_list windows; + + struct wl_list outputs; + + UwacEventListItem *push_queue, *pop_queue; +}; + +/** @brief an output on a wayland display */ +struct uwac_output { + UwacDisplay *display; + + bool doneNeeded; + bool doneReceived; + + UwacSize resolution; + int transform; + int scale; + char *make; + char *model; + uint32_t server_output_id; + struct wl_output *output; + + struct wl_list link; +}; + +/** @brief a seat attached to a wayland display */ +struct uwac_seat { + UwacDisplay *display; + char *name; + struct wl_seat *seat; + uint32_t seat_id; + uint32_t seat_version; + struct wl_pointer *pointer; + struct wl_keyboard *keyboard; + struct wl_touch *touch; + struct xkb_context *xkb_context; + + struct { + struct xkb_keymap *keymap; + struct xkb_state *state; + xkb_mod_mask_t control_mask; + xkb_mod_mask_t alt_mask; + xkb_mod_mask_t shift_mask; + } xkb; + uint32_t modifiers; + int32_t repeat_rate_sec, repeat_rate_nsec; + int32_t repeat_delay_sec, repeat_delay_nsec; + uint32_t repeat_sym, repeat_key, repeat_time; + + struct wl_array pressed_keys; + + UwacWindow *pointer_focus; + + UwacWindow *keyboard_focus; + + UwacWindow *touch_focus; + bool touch_frame_started; + + int repeat_timer_fd; + UwacTask repeat_task; + float sx, sy; + struct wl_list link; +}; + + +/** @brief a buffer used for drawing a surface frame */ +struct uwac_buffer { + bool used; +#ifdef HAVE_PIXMAN_REGION + pixman_region32_t damage; +#else + REGION16 damage; +#endif + struct wl_buffer *wayland_buffer; + void *data; +}; +typedef struct uwac_buffer UwacBuffer; + + +/** @brief a window */ +struct uwac_window { + UwacDisplay *display; + int width, height, stride; + int surfaceStates; + enum wl_shm_format format; + + int nbuffers; + UwacBuffer *buffers; + + struct wl_region *opaque_region; + struct wl_region *input_region; + struct wl_callback *frame_callback; + UwacBuffer *drawingBuffer, *pendingBuffer; + struct wl_surface *surface; + struct wl_shell_surface *shell_surface; + struct xdg_surface *xdg_surface; +#ifdef BUILD_IVI + struct ivi_surface *ivi_surface; +#endif + struct wl_list link; + + uint32_t pointer_enter_serial; + uint32_t pointer_cursor_serial; + int pointer_current_cursor; +}; + + +/* in uwa-display.c */ +UwacEvent *UwacDisplayNewEvent(UwacDisplay *d, int type); +int UwacDisplayWatchFd(UwacDisplay *display, int fd, uint32_t events, UwacTask *task); + + +/* in uwac-input.c */ +UwacSeat *UwacSeatNew(UwacDisplay *d, uint32_t id, uint32_t version); +void UwacSeatDestroy(UwacSeat *s); + +/* in uwac-output.c */ +UwacOutput *UwacCreateOutput(UwacDisplay *d, uint32_t id, uint32_t version); +int UwacDestroyOutput(UwacOutput *output); + +#endif /* __UWAC_PRIV_H_ */ diff --git a/uwac/libuwac/uwac-tools.c b/uwac/libuwac/uwac-tools.c new file mode 100644 index 000000000..73aff227e --- /dev/null +++ b/uwac/libuwac/uwac-tools.c @@ -0,0 +1,93 @@ +/* + * Copyright © 2015 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include +#include +#include + +/** @brief */ +struct uwac_touch_automata { + struct wl_array tp; +}; + +void UwacTouchAutomataInit(UwacTouchAutomata *automata) { + wl_array_init(&automata->tp); +} + +void UwacTouchAutomataReset(UwacTouchAutomata *automata) { + automata->tp.size = 0; +} + +bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event) { + + UwacTouchPoint *tp; + + switch (event->type) { + case UWAC_EVENT_TOUCH_FRAME_BEGIN: + break; + + case UWAC_EVENT_TOUCH_UP: { + UwacTouchUp *touchUp = &event->touchUp; + int toMove = automata->tp.size - sizeof(UwacTouchPoint); + + wl_array_for_each(tp, &automata->tp) { + if (tp->id == touchUp->id) { + if (toMove) + memmove(tp, tp+1, toMove); + return true; + } + + toMove -= sizeof(UwacTouchPoint); + } + break; + } + + case UWAC_EVENT_TOUCH_DOWN: { + UwacTouchDown *touchDown = &event->touchDown; + + wl_array_for_each(tp, &automata->tp) { + if (tp->id == touchDown->id) { + tp->x = touchDown->x; + tp->y = touchDown->y; + return true; + } + } + + tp = wl_array_add(&automata->tp, sizeof(UwacTouchPoint)); + if (!tp) + return false; + + tp->id = touchDown->id; + tp->x = touchDown->x; + tp->y = touchDown->y; + break; + } + + case UWAC_EVENT_TOUCH_FRAME_END: + break; + + default: + break; + } + + return true; +} diff --git a/uwac/libuwac/uwac-utils.c b/uwac/libuwac/uwac-utils.c new file mode 100644 index 000000000..c9c33f6fe --- /dev/null +++ b/uwac/libuwac/uwac-utils.c @@ -0,0 +1,63 @@ +/* + * Copyright © 2012 Collabora, Ltd. + * Copyright © 2008 Kristian Høgsberg + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#include "config.h" + +#include +#include +#include +#include + +#include "uwac-utils.h" + +/* + * This part is an adaptation of client/window.c from the weston project. + */ + +void *fail_on_null(void *p) { + if (p == NULL) { + fprintf(stderr, "out of memory\n"); + exit(EXIT_FAILURE); + } + + return p; +} + +void *xmalloc(size_t s) { + return fail_on_null(malloc(s)); +} + +void *xzalloc(size_t s) { + return fail_on_null(zalloc(s)); +} + +char *xstrdup(const char *s) { + return fail_on_null(strdup(s)); +} + +void *xrealloc(char *p, size_t s) { + return fail_on_null(realloc(p, s)); +} + + diff --git a/uwac/libuwac/uwac-utils.h b/uwac/libuwac/uwac-utils.h new file mode 100644 index 000000000..e30507300 --- /dev/null +++ b/uwac/libuwac/uwac-utils.h @@ -0,0 +1,53 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + +#ifndef __UWAC_UTILS_H_ +#define __UWAC_UTILS_H_ + +#include + +#define min(a,b) \ + ({ __typeof__ (a) _a = (a); \ + __typeof__ (b) _b = (b); \ + _a < _b ? _a : _b; }) + +#define container_of(ptr, type, member) ({ \ + const __typeof__( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) + + + +void *xmalloc(size_t s); + +static inline void *zalloc(size_t size) { + return calloc(1, size); +} + +void *xzalloc(size_t s); + +char *xstrdup(const char *s); + +void *xrealloc(char *p, size_t s); + +#endif /* __UWAC_UTILS_H_ */ diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c new file mode 100644 index 000000000..fa3b860ea --- /dev/null +++ b/uwac/libuwac/uwac-window.c @@ -0,0 +1,616 @@ +/* + * Copyright © 2014 David FORT + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that copyright + * notice and this permission notice appear in supporting documentation, and + * that the name of the copyright holders not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. The copyright holders make no representations + * about the suitability of this software for any purpose. It is provided "as + * is" without express or implied warranty. + * + * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "uwac-priv.h" +#include "uwac-utils.h" +#include "uwac-os.h" + + +#define UWAC_INITIAL_BUFFERS 3 + + +static int bppFromShmFormat(enum wl_shm_format format) { + switch (format) { + case WL_SHM_FORMAT_ARGB8888: + case WL_SHM_FORMAT_XRGB8888: + default: + return 4; + } +} + + +static void buffer_release(void *data, struct wl_buffer *buffer) { + UwacBuffer *uwacBuffer = (UwacBuffer *)data; + + uwacBuffer->used = false; +} + +static const struct wl_buffer_listener buffer_listener = { + buffer_release +}; + +void UwacWindowDestroyBuffers(UwacWindow *w) { + int i; + + for (i = 0; i < w->nbuffers; i++) { + UwacBuffer *buffer = &w->buffers[i]; +#ifdef HAVE_PIXMAN_REGION + pixman_region32_fini(&buffer->damage); +#else + region16_uninit(&buffer->damage); +#endif + wl_buffer_destroy(buffer->wayland_buffer); + } + + w->nbuffers = 0; + free(w->buffers); + w->buffers = NULL; +} + + +int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width, + uint32_t height, enum wl_shm_format format); + +static void xdg_handle_configure(void *data, struct xdg_surface *surface, + int32_t width, int32_t height, + struct wl_array *states, uint32_t serial) +{ + UwacWindow *window = (UwacWindow *)data; + UwacConfigureEvent *event; + int ret, surfaceState; + enum xdg_surface_state *state; + + surfaceState = 0; + wl_array_for_each(state, states) { + switch (*state) { + case XDG_SURFACE_STATE_MAXIMIZED: + surfaceState |= UWAC_WINDOW_MAXIMIZED; + break; + case XDG_SURFACE_STATE_FULLSCREEN: + surfaceState |= UWAC_WINDOW_FULLSCREEN; + break; + case XDG_SURFACE_STATE_ACTIVATED: + surfaceState |= UWAC_WINDOW_ACTIVATED; + break; + case XDG_SURFACE_STATE_RESIZING: + surfaceState |= UWAC_WINDOW_RESIZING; + break; + default: + break; + } + } + + window->surfaceStates = surfaceState; + + event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n")); + goto ack; + } + + event->window = window; + event->states = surfaceState; + if (width && height) { + event->width = width; + event->height = height; + + UwacWindowDestroyBuffers(window); + + window->width = width; + window->stride = width * bppFromShmFormat(window->format); + window->height = height; + + ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height, + width, height, window->format); + if (ret != UWAC_SUCCESS) { + assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); + window->drawingBuffer = window->pendingBuffer = NULL; + goto ack; + } + window->drawingBuffer = window->pendingBuffer = &window->buffers[0]; + } else { + event->width = window->width; + event->height = window->height; + } + +ack: + xdg_surface_ack_configure(surface, serial); +} + +static void xdg_handle_close(void *data, struct xdg_surface *xdg_surface) +{ + UwacCloseEvent *event; + UwacWindow *window = (UwacWindow *)data; + + event = (UwacCloseEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CLOSE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_INTERNAL, "failed to allocate a close event\n")); + return; + } + + event->window = window; +} + +static const struct xdg_surface_listener xdg_surface_listener = { + xdg_handle_configure, + xdg_handle_close, +}; + +#if BUILD_IVI + +static void ivi_handle_configure(void *data, struct ivi_surface *surface, + int32_t width, int32_t height) +{ + UwacWindow *window = (UwacWindow *)data; + UwacConfigureEvent *event; + int ret; + + + event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n")); + return; + } + + event->window = window; + event->states = 0; + if (width && height) { + event->width = width; + event->height = height; + + UwacWindowDestroyBuffers(window); + + window->width = width; + window->stride = width * bppFromShmFormat(window->format); + window->height = height; + + ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height, + width, height, window->format); + if (ret != UWAC_SUCCESS) { + assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); + window->drawingBuffer = window->pendingBuffer = NULL; + return; + } + window->drawingBuffer = window->pendingBuffer = &window->buffers[0]; + } else { + event->width = window->width; + event->height = window->height; + } +} + +static const struct ivi_surface_listener ivi_surface_listener = { + ivi_handle_configure, +}; +#endif + +void shell_ping(void *data, struct wl_shell_surface *surface, uint32_t serial) +{ + wl_shell_surface_pong(surface, serial); +} + +void shell_configure(void *data, struct wl_shell_surface *surface, uint32_t edges, + int32_t width, int32_t height) +{ + UwacWindow *window = (UwacWindow *)data; + UwacConfigureEvent *event; + int ret; + + event = (UwacConfigureEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_CONFIGURE); + if(!event) { + assert(uwacErrorHandler(window->display, UWAC_ERROR_NOMEMORY, "failed to allocate a configure event\n")); + return; + } + + event->window = window; + event->states = 0; + if (width && height) { + event->width = width; + event->height = height; + + UwacWindowDestroyBuffers(window); + + window->width = width; + window->stride = width * bppFromShmFormat(window->format); + window->height = height; + + ret = UwacWindowShmAllocBuffers(window, UWAC_INITIAL_BUFFERS, window->stride * height, + width, height, window->format); + if (ret != UWAC_SUCCESS) { + assert(uwacErrorHandler(window->display, ret, "failed to reallocate a wayland buffers\n")); + window->drawingBuffer = window->pendingBuffer = NULL; + return; + } + window->drawingBuffer = window->pendingBuffer = &window->buffers[0]; + } else { + event->width = window->width; + event->height = window->height; + } + +} + + +void shell_popup_done(void *data, struct wl_shell_surface *surface) +{ +} + + +static const struct wl_shell_surface_listener shell_listener = { + shell_ping, + shell_configure, + shell_popup_done +}; + + +int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32_t width, + uint32_t height, enum wl_shm_format format) +{ + int ret = UWAC_SUCCESS; + UwacBuffer *newBuffers; + int i, fd; + void *data; + struct wl_shm_pool *pool; + + newBuffers = realloc(w->buffers, (w->nbuffers + nbuffers) * sizeof(UwacBuffer)); + if (!newBuffers) + return UWAC_ERROR_NOMEMORY; + + w->buffers = newBuffers; + + memset(w->buffers + w->nbuffers, 0, sizeof(UwacBuffer) * nbuffers); + + fd = uwac_create_anonymous_file(allocSize * nbuffers); + if (fd < 0) { + return UWAC_ERROR_INTERNAL; + } + + data = mmap(NULL, allocSize * nbuffers, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (data == MAP_FAILED) { + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } + + pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers); + + for (i = 0; i < nbuffers; i++) { + UwacBuffer *buffer = &w->buffers[w->nbuffers + i]; +#ifdef HAVE_PIXMAN_REGION + pixman_region32_init(&buffer->damage); +#else + region16_init(&buffer->damage); +#endif + buffer->data = data + (allocSize * i); + + buffer->wayland_buffer = wl_shm_pool_create_buffer(pool, allocSize * i, width, height, w->stride, format); + wl_buffer_add_listener(buffer->wayland_buffer, &buffer_listener, buffer); + + } + + wl_shm_pool_destroy(pool); + w->nbuffers += nbuffers; + +error_mmap: + close(fd); + return ret; +} + +UwacBuffer *UwacWindowFindFreeBuffer(UwacWindow *w) { + int i, ret; + + for (i = 0; i < w->nbuffers; i++) { + if (!w->buffers[i].used) { + w->buffers[i].used = true; + return &w->buffers[i]; + } + } + + ret = UwacWindowShmAllocBuffers(w, 2, w->stride * w->height, w->width, w->height, w->format); + if (ret != UWAC_SUCCESS) { + w->display->last_error = ret; + return NULL; + } + + w->buffers[i].used = true; + return &w->buffers[i]; +} + + +UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format) { + UwacWindow *w; + int allocSize, ret; + + if (!display) { + display->last_error = UWAC_ERROR_INVALID_DISPLAY; + return NULL; + } + + w = zalloc(sizeof(*w)); + if (!w) { + display->last_error = UWAC_ERROR_NOMEMORY; + return NULL; + } + + w->display = display; + w->format = format; + w->width = width; + w->height = height; + w->stride = width * bppFromShmFormat(format); + allocSize = w->stride * height; + + ret = UwacWindowShmAllocBuffers(w, UWAC_INITIAL_BUFFERS, allocSize, width, height, format); + if (ret != UWAC_SUCCESS) { + display->last_error = ret; + goto out_error_free; + } + + w->buffers[0].used = true; + w->drawingBuffer = &w->buffers[0]; + + w->surface = wl_compositor_create_surface(display->compositor); + if (!w->surface) { + display->last_error = UWAC_ERROR_NOMEMORY; + goto out_error_surface; + } + wl_surface_set_user_data(w->surface, w); + + if (display->xdg_shell) { + w->xdg_surface = xdg_shell_get_xdg_surface(display->xdg_shell, w->surface); + if (!w->xdg_surface) { + display->last_error = UWAC_ERROR_NOMEMORY; + goto out_error_shell; + } + + assert(w->xdg_surface); + + xdg_surface_add_listener(w->xdg_surface, &xdg_surface_listener, w); +#if BUILD_IVI + } else if (display->ivi_application) { + w->ivi_surface = ivi_application_surface_create(display->ivi_application, 1, w->surface); + + assert (w->ivi_surface); + + ivi_surface_add_listener(w->ivi_surface, &ivi_surface_listener, w); +#endif +#if BUILD_FULLSCREEN_SHELL + } else if (display->fullscreen_shell) { + _wl_fullscreen_shell_present_surface(display->fullscreen_shell, w->surface, + _WL_FULLSCREEN_SHELL_PRESENT_METHOD_CENTER, NULL); +#endif + } else { + w->shell_surface = wl_shell_get_shell_surface(display->shell, w->surface); + + assert(w->shell_surface); + + wl_shell_surface_add_listener(w->shell_surface, &shell_listener, w); + wl_shell_surface_set_toplevel(w->shell_surface); + } + + wl_list_insert(display->windows.prev, &w->link); + + display->last_error = UWAC_SUCCESS; + return w; + +out_error_shell: + wl_surface_destroy(w->surface); +out_error_surface: + UwacWindowDestroyBuffers(w); +out_error_free: + free(w); + return NULL; +} + + +UwacReturnCode UwacDestroyWindow(UwacWindow **pwindow) { + UwacWindow *w; + + assert (pwindow); + + w = *pwindow; + UwacWindowDestroyBuffers(w); + + if (w->frame_callback) + wl_callback_destroy(w->frame_callback); + + if (w->xdg_surface) + xdg_surface_destroy(w->xdg_surface); +#if BUILD_IVI + if (w->ivi_surface) + ivi_surface_destroy(w->ivi_surface); +#endif + + if (w->opaque_region) + wl_region_destroy(w->opaque_region); + + if (w->input_region) + wl_region_destroy(w->opaque_region); + + wl_surface_destroy(w->surface); + wl_list_remove(&w->link); + free(w); + + *pwindow = NULL; + return UWAC_SUCCESS; +} + + +UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, + uint32_t height) +{ + assert(window); + + if (window->opaque_region) + wl_region_destroy(window->opaque_region); + + window->opaque_region = wl_compositor_create_region(window->display->compositor); + if (!window->opaque_region) + return UWAC_ERROR_NOMEMORY; + + wl_region_add(window->opaque_region, x, y, width, height); + wl_surface_set_opaque_region(window->surface, window->opaque_region); + return UWAC_SUCCESS; +} + +UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { + assert(window); + + if (window->input_region) + wl_region_destroy(window->input_region); + + window->input_region = wl_compositor_create_region(window->display->compositor); + if (!window->input_region) + return UWAC_ERROR_NOMEMORY; + + wl_region_add(window->input_region, x, y, width, height); + wl_surface_set_input_region(window->surface, window->input_region); + return UWAC_SUCCESS; +} + + +void *UwacWindowGetDrawingBuffer(UwacWindow *window) { + return window->drawingBuffer->data; +} + +static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time); + +static const struct wl_callback_listener frame_listener = { + frame_done_cb +}; + + +static void UwacSubmitBufferPtr(UwacWindow *window, UwacBuffer *buffer) { + int nrects, i; +#ifdef HAVE_PIXMAN_REGION + const pixman_box32_t *box; +#else + const RECTANGLE_16 *box; +#endif + + wl_surface_attach(window->surface, buffer->wayland_buffer, 0, 0); + +#ifdef HAVE_PIXMAN_REGION + box = pixman_region32_rectangles(&buffer->damage, &nrects); + for (i = 0; i < nrects; i++, box++) + wl_surface_damage(window->surface, box->x1, box->y1, (box->x2 - box->x1), (box->y2 - box->y1)); +#else + box = region16_rects(&buffer->damage, &nrects); + for (i = 0; i < nrects; i++, box++) + wl_surface_damage(window->surface, box->left, box->top, (box->right - box->left), (box->bottom - box->top)); +#endif + + if (window->frame_callback) + wl_callback_destroy(window->frame_callback); + + window->frame_callback = wl_surface_frame(window->surface); + wl_callback_add_listener(window->frame_callback, &frame_listener, window); + + wl_surface_commit(window->surface); + +#ifdef HAVE_PIXMAN_REGION + pixman_region32_clear(&buffer->damage); +#else + region16_clear(&buffer->damage); +#endif +} + + +static void frame_done_cb(void *data, struct wl_callback *callback, uint32_t time) { + UwacWindow *window = (UwacWindow *)data; + UwacFrameDoneEvent *event; + + window->pendingBuffer = NULL; + event = (UwacFrameDoneEvent *)UwacDisplayNewEvent(window->display, UWAC_EVENT_FRAME_DONE); + if(event) + event->window = window; +} + + +UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height) { +#ifdef HAVE_PIXMAN_REGION + if (!pixman_region32_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, x, y, width, height)) +#else + RECTANGLE_16 box; + box.left = x; box.top = y; + box.right = x + width; box.bottom = y + height; + + if (!region16_union_rect(&window->drawingBuffer->damage, &window->drawingBuffer->damage, &box)) +#endif + return UWAC_ERROR_INTERNAL; + + return UWAC_SUCCESS; +} + + +UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame) { + UwacBuffer *drawingBuffer = window->drawingBuffer; + + if (window->pendingBuffer) { + /* we already have a pending frame, don't do anything*/ + return UWAC_SUCCESS; + } + + UwacSubmitBufferPtr(window, drawingBuffer); + + window->pendingBuffer = window->drawingBuffer; + window->drawingBuffer = UwacWindowFindFreeBuffer(window); + if (!window->drawingBuffer) + return UWAC_ERROR_NOMEMORY; + + if (copyContentForNextFrame) { + memcpy(window->drawingBuffer->data, window->pendingBuffer->data, window->stride * window->height); + } + + return UWAC_SUCCESS; +} + +UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry) { + assert(window); + assert(geometry); + + geometry->width = window->width; + geometry->height = window->height; + return UWAC_SUCCESS; +} + + +UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen) { + if (window->xdg_surface) { + if (isFullscreen) { + xdg_surface_set_fullscreen(window->xdg_surface, output ? output->output : NULL); + } else { + xdg_surface_unset_fullscreen(window->xdg_surface); + } + } + return UWAC_SUCCESS; +} + +void UwacWindowSetTitle(UwacWindow *window, const char *name) { + if (window->xdg_surface) + xdg_surface_set_title(window->xdg_surface, name); + else if (window->shell_surface) + wl_shell_surface_set_title(window->shell_surface, name); +} diff --git a/uwac/protocols/fullscreen-shell.xml b/uwac/protocols/fullscreen-shell.xml new file mode 100644 index 000000000..e2b994b94 --- /dev/null +++ b/uwac/protocols/fullscreen-shell.xml @@ -0,0 +1,206 @@ + + + + Displays a single surface per output. + + This interface provides a mechanism for a single client to display + simple full-screen surfaces. While there technically may be multiple + clients bound to this interface, only one of those clients should be + shown at a time. + + To present a surface, the client uses either the present_surface or + present_surface_for_mode requests. Presenting a surface takes effect + on the next wl_surface.commit. See the individual requests for + details about scaling and mode switches. + + The client can have at most one surface per output at any time. + Requesting a surface be presented on an output that already has a + surface replaces the previously presented surface. Presenting a null + surface removes its content and effectively disables the output. + Exactly what happens when an output is "disabled" is + compositor-specific. The same surface may be presented on multiple + outputs simultaneously. + + Once a surface is presented on an output, it stays on that output + until either the client removes it or the compositor destroys the + output. This way, the client can update the output's contents by + simply attaching a new buffer. + + + + + Release the binding from the wl_fullscreen_shell interface + + This destroys the server-side object and frees this binding. If + the client binds to wl_fullscreen_shell multiple times, it may wish + to free some of those bindings. + + + + + + Various capabilities that can be advertised by the compositor. They + are advertised one-at-a-time when the wl_fullscreen_shell interface is + bound. See the wl_fullscreen_shell.capability event for more details. + + ARBITRARY_MODE: + This is a hint to the client that indicates that the compositor is + capable of setting practically any mode on its outputs. If this + capability is provided, wl_fullscreen_shell.present_surface_for_mode + will almost never fail and clients should feel free to set whatever + mode they like. If the compositor does not advertise this, it may + still support some modes that are not advertised through wl_global.mode + but it is less likely. + + CURSOR_PLANE: + This is a hint to the client that indicates that the compositor can + handle a cursor surface from the client without actually compositing. + This may be because of a hardware cursor plane or some other mechanism. + If the compositor does not advertise this capability then setting + wl_pointer.cursor may degrade performance or be ignored entirely. If + CURSOR_PLANE is not advertised, it is recommended that the client draw + its own cursor and set wl_pointer.cursor(NULL). + + + + + + + + Advertises a single capability of the compositor. + + When the wl_fullscreen_shell interface is bound, this event is emitted + once for each capability advertised. Valid capabilities are given by + the wl_fullscreen_shell.capability enum. If clients want to take + advantage of any of these capabilities, they should use a + wl_display.sync request immediately after binding to ensure that they + receive all the capability events. + + + + + + + Hints to indicate to the compositor how to deal with a conflict + between the dimensions of the surface and the dimensions of the + output. The compositor is free to ignore this parameter. + + + + + + + + + + + Present a surface on the given output. + + If the output is null, the compositor will present the surface on + whatever display (or displays) it thinks best. In particular, this + may replace any or all surfaces currently presented so it should + not be used in combination with placing surfaces on specific + outputs. + + The method parameter is a hint to the compositor for how the surface + is to be presented. In particular, it tells the compositor how to + handle a size mismatch between the presented surface and the + output. The compositor is free to ignore this parameter. + + The "zoom", "zoom_crop", and "stretch" methods imply a scaling + operation on the surface. This will override any kind of output + scaling, so the buffer_scale property of the surface is effectively + ignored. + + + + + + + + + Presents a surface on the given output for a particular mode. + + If the current size of the output differs from that of the surface, + the compositor will attempt to change the size of the output to + match the surface. The result of the mode-switch operation will be + returned via the provided wl_fullscreen_shell_mode_feedback object. + + If the current output mode matches the one requested or if the + compositor successfully switches the mode to match the surface, + then the mode_successful event will be sent and the output will + contain the contents of the given surface. If the compositor + cannot match the output size to the surface size, the mode_failed + will be sent and the output will contain the contents of the + previously presented surface (if any). If another surface is + presented on the given output before either of these has a chance + to happen, the present_cancelled event will be sent. + + Due to race conditions and other issues unknown to the client, no + mode-switch operation is guaranteed to succeed. However, if the + mode is one advertised by wl_output.mode or if the compositor + advertises the ARBITRARY_MODES capability, then the client should + expect that the mode-switch operation will usually succeed. + + If the size of the presented surface changes, the resulting output + is undefined. The compositor may attempt to change the output mode + to compensate. However, there is no guarantee that a suitable mode + will be found and the client has no way to be notified of success + or failure. + + The framerate parameter specifies the desired framerate for the + output in mHz. The compositor is free to ignore this parameter. A + value of 0 indicates that the client has no preference. + + If the value of wl_output.scale differs from wl_surface.buffer_scale, + then the compositor may choose a mode that matches either the buffer + size or the surface size. In either case, the surface will fill the + output. + + + + + + + + + + These errors can be emitted in response to wl_fullscreen_shell requests + + + + + + + + + This event indicates that the attempted mode switch operation was + successful. A surface of the size requested in the mode switch + will fill the output without scaling. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + + This event indicates that the attempted mode switch operation + failed. This may be because the requested output mode is not + possible or it may mean that the compositor does not want to allow it. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + + This event indicates that the attempted mode switch operation was + cancelled. Most likely this is because the client requested a + second mode switch before the first one completed. + + Upon receiving this event, the client should destroy the + wl_fullscreen_shell_mode_feedback object. + + + + diff --git a/uwac/protocols/ivi-application.xml b/uwac/protocols/ivi-application.xml new file mode 100644 index 000000000..8f2422688 --- /dev/null +++ b/uwac/protocols/ivi-application.xml @@ -0,0 +1,100 @@ + + + + + Copyright (C) 2013 DENSO CORPORATION + Copyright (c) 2013 BMW Car IT GmbH + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + + + + This removes link from ivi_id to wl_surface and destroys ivi_surface. + The ID, ivi_id, is free and can be used for surface_create again. + + + + + + The configure event asks the client to resize its surface. + + The size is a hint, in the sense that the client is free to + ignore it if it doesn't resize, pick a smaller size (to + satisfy aspect ratio or resize in steps of NxM pixels). + + The client is free to dismiss all but the last configure + event it received. + + The width and height arguments specify the size of the window + in surface local coordinates. + + + + + + + + + This interface is exposed as a global singleton. + This interface is implemented by servers that provide IVI-style user interfaces. + It allows clients to associate a ivi_surface with wl_surface. + + + + + + + + + + This request gives the wl_surface the role of an IVI Surface. Creating more than + one ivi_surface for a wl_surface is not allowed. Note, that this still allows the + following example: + + 1. create a wl_surface + 2. create ivi_surface for the wl_surface + 3. destroy the ivi_surface + 4. create ivi_surface for the wl_surface (with the same or another ivi_id as before) + + surface_create will create a interface:ivi_surface with numeric ID; ivi_id in + ivi compositor. These ivi_ids are defined as unique in the system to identify + it inside of ivi compositor. The ivi compositor implements business logic how to + set properties of the surface with ivi_id according to status of the system. + E.g. a unique ID for Car Navigation application is used for implementing special + logic of the application about where it shall be located. + The server regards following cases as protocol errors and disconnects the client. + - wl_surface already has an nother role. + - ivi_id is already assigned to an another wl_surface. + + If client destroys ivi_surface or wl_surface which is assigne to the ivi_surface, + ivi_id which is assigned to the ivi_surface is free for reuse. + + + + + + + + + diff --git a/uwac/protocols/xdg-shell.xml b/uwac/protocols/xdg-shell.xml new file mode 100644 index 000000000..f98e760d4 --- /dev/null +++ b/uwac/protocols/xdg-shell.xml @@ -0,0 +1,608 @@ + + + + + Copyright © 2008-2013 Kristian Høgsberg + Copyright © 2013 Rafael Antognolli + Copyright © 2013 Jasper St. Pierre + Copyright © 2010-2013 Intel Corporation + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + xdg_shell allows clients to turn a wl_surface into a "real window" + which can be dragged, resized, stacked, and moved around by the + user. Everything about this interface is suited towards traditional + desktop environments. + + + + + The 'current' member of this enum gives the version of the + protocol. Implementations can compare this to the version + they implement using static_assert to ensure the protocol and + implementation versions match. + + + + + + + + + + + + + + Destroy this xdg_shell object. + + Destroying a bound xdg_shell object while there are surfaces + still alive created by this xdg_shell object instance is illegal + and will result in a protocol error. + + + + + + Negotiate the unstable version of the interface. This + mechanism is in place to ensure client and server agree on the + unstable versions of the protocol that they speak or exit + cleanly if they don't agree. This request will go away once + the xdg-shell protocol is stable. + + + + + + + This creates an xdg_surface for the given surface and gives it the + xdg_surface role. A wl_surface can only be given an xdg_surface role + once. If get_xdg_surface is called with a wl_surface that already has + an active xdg_surface associated with it, or if it had any other role, + an error is raised. + + See the documentation of xdg_surface for more details about what an + xdg_surface is and how it is used. + + + + + + + + This creates an xdg_popup for the given surface and gives it the + xdg_popup role. A wl_surface can only be given an xdg_popup role + once. If get_xdg_popup is called with a wl_surface that already has + an active xdg_popup associated with it, or if it had any other role, + an error is raised. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. + + See the documentation of xdg_popup for more details about what an + xdg_popup is and how it is used. + + + + + + + + + + + + + The ping event asks the client if it's still alive. Pass the + serial specified in the event back to the compositor by sending + a "pong" request back with the specified serial. + + Compositors can use this to determine if the client is still + alive. It's unspecified what will happen if the client doesn't + respond to the ping request, or in what timeframe. Clients should + try to respond in a reasonable amount of time. + + A compositor is free to ping in any way it wants, but a client must + always respond to any xdg_shell object it created. + + + + + + + A client must respond to a ping event with a pong request or + the client may be deemed unresponsive. + + + + + + + + An interface that may be implemented by a wl_surface, for + implementations that provide a desktop-style user interface. + + It provides requests to treat surfaces like windows, allowing to set + properties like maximized, fullscreen, minimized, and to move and resize + them, and associate metadata like title and app id. + + The client must call wl_surface.commit on the corresponding wl_surface + for the xdg_surface state to take effect. Prior to committing the new + state, it can set up initial configuration, such as maximizing or setting + a window geometry. + + Even without attaching a buffer the compositor must respond to initial + committed configuration, for instance sending a configure event with + expected window geometry if the client maximized its surface during + initialization. + + For a surface to be mapped by the compositor the client must have + committed both an xdg_surface state and a buffer. + + + + + Unmap and destroy the window. The window will be effectively + hidden from the user's point of view, and all state like + maximization, fullscreen, and so on, will be lost. + + + + + + Set the "parent" of this surface. This window should be stacked + above a parent. The parent surface must be mapped as long as this + surface is mapped. + + Parent windows should be set on dialogs, toolboxes, or other + "auxiliary" surfaces, so that the parent is raised when the dialog + is raised. + + + + + + + Set a short title for the surface. + + This string may be used to identify the surface in a task bar, + window list, or other user interface elements provided by the + compositor. + + The string must be encoded in UTF-8. + + + + + + + Set an application identifier for the surface. + + The app ID identifies the general class of applications to which + the surface belongs. The compositor can use this to group multiple + surfaces together, or to determine how to launch a new application. + + For D-Bus activatable applications, the app ID is used as the D-Bus + service name. + + The compositor shell will try to group application surfaces together + by their app ID. As a best practice, it is suggested to select app + ID's that match the basename of the application's .desktop file. + For example, "org.freedesktop.FooViewer" where the .desktop file is + "org.freedesktop.FooViewer.desktop". + + See the desktop-entry specification [0] for more details on + application identifiers and how they relate to well-known D-Bus + names and .desktop files. + + [0] http://standards.freedesktop.org/desktop-entry-spec/ + + + + + + + Clients implementing client-side decorations might want to show + a context menu when right-clicking on the decorations, giving the + user a menu that they can use to maximize or minimize the window. + + This request asks the compositor to pop up such a window menu at + the given position, relative to the local surface coordinates of + the parent surface. There are no guarantees as to what menu items + the window menu contains. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. + + + + + + + + + + + Start an interactive, user-driven move of the surface. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. The passed + serial is used to determine the type of interactive move (touch, + pointer, etc). + + The server may ignore move requests depending on the state of + the surface (e.g. fullscreen or maximized), or if the passed serial + is no longer valid. + + If triggered, the surface will lose the focus of the device + (wl_pointer, wl_touch, etc) used for the move. It is up to the + compositor to visually indicate that the move is taking place, such as + updating a pointer cursor, during the move. There is no guarantee + that the device focus will return when the move is completed. + + + + + + + + These values are used to indicate which edge of a surface + is being dragged in a resize operation. + + + + + + + + + + + + + + + Start a user-driven, interactive resize of the surface. + + This request must be used in response to some sort of user action + like a button press, key press, or touch down event. The passed + serial is used to determine the type of interactive resize (touch, + pointer, etc). + + The server may ignore resize requests depending on the state of + the surface (e.g. fullscreen or maximized). + + If triggered, the client will receive configure events with the + "resize" state enum value and the expected sizes. See the "resize" + enum value for more details about what is required. The client + must also acknowledge configure events using "ack_configure". After + the resize is completed, the client will receive another "configure" + event without the resize state. + + If triggered, the surface also will lose the focus of the device + (wl_pointer, wl_touch, etc) used for the resize. It is up to the + compositor to visually indicate that the resize is taking place, + such as updating a pointer cursor, during the resize. There is no + guarantee that the device focus will return when the resize is + completed. + + The edges parameter specifies how the surface should be resized, + and is one of the values of the resize_edge enum. The compositor + may use this information to update the surface position for + example when dragging the top left corner. The compositor may also + use this information to adapt its behavior, e.g. choose an + appropriate cursor image. + + + + + + + + + The different state values used on the surface. This is designed for + state values like maximized, fullscreen. It is paired with the + configure event to ensure that both the client and the compositor + setting the state can be synchronized. + + States set in this way are double-buffered. They will get applied on + the next commit. + + Desktop environments may extend this enum by taking up a range of + values and documenting the range they chose in this description. + They are not required to document the values for the range that they + chose. Ideally, any good extensions from a desktop environment should + make its way into standardization into this enum. + + The current reserved ranges are: + + 0x0000 - 0x0FFF: xdg-shell core values, documented below. + 0x1000 - 0x1FFF: GNOME + + + The surface is maximized. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is fullscreen. The window geometry specified in the configure + event must be obeyed by the client. + + + The surface is being resized. The window geometry specified in the + configure event is a maximum; the client cannot resize beyond it. + Clients that have aspect ratio or cell sizing configuration can use + a smaller size, however. + + + Client window decorations should be painted as if the window is + active. Do not assume this means that the window actually has + keyboard or pointer focus. + + + + + + The configure event asks the client to resize its surface or to + change its state. + + The width and height arguments specify a hint to the window + about how its surface should be resized in window geometry + coordinates. See set_window_geometry. + + If the width or height arguments are zero, it means the client + should decide its own window dimension. This may happen when the + compositor need to configure the state of the surface but doesn't + have any information about any previous or expected dimension. + + The states listed in the event specify how the width/height + arguments should be interpreted, and possibly how it should be + drawn. + + Clients should arrange their surface for the new size and + states, and then send a ack_configure request with the serial + sent in this configure event at some point before committing + the new surface. + + If the client receives multiple configure events before it + can respond to one, it is free to discard all but the last + event it received. + + + + + + + + + + + When a configure event is received, if a client commits the + surface in response to the configure event, then the client + must make a ack_configure request before the commit request, + passing along the serial of the configure event. + + For instance, the compositor might use this information to move + a surface to the top left only when the client has drawn itself + for the maximized or fullscreen state. + + If the client receives multiple configure events before it + can respond to one, it only has to ack the last configure event. + + + + + + + The window geometry of a window is its "visible bounds" from the + user's perspective. Client-side decorations often have invisible + portions like drop-shadows which should be ignored for the + purposes of aligning, placing and constraining windows. + + The window geometry is double buffered, and will be applied at the + time wl_surface.commit of the corresponding wl_surface is called. + + Once the window geometry of the surface is set once, it is not + possible to unset it, and it will remain the same until + set_window_geometry is called again, even if a new subsurface or + buffer is attached. + + If never set, the value is the full bounds of the surface, + including any subsurfaces. This updates dynamically on every + commit. This unset mode is meant for extremely simple clients. + + If responding to a configure event, the window geometry in here + must respect the sizing negotiations specified by the states in + the configure event. + + The arguments are given in the surface local coordinate space of + the wl_surface associated with this xdg_surface. + + The width and height must be greater than zero. + + + + + + + + + + Maximize the surface. + + After requesting that the surface should be maximized, the compositor + will respond by emitting a configure event with the "maximized" state + and the required window geometry. The client should then update its + content, drawing it in a maximized state, i.e. without shadow or other + decoration outside of the window geometry. The client must also + acknowledge the configure when committing the new content (see + ack_configure). + + It is up to the compositor to decide how and where to maximize the + surface, for example which output and what region of the screen should + be used. + + If the surface was already maximized, the compositor will still emit + a configure event with the "maximized" state. + + + + + + Unmaximize the surface. + + After requesting that the surface should be unmaximized, the compositor + will respond by emitting a configure event without the "maximized" + state. If available, the compositor will include the window geometry + dimensions the window had prior to being maximized in the configure + request. The client must then update its content, drawing it in a + regular state, i.e. potentially with shadow, etc. The client must also + acknowledge the configure when committing the new content (see + ack_configure). + + It is up to the compositor to position the surface after it was + unmaximized; usually the position the surface had before maximizing, if + applicable. + + If the surface was already not maximized, the compositor will still + emit a configure event without the "maximized" state. + + + + + + Make the surface fullscreen. + + You can specify an output that you would prefer to be fullscreen. + If this value is NULL, it's up to the compositor to choose which + display will be used to map this surface. + + If the surface doesn't cover the whole output, the compositor will + position the surface in the center of the output and compensate with + black borders filling the rest of the output. + + + + + + + + Request that the compositor minimize your surface. There is no + way to know if the surface is currently minimized, nor is there + any way to unset minimization on this surface. + + If you are looking to throttle redrawing when minimized, please + instead use the wl_surface.frame event for this, as this will + also work with live previews on windows in Alt-Tab, Expose or + similar compositor features. + + + + + + The close event is sent by the compositor when the user + wants the surface to be closed. This should be equivalent to + the user clicking the close button in client-side decorations, + if your application has any... + + This is only a request that the user intends to close your + window. The client may choose to ignore this request, or show + a dialog to ask the user to save their data... + + + + + + + A popup surface is a short-lived, temporary surface that can be + used to implement menus. It takes an explicit grab on the surface + that will be dismissed when the user dismisses the popup. This can + be done by the user clicking outside the surface, using the keyboard, + or even locking the screen through closing the lid or a timeout. + + When the popup is dismissed, a popup_done event will be sent out, + and at the same time the surface will be unmapped. The xdg_popup + object is now inert and cannot be reactivated, so clients should + destroy it. Explicitly destroying the xdg_popup object will also + dismiss the popup and unmap the surface. + + Clients will receive events for all their surfaces during this + grab (which is an "owner-events" grab in X11 parlance). This is + done so that users can navigate through submenus and other + "nested" popup windows without having to dismiss the topmost + popup. + + Clients that want to dismiss the popup when another surface of + their own is clicked should dismiss the popup using the destroy + request. + + The parent surface must have either an xdg_surface or xdg_popup + role. + + Specifying an xdg_popup for the parent means that the popups are + nested, with this popup now being the topmost popup. Nested + popups must be destroyed in the reverse order they were created + in, e.g. the only popup you are allowed to destroy at all times + is the topmost one. + + If there is an existing popup when creating a new popup, the + parent must be the current topmost popup. + + A parent surface must be mapped before the new popup is mapped. + + When compositors choose to dismiss a popup, they will likely + dismiss every nested popup as well. When a compositor dismisses + popups, it will follow the same dismissing order as required + from the client. + + The x and y arguments passed when creating the popup object specify + where the top left of the popup should be placed, relative to the + local surface coordinates of the parent surface. See + xdg_shell.get_xdg_popup. + + The client must call wl_surface.commit on the corresponding wl_surface + for the xdg_popup state to take effect. + + For a surface to be mapped by the compositor the client must have + committed both the xdg_popup state and a buffer. + + + + + This destroys the popup. Explicitly destroying the xdg_popup + object will also dismiss the popup, and unmap the surface. + + If this xdg_popup is not the "topmost" popup, a protocol error + will be sent. + + + + + + The popup_done event is sent out when a popup is dismissed by the + compositor. The client should destroy the xdg_popup object at this + point. + + + + + From 5dcb3dfe8b153306f4758b3bb8b1bbdab549f6c8 Mon Sep 17 00:00:00 2001 From: David FORT Date: Mon, 22 Feb 2016 16:03:57 +0100 Subject: [PATCH 041/128] Fix compilation and detection under debian/ubuntu --- cmake/FindWayland.cmake | 14 +++++++------- uwac/libuwac/uwac-input.c | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index e1a7030b4..ff5958b36 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -29,30 +29,30 @@ include(FindPkgConfig) if(PKG_CONFIG_FOUND) pkg_check_modules(WAYLAND_SCANNER_PKG wayland-scanner) - pkg_check_modules(WAYLAND_CLIENT wayland-client) - pkg_check_modules(XKBCOMMON xkbcommon) + pkg_check_modules(WAYLAND_CLIENT_PKG wayland-client) + pkg_check_modules(XKBCOMMON_PC_PKG xkbcommon) endif() find_program(WAYLAND_SCANNER wayland-scanner - HINTS "${WAYLAND_SCANNER_PREFIX}/bin" + HINTS "${WAYLAND_SCANNER_PKG_PREFIX}/bin" ) find_path(WAYLAND_INCLUDE_DIR wayland-client.h - HINTS ${WAYLAND_CLIENT_INCLUDE_DIRS} + HINTS ${WAYLAND_CLIENT_PKG_INCLUDE_DIRS} ) find_library(WAYLAND_LIBS NAMES "wayland-client" - HINTS "${WAYLAND_CLIENT_LIBRARIES}" + HINTS "${WAYLAND_CLIENT_PKG_LIBRARIES}" ) find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h - HINTS ${XKBCOMMON_INCLUDE_DIRS} + HINTS ${XKBCOMMON_PC_INCLUDE_DIRS} ) find_library(XKBCOMMON_LIBS NAMES xkbcommon - HINTS "${XKBCOMMON_LIBRARIES}" + HINTS "${XKBCOMMON_PC_LIBRARIES}" ) include(FindPackageHandleStandardArgs) diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index c7dbb83bf..20d0ad01a 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -696,9 +696,11 @@ static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_s wl_pointer_set_user_data(input->pointer, input); wl_pointer_add_listener(input->pointer, &pointer_listener, input); } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) { +#ifdef WL_POINTER_RELEASE_SINCE_VERSION if (input->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) wl_pointer_release(input->pointer); else +#endif wl_pointer_destroy(input->pointer); input->pointer = NULL; } @@ -708,9 +710,11 @@ static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_s wl_keyboard_set_user_data(input->keyboard, input); wl_keyboard_add_listener(input->keyboard, &keyboard_listener, input); } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) { +#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION if (input->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) wl_keyboard_release(input->keyboard); else +#endif wl_keyboard_destroy(input->keyboard); input->keyboard = NULL; } @@ -720,9 +724,11 @@ static void seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_s wl_touch_set_user_data(input->touch, input); wl_touch_add_listener(input->touch, &touch_listener, input); } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) { +#ifdef WL_TOUCH_RELEASE_SINCE_VERSION if (input->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) wl_touch_release(input->touch); else +#endif wl_touch_destroy(input->touch); input->touch = NULL; } @@ -788,9 +794,11 @@ error_xkb_context: void UwacSeatDestroy(UwacSeat *s) { if (s->seat) { +#ifdef WL_SEAT_RELEASE_SINCE_VERSION if (s->seat_version >= WL_SEAT_RELEASE_SINCE_VERSION) wl_seat_release(s->seat); else +#endif wl_seat_destroy(s->seat); } s->seat = NULL; @@ -802,23 +810,29 @@ void UwacSeatDestroy(UwacSeat *s) { xkb_context_unref(s->xkb_context); if (s->pointer) { +#ifdef WL_POINTER_RELEASE_SINCE_VERSION if (s->seat_version >= WL_POINTER_RELEASE_SINCE_VERSION) wl_pointer_release(s->pointer); else +#endif wl_pointer_destroy(s->pointer); } if (s->touch) { +#ifdef WL_TOUCH_RELEASE_SINCE_VERSION if (s->seat_version >= WL_TOUCH_RELEASE_SINCE_VERSION) wl_touch_release(s->touch); else +#endif wl_touch_destroy(s->touch); } if (s->keyboard) { +#ifdef WL_KEYBOARD_RELEASE_SINCE_VERSION if (s->seat_version >= WL_KEYBOARD_RELEASE_SINCE_VERSION) wl_keyboard_release(s->keyboard); else +#endif wl_keyboard_destroy(s->keyboard); } From c1c43f91c717cd1eb8f83d1fe41c2d7ea8a45975 Mon Sep 17 00:00:00 2001 From: David FORT Date: Tue, 23 Feb 2016 09:22:15 +0100 Subject: [PATCH 042/128] Fixed detection of wayland libs --- cmake/FindWayland.cmake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index ff5958b36..93668d338 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -43,7 +43,7 @@ find_path(WAYLAND_INCLUDE_DIR wayland-client.h find_library(WAYLAND_LIBS NAMES "wayland-client" - HINTS "${WAYLAND_CLIENT_PKG_LIBRARIES}" + HINTS "${WAYLAND_CLIENT_PKG_LIBRARY_DIRS}" ) find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h @@ -52,7 +52,7 @@ find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h find_library(XKBCOMMON_LIBS NAMES xkbcommon - HINTS "${XKBCOMMON_PC_LIBRARIES}" + HINTS "${XKBCOMMON_PC_LIBRARY_DIRS}" ) include(FindPackageHandleStandardArgs) From 0bf2faedc47078509d0742d8b1a166faa20b6e02 Mon Sep 17 00:00:00 2001 From: David FORT Date: Tue, 23 Feb 2016 14:09:14 +0100 Subject: [PATCH 043/128] Fix compilation with out-of-tree builds Generated files weren't in the include path --- uwac/libuwac/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/uwac/libuwac/CMakeLists.txt b/uwac/libuwac/CMakeLists.txt index b8219bba2..49a663407 100644 --- a/uwac/libuwac/CMakeLists.txt +++ b/uwac/libuwac/CMakeLists.txt @@ -44,6 +44,7 @@ include_directories(${WAYLAND_INCLUDE_DIR}) include_directories(${XKBCOMMON_INCLUDE_DIR}) include_directories("${CMAKE_SOURCE_DIR}/uwac/include") include_directories("${CMAKE_BINARY_DIR}/uwac/include") +include_directories("${CMAKE_BINARY_DIR}/uwac/libuwac") add_definitions(-DBUILD_IVI -DBUILD_FULLSCREEN_SHELL -DENABLE_XKBCOMMON) From 8b9c40248a368a5a1c5cb6a894c841a8f90a2d7b Mon Sep 17 00:00:00 2001 From: volth Date: Mon, 19 Oct 2015 18:29:30 +0000 Subject: [PATCH 044/128] Increase TCP_USER_TIMEOUT to avoid disconnections. TCP_USER_TIMEOUT value is too small, it is only 4 seconds. That causes random disconnections reported in the bug report https://github.com/FreeRDP/FreeRDP/issues/2802 This patch should fix the bug report https://github.com/FreeRDP/FreeRDP/issues/2802 --- libfreerdp/core/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index 24bbcd05d..c4af4c295 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -1027,7 +1027,7 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd) #endif #ifdef TCP_USER_TIMEOUT - optval = 4000; + optval = 60000; optlen = sizeof(optval); if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*) &optval, optlen) < 0) From be02849ecefeae53af92a0273a9bd7349e881ad9 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 23 Feb 2016 15:34:58 +0100 Subject: [PATCH 045/128] tcp: set the timeout to 9s Set the TCP_USER_TIMEOUT to 9s as suggested by @giox069. See #3015 for details --- libfreerdp/core/tcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/core/tcp.c b/libfreerdp/core/tcp.c index c4af4c295..1a6cff273 100644 --- a/libfreerdp/core/tcp.c +++ b/libfreerdp/core/tcp.c @@ -1027,7 +1027,7 @@ BOOL freerdp_tcp_set_keep_alive_mode(int sockfd) #endif #ifdef TCP_USER_TIMEOUT - optval = 60000; + optval = 9000; optlen = sizeof(optval); if (setsockopt(sockfd, SOL_TCP, TCP_USER_TIMEOUT, (void*) &optval, optlen) < 0) From dd93fd2b3de7bef3f4faebfe04448344a0a5ab88 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Tue, 23 Feb 2016 16:25:05 +0100 Subject: [PATCH 046/128] timezon: add support for tz package Some distributions don't use /etc/localtime but /etc/TZ instead. If /etc/localtime isn't find try this. For details see #2818 --- libfreerdp/locale/timezone.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libfreerdp/locale/timezone.c b/libfreerdp/locale/timezone.c index 573504956..a37b9ea8f 100644 --- a/libfreerdp/locale/timezone.c +++ b/libfreerdp/locale/timezone.c @@ -1567,9 +1567,11 @@ char* freerdp_get_unix_timezone_identifier() * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime * will point to /usr/share/zoneinfo/region/place where region/place could be * America/Montreal for example. + * Some distributions do have to symlink at /etc/TZ. */ - if ((len = readlink("/etc/localtime", buf, sizeof(buf) - 1)) != -1) + if ((len = readlink("/etc/localtime", buf, sizeof(buf) - 1)) != -1 || + (len = readlink("/etc/TZ", buf, sizeof(buf) - 1)) != -1) { int num = 0; int pos = len; From 24c93e4de7c3864e77cd21fafa57c848b3e96898 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 10 Feb 2016 11:20:52 +0100 Subject: [PATCH 047/128] Resetting abortEvent only on connect and reconnect. --- libfreerdp/core/connection.c | 2 -- libfreerdp/core/freerdp.c | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 5047aadfe..286643e10 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -312,8 +312,6 @@ BOOL rdp_client_disconnect(rdpRdp* rdp) { BOOL status; - ResetEvent(rdp->context->abortEvent); - if (rdp->settingsCopy) { freerdp_settings_free(rdp->settingsCopy); diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 91eae992d..07bb43736 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -383,6 +383,7 @@ BOOL freerdp_reconnect(freerdp* instance) BOOL status; rdpRdp* rdp = instance->context->rdp; + ResetEvent(instance->context->abortEvent); status = rdp_client_reconnect(rdp); return status; From d28cb6ac6af1eeea9009d9c43b6f46c3a307f7cb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 23 Feb 2016 15:58:48 +0100 Subject: [PATCH 048/128] Removed function call with invalid arguments. --- libfreerdp/core/rdp.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 2675a22f5..c3488f4f5 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -340,10 +340,7 @@ BOOL rdp_read_header(rdpRdp* rdp, wStream* s, UINT16* length, UINT16* channelId) return FALSE; if (!rdp->instance) - { - freerdp_abort_connect(rdp->instance); return FALSE; - } context = rdp->instance->context; From db44d277df9d047b6ba9138cba47c085dbfe70fd Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Tue, 23 Feb 2016 10:49:52 +0100 Subject: [PATCH 049/128] server/shadow: Build libraries for shadow subsystems Commit 60ae27b0 decoupled subsystem implementations and shadow framework core by moving subsystem specific code right into freerdp-shadow-cli. This, however, doesn't allow applications that would like to link libfreerdp-shadow, in order to embed RDP shadow server, to reuse also the subsystem module. 3rd party developers now have to either provide their own subsystem code (copied from FreeRDP sources or written from scratch) or be limited to usaging freerdp-shadow-cli executable, which doesn't expose all functions of the shadow server library (e.g. enumeration of available monitors). This change moves the shadow subsystem out of the executable into new freerdp-shadow-subsystem library, which freerdp-shadow-cli and potentially other applications can link to. --- server/shadow/CMakeLists.txt | 43 +++++++++++++++++++++++++++--------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 421d4bd82..67c3aa2a5 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -92,10 +92,10 @@ endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") -# command-line executable +# subsystem library -set(MODULE_NAME "freerdp-shadow-cli") -set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI") +set(MODULE_NAME "freerdp-shadow-subsystem") +set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_SUBSYSTEM") if(WIN32) set(WITH_SHADOW_WIN 1) @@ -225,9 +225,6 @@ if(WITH_SHADOW_MAC) list(APPEND ${MODULE_PREFIX}_MAC_LIBS ${IOKIT} ${IOSURFACE} ${CARBON}) endif() -set(${MODULE_PREFIX}_SRCS - shadow.c) - set(${MODULE_PREFIX}_WIN_SRCS Win/win_rdp.c Win/win_rdp.h @@ -248,20 +245,46 @@ set(${MODULE_PREFIX}_MAC_SRCS if(WITH_SHADOW_WIN) add_definitions(-DWITH_SHADOW_WIN) - list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_WIN_LIBS}) elseif(WITH_SHADOW_X11) add_definitions(-DWITH_SHADOW_X11) - list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_X11_SRCS}) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_X11_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_X11_LIBS}) elseif(WITH_SHADOW_MAC) add_definitions(-DWITH_SHADOW_MAC) - list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_MAC_SRCS}) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_MAC_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_MAC_LIBS}) endif() list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_AUTH_LIBS}) +add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) + +if (WITH_LIBRARY_VERSIONING) + set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION}) +endif() + +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server) +if (WITH_DEBUG_SYMBOLS AND MSVC) + install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT symbols) +endif() + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") + +# command-line executable + +set(MODULE_NAME "freerdp-shadow-cli") +set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI") + +set(${MODULE_PREFIX}_SRCS + shadow.c) + # On windows create dll version information. # Vendor, product and year are already set in top level CMakeLists.txt if (WIN32) @@ -280,7 +303,7 @@ endif() add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) -set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-shadow-subsystem) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) From 447ac23aeee48719439c05add8167ccee2627002 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 23 Feb 2016 18:08:18 +0100 Subject: [PATCH 050/128] Refactored timezone functions. --- include/freerdp/locale/timezone.h | 37 - include/freerdp/settings.h | 30 +- libfreerdp/core/settings.c | 8 +- libfreerdp/core/timezone.c | 90 +- libfreerdp/core/timezone.h | 4 - libfreerdp/locale/CMakeLists.txt | 1 - libfreerdp/locale/timezone.c | 1772 ---------------------------- winpr/libwinpr/timezone/timezone.c | 1710 ++++++++++++++++++++++++++- 8 files changed, 1751 insertions(+), 1901 deletions(-) delete mode 100644 include/freerdp/locale/timezone.h delete mode 100644 libfreerdp/locale/timezone.c diff --git a/include/freerdp/locale/timezone.h b/include/freerdp/locale/timezone.h deleted file mode 100644 index 1d062c8f1..000000000 --- a/include/freerdp/locale/timezone.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Time Zone Redirection - * - * Copyright 2012 Marc-Andre Moreau - * - * 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 FREERDP_LOCALE_TIMEZONE_H -#define FREERDP_LOCALE_TIMEZONE_H - -#include -#include -#include - -#ifdef __cplusplus - extern "C" { -#endif - -FREERDP_API void freerdp_time_zone_detect(TIME_ZONE_INFO* clientTimeZone); - -#ifdef __cplusplus - } -#endif - -#endif /* FREERDP_LOCALE_TIMEZONE_H */ diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index 268c6351e..a53054fab 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -21,6 +21,8 @@ #ifndef FREERDP_SETTINGS_H #define FREERDP_SETTINGS_H +#include + #include #include @@ -269,32 +271,6 @@ typedef struct _TARGET_NET_ADDRESS TARGET_NET_ADDRESS; #define ORIENTATION_LANDSCAPE_FLIPPED 180 #define ORIENTATION_PORTRAIT_FLIPPED 270 -/* SYSTEM_TIME */ -typedef struct -{ - UINT16 wYear; - UINT16 wMonth; - UINT16 wDayOfWeek; - UINT16 wDay; - UINT16 wHour; - UINT16 wMinute; - UINT16 wSecond; - UINT16 wMilliseconds; -} SYSTEM_TIME; - -/* TIME_ZONE_INFORMATION */ -struct _TIME_ZONE_INFO -{ - UINT32 bias; - char standardName[32]; - SYSTEM_TIME standardDate; - UINT32 standardBias; - char daylightName[32]; - SYSTEM_TIME daylightDate; - UINT32 daylightBias; -}; -typedef struct _TIME_ZONE_INFO TIME_ZONE_INFO; - /* ARC_CS_PRIVATE_PACKET */ typedef struct { @@ -977,7 +953,7 @@ struct rdp_settings UINT64 padding0896[896 - 837]; /* 837 */ /* Client Info (Time Zone) */ - ALIGN64 TIME_ZONE_INFO* ClientTimeZone; /* 896 */ + ALIGN64 LPTIME_ZONE_INFORMATION ClientTimeZone; /* 896 */ ALIGN64 char* DynamicDSTTimeZoneKeyName; /* 897 */ ALIGN64 BOOL DynamicDaylightTimeDisabled; /* 898 */ UINT64 padding0960[960 - 899]; /* 899 */ diff --git a/libfreerdp/core/settings.c b/libfreerdp/core/settings.c index c7d4b30ff..1002d1770 100644 --- a/libfreerdp/core/settings.c +++ b/libfreerdp/core/settings.c @@ -472,7 +472,7 @@ rdpSettings* freerdp_settings_new(DWORD flags) if (!settings->ServerAutoReconnectCookie) goto out_fail; - settings->ClientTimeZone = (TIME_ZONE_INFO*) calloc(1,sizeof(TIME_ZONE_INFO)); + settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION) calloc(1,sizeof(TIME_ZONE_INFORMATION)); if (!settings->ClientTimeZone) goto out_fail; @@ -762,10 +762,10 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) CopyMemory(_settings->ClientAutoReconnectCookie, settings->ClientAutoReconnectCookie, sizeof(ARC_CS_PRIVATE_PACKET)); CopyMemory(_settings->ServerAutoReconnectCookie, settings->ServerAutoReconnectCookie, sizeof(ARC_SC_PRIVATE_PACKET)); - _settings->ClientTimeZone = (TIME_ZONE_INFO*) malloc(sizeof(TIME_ZONE_INFO)); + _settings->ClientTimeZone = (LPTIME_ZONE_INFORMATION) malloc(sizeof(TIME_ZONE_INFORMATION)); if (!_settings->ClientTimeZone) goto out_fail; - CopyMemory(_settings->ClientTimeZone, settings->ClientTimeZone, sizeof(TIME_ZONE_INFO)); + CopyMemory(_settings->ClientTimeZone, settings->ClientTimeZone, sizeof(TIME_ZONE_INFORMATION)); _settings->TargetNetAddressCount = settings->TargetNetAddressCount; @@ -815,7 +815,7 @@ rdpSettings* freerdp_settings_clone(rdpSettings* settings) goto out_fail; } - if (_settings->DeviceArraySize < _settings->DeviceCount) + if (_settings->DeviceArraySize < _settings->DeviceCount) { _settings->DeviceCount = 0; _settings->DeviceArraySize = 0; diff --git a/libfreerdp/core/timezone.c b/libfreerdp/core/timezone.c index 95f06a356..1aee3ba87 100644 --- a/libfreerdp/core/timezone.c +++ b/libfreerdp/core/timezone.c @@ -22,9 +22,13 @@ #endif #include +#include #include "timezone.h" +static void rdp_read_system_time(wStream* s, SYSTEMTIME* system_time); +static void rdp_write_system_time(wStream* s, SYSTEMTIME* system_time); + /** * Read SYSTEM_TIME structure (TS_SYSTEMTIME).\n * @msdn{cc240478} @@ -32,7 +36,7 @@ * @param system_time system time structure */ -void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time) +void rdp_read_system_time(wStream* s, SYSTEMTIME* system_time) { Stream_Read_UINT16(s, system_time->wYear); /* wYear, must be set to 0 */ Stream_Read_UINT16(s, system_time->wMonth); /* wMonth */ @@ -51,7 +55,7 @@ void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time) * @param system_time system time structure */ -void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time) +void rdp_write_system_time(wStream* s, SYSTEMTIME* system_time) { Stream_Write_UINT16(s, system_time->wYear); /* wYear, must be set to 0 */ Stream_Write_UINT16(s, system_time->wMonth); /* wMonth */ @@ -76,34 +80,26 @@ void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time) BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) { - char* str = NULL; - TIME_ZONE_INFO* clientTimeZone; + LPTIME_ZONE_INFORMATION tz; if (Stream_GetRemainingLength(s) < 172) return FALSE; - clientTimeZone = settings->ClientTimeZone; + tz = settings->ClientTimeZone; - Stream_Read_UINT32(s, clientTimeZone->bias); /* Bias */ + Stream_Read_UINT32(s, tz->Bias); /* Bias */ /* standardName (64 bytes) */ - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); - Stream_Seek(s, 64); - strncpy(clientTimeZone->standardName, str, sizeof(clientTimeZone->standardName)); - free(str); - str = NULL; + Stream_Read(s, tz->StandardName, sizeof(tz->StandardName)); - rdp_read_system_time(s, &clientTimeZone->standardDate); /* StandardDate */ - Stream_Read_UINT32(s, clientTimeZone->standardBias); /* StandardBias */ + rdp_read_system_time(s, &tz->StandardDate); /* StandardDate */ + Stream_Read_UINT32(s, tz->StandardBias); /* StandardBias */ /* daylightName (64 bytes) */ - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); - Stream_Seek(s, 64); - strncpy(clientTimeZone->daylightName, str, sizeof(clientTimeZone->daylightName)); - free(str); + Stream_Read(s, tz->DaylightName, sizeof(tz->DaylightName)); - rdp_read_system_time(s, &clientTimeZone->daylightDate); /* DaylightDate */ - Stream_Read_UINT32(s, clientTimeZone->daylightBias); /* DaylightBias */ + rdp_read_system_time(s, &tz->DaylightDate); /* DaylightDate */ + Stream_Read_UINT32(s, tz->DaylightBias); /* DaylightBias */ return TRUE; } @@ -117,53 +113,37 @@ BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) void rdp_write_client_time_zone(wStream* s, rdpSettings* settings) { - WCHAR* standardName = NULL; - WCHAR* daylightName = NULL; - int standardNameLength; - int daylightNameLength; - TIME_ZONE_INFO* clientTimeZone; + LPTIME_ZONE_INFORMATION tz; + DWORD rc; - clientTimeZone = settings->ClientTimeZone; - freerdp_time_zone_detect(clientTimeZone); + tz = settings->ClientTimeZone; + rc = GetTimeZoneInformation(tz); - standardNameLength = ConvertToUnicode(CP_UTF8, 0, clientTimeZone->standardName, -1, &standardName, 0) * 2; - daylightNameLength = ConvertToUnicode(CP_UTF8, 0, clientTimeZone->daylightName, -1, &daylightName, 0) * 2; - - if (standardNameLength > 62) - standardNameLength = 62; - - if (daylightNameLength > 62) - daylightNameLength = 62; - - /* Bias */ - Stream_Write_UINT32(s, clientTimeZone->bias); + /* Bias */ + Stream_Write_UINT32(s, tz->Bias); /* standardName (64 bytes) */ - Stream_Write(s, standardName, standardNameLength); - Stream_Zero(s, 64 - standardNameLength); + Stream_Write(s, tz->StandardName, sizeof(tz->StandardName)); - /* StandardDate */ - rdp_write_system_time(s, &clientTimeZone->standardDate); + /* StandardDate */ + rdp_write_system_time(s, &tz->StandardDate); - DEBUG_TIMEZONE("bias=%d stdName='%s' dlName='%s'", clientTimeZone->bias, clientTimeZone->standardName, clientTimeZone->daylightName); + DEBUG_TIMEZONE("bias=%d stdName='%s' dlName='%s'", tz->Bias, + tz->StandardName, tz->DaylightName); /* Note that StandardBias is ignored if no valid standardDate is provided. */ - /* StandardBias */ - Stream_Write_UINT32(s, clientTimeZone->standardBias); - DEBUG_TIMEZONE("StandardBias=%d", clientTimeZone->standardBias); + /* StandardBias */ + Stream_Write_UINT32(s, tz->StandardBias); + DEBUG_TIMEZONE("StandardBias=%d", tz->StandardBias); /* daylightName (64 bytes) */ - Stream_Write(s, daylightName, daylightNameLength); - Stream_Zero(s, 64 - daylightNameLength); + Stream_Write(s, tz->DaylightName, sizeof(tz->DaylightName)); - /* DaylightDate */ - rdp_write_system_time(s, &clientTimeZone->daylightDate); + /* DaylightDate */ + rdp_write_system_time(s, &tz->DaylightDate); /* Note that DaylightBias is ignored if no valid daylightDate is provided. */ - /* DaylightBias */ - Stream_Write_UINT32(s, clientTimeZone->daylightBias); - DEBUG_TIMEZONE("DaylightBias=%d", clientTimeZone->daylightBias); - - free(standardName); - free(daylightName); + /* DaylightBias */ + Stream_Write_UINT32(s, tz->DaylightBias); + DEBUG_TIMEZONE("DaylightBias=%d", tz->DaylightBias); } diff --git a/libfreerdp/core/timezone.h b/libfreerdp/core/timezone.h index a45cd4437..d40940988 100644 --- a/libfreerdp/core/timezone.h +++ b/libfreerdp/core/timezone.h @@ -28,13 +28,9 @@ #include #include -#include #include -void rdp_read_system_time(wStream* s, SYSTEM_TIME* system_time); -void rdp_write_system_time(wStream* s, SYSTEM_TIME* system_time); -void rdp_get_client_time_zone(wStream* s, rdpSettings* settings); BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings); void rdp_write_client_time_zone(wStream* s, rdpSettings* settings); diff --git a/libfreerdp/locale/CMakeLists.txt b/libfreerdp/locale/CMakeLists.txt index f6bdf73f8..e418e0c9f 100644 --- a/libfreerdp/locale/CMakeLists.txt +++ b/libfreerdp/locale/CMakeLists.txt @@ -22,7 +22,6 @@ set(${MODULE_PREFIX}_SRCS keyboard_layout.c keyboard.c locale.c - timezone.c liblocale.h) set(${MODULE_PREFIX}_X11_SRCS diff --git a/libfreerdp/locale/timezone.c b/libfreerdp/locale/timezone.c deleted file mode 100644 index a37b9ea8f..000000000 --- a/libfreerdp/locale/timezone.c +++ /dev/null @@ -1,1772 +0,0 @@ -/** - * FreeRDP: A Remote Desktop Protocol Implementation - * Time Zone Redirection - * - * Copyright 2012 Marc-Andre Moreau - * - * 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 - -#define __USE_XOPEN -#include - -#ifndef _WIN32 -#include -#endif - -#include "liblocale.h" - -#include -#include - -#define TAG FREERDP_TAG("locale") - -/* Time Zone Redirection table generated with TimeZones.cs script */ - - -struct _SYSTEM_TIME_ENTRY -{ - UINT16 wYear; - UINT16 wMonth; - UINT16 wDayOfWeek; - UINT16 wDay; - UINT16 wHour; - UINT16 wMinute; - UINT16 wSecond; - UINT16 wMilliseconds; -}; -typedef struct _SYSTEM_TIME_ENTRY SYSTEM_TIME_ENTRY; - -struct _TIME_ZONE_RULE_ENTRY -{ - UINT64 TicksStart; - UINT64 TicksEnd; - INT32 DaylightDelta; - SYSTEM_TIME_ENTRY StandardDate; - SYSTEM_TIME_ENTRY DaylightDate; -}; -typedef struct _TIME_ZONE_RULE_ENTRY TIME_ZONE_RULE_ENTRY; - -struct _TIME_ZONE_ENTRY -{ - const char* Id; - UINT32 Bias; - BOOL SupportsDST; - const char* DisplayName; - const char* StandardName; - const char* DaylightName; - TIME_ZONE_RULE_ENTRY* RuleTable; - UINT32 RuleTableCount; -}; -typedef struct _TIME_ZONE_ENTRY TIME_ZONE_ENTRY; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_3[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_4[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_5[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_7[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_8[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_10[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_11[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_14[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_15[] = -{ - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_17[] = -{ - { 633662964000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 9, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_18[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_19[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_21[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 5, 6, 1, 23, 59 }, { 0, 8, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_22[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 1 }, { 0, 4, 0, 1, 0, 1 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 0, 1 }, }, - { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_23[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_24[] = -{ - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 1, 1, 1, 0, 0 }, { 0, 12, 0, 1, 0, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 1, 4, 1, 0, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_26[] = -{ - { 633662964000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, - { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_27[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_28[] = -{ - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 1, 6, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_30[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_31[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_33[] = -{ - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 0, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 5, 0, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 8, 6, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 7, 6, 1, 23, 59 }, { 0, 4, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_35[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 0, 1, 1, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_37[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_38[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_39[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_40[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_42[] = -{ - { 634293684000000000ULL, 180000000000ULL, -60, { 0, 9, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_43[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 5, 1, 1, 0 }, { 0, 3, 4, 1, 0, 0 }, }, - { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 10, 5, 1, 1, 0 }, { 0, 3, 4, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_44[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_45[] = -{ - { 633978324000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 0 }, { 0, 3, 0, 1, 0, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_46[] = -{ - { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_47[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 3, 1, 23, 59 }, { 0, 3, 5, 1, 23, 59 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 3155378292000000000ULL, 636188436000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_49[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_50[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 1, 1, 3, 0 }, }, - { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_51[] = -{ - { 632716020000000000ULL, 632401524000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, - { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, - { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_52[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_53[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 10, 1, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_54[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_57[] = -{ - { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 2, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 9, 6, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, - { 3155378292000000000ULL, 633663828000000000ULL, 60, { 0, 9, 1, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_59[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 5, 0 }, { 0, 3, 0, 1, 4, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_60[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_61[] = -{ - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 1, 2, 1, 0, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 1, 4, 1, 0, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_63[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_65[] = -{ - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 4, 2, 1, 23, 59 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_71[] = -{ - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 12, 4, 1, 23, 59 }, { 0, 6, 5, 1, 23, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_72[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_75[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_77[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_79[] = -{ - { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 1, 0, 1, 0, 0 }, { 0, 12, 0, 1, 2, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 1, 4, 1, 0, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_82[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_85[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_88[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_90[] = -{ - { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_91[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_93[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_94[] = -{ - { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_96[] = -{ - { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 1, 4, 1, 0, 0 }, { 0, 11, 0, 1, 2, 0 }, }, - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 1, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, - { 3155378292000000000ULL, 634926132000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_97[] = -{ - { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_98[] = -{ - { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } -}; - -static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_100[] = -{ - { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 1, 5, 1, 0, 0 }, { 0, 9, 6, 1, 23, 59 }, }, - { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 1, 0 }, { 0, 9, 0, 1, 0, 0 }, } -}; - -static const TIME_ZONE_ENTRY TimeZoneTable[] = -{ - { - "Dateline Standard Time", 720, FALSE, "(UTC-12:00) International Date Line West", - "Dateline Standard Time", "Dateline Daylight Time", - NULL, 0 - }, - { - "UTC-11", 780, FALSE, "(UTC-11:00) Coordinated Universal Time-11", - "UTC-11", "UTC-11", - NULL, 0 - }, - { - "Hawaiian Standard Time", 840, FALSE, "(UTC-10:00) Hawaii", - "Hawaiian Standard Time", "Hawaiian Daylight Time", - NULL, 0 - }, - { - "Alaskan Standard Time", 900, TRUE, "(UTC-09:00) Alaska", - "Alaskan Standard Time", "Alaskan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_3, 2 - }, - { - "Pacific Standard Time (Mexico)", 960, TRUE, "(UTC-08:00) Baja California", - "Pacific Standard Time (Mexico)", "Pacific Daylight Time (Mexico)", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_4, 1 - }, - { - "Pacific Standard Time", 960, TRUE, "(UTC-08:00) Pacific Time (US & Canada)", - "Pacific Standard Time", "Pacific Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_5, 2 - }, - { - "US Mountain Standard Time", 1020, FALSE, "(UTC-07:00) Arizona", - "US Mountain Standard Time", "US Mountain Daylight Time", - NULL, 0 - }, - { - "Mountain Standard Time (Mexico)", 1020, TRUE, "(UTC-07:00) Chihuahua, La Paz, Mazatlan", - "Mountain Standard Time (Mexico)", "Mountain Daylight Time (Mexico)", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_7, 1 - }, - { - "Mountain Standard Time", 1020, TRUE, "(UTC-07:00) Mountain Time (US & Canada)", - "Mountain Standard Time", "Mountain Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_8, 2 - }, - { - "Central America Standard Time", 1080, FALSE, "(UTC-06:00) Central America", - "Central America Standard Time", "Central America Daylight Time", - NULL, 0 - }, - { - "Central Standard Time", 1080, TRUE, "(UTC-06:00) Central Time (US & Canada)", - "Central Standard Time", "Central Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_10, 2 - }, - { - "Central Standard Time (Mexico)", 1080, TRUE, "(UTC-06:00) Guadalajara, Mexico City, Monterrey", - "Central Standard Time (Mexico)", "Central Daylight Time (Mexico)", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_11, 1 - }, - { - "Canada Central Standard Time", 1080, FALSE, "(UTC-06:00) Saskatchewan", - "Canada Central Standard Time", "Canada Central Daylight Time", - NULL, 0 - }, - { - "SA Pacific Standard Time", 1140, FALSE, "(UTC-05:00) Bogota, Lima, Quito", - "SA Pacific Standard Time", "SA Pacific Daylight Time", - NULL, 0 - }, - { - "Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Eastern Time (US & Canada)", - "Eastern Standard Time", "Eastern Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_14, 2 - }, - { - "US Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Indiana (East)", - "US Eastern Standard Time", "US Eastern Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_15, 2 - }, - { - "Venezuela Standard Time", 1170, FALSE, "(UTC-04:30) Caracas", - "Venezuela Standard Time", "Venezuela Daylight Time", - NULL, 0 - }, - { - "Paraguay Standard Time", 1200, TRUE, "(UTC-04:00) Asuncion", - "Paraguay Standard Time", "Paraguay Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_17, 14 - }, - { - "Atlantic Standard Time", 1200, TRUE, "(UTC-04:00) Atlantic Time (Canada)", - "Atlantic Standard Time", "Atlantic Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_18, 2 - }, - { - "Central Brazilian Standard Time", 1200, TRUE, "(UTC-04:00) Cuiaba", - "Central Brazilian Standard Time", "Central Brazilian Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_19, 35 - }, - { - "SA Western Standard Time", 1200, FALSE, "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", - "SA Western Standard Time", "SA Western Daylight Time", - NULL, 0 - }, - { - "Pacific SA Standard Time", 1200, TRUE, "(UTC-04:00) Santiago", - "Pacific SA Standard Time", "Pacific SA Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_21, 6 - }, - { - "Newfoundland Standard Time", 1230, TRUE, "(UTC-03:30) Newfoundland", - "Newfoundland Standard Time", "Newfoundland Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_22, 7 - }, - { - "E. South America Standard Time", 1260, TRUE, "(UTC-03:00) Brasilia", - "E. South America Standard Time", "E. South America Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_23, 35 - }, - { - "Argentina Standard Time", 1260, TRUE, "(UTC-03:00) Buenos Aires", - "Argentina Standard Time", "Argentina Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_24, 3 - }, - { - "SA Eastern Standard Time", 1260, FALSE, "(UTC-03:00) Cayenne, Fortaleza", - "SA Eastern Standard Time", "SA Eastern Daylight Time", - NULL, 0 - }, - { - "Greenland Standard Time", 1260, TRUE, "(UTC-03:00) Greenland", - "Greenland Standard Time", "Greenland Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_26, 14 - }, - { - "Montevideo Standard Time", 1260, TRUE, "(UTC-03:00) Montevideo", - "Montevideo Standard Time", "Montevideo Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_27, 2 - }, - { - "Bahia Standard Time", 1260, TRUE, "(UTC-03:00) Salvador", - "Bahia Standard Time", "Bahia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_28, 30 - }, - { - "UTC-02", 1320, FALSE, "(UTC-02:00) Coordinated Universal Time-02", - "UTC-02", "UTC-02", - NULL, 0 - }, - { - "Mid-Atlantic Standard Time", 1320, TRUE, "(UTC-02:00) Mid-Atlantic", - "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_30, 1 - }, - { - "Azores Standard Time", 1380, TRUE, "(UTC-01:00) Azores", - "Azores Standard Time", "Azores Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_31, 1 - }, - { - "Cape Verde Standard Time", 1380, FALSE, "(UTC-01:00) Cape Verde Is.", - "Cape Verde Standard Time", "Cape Verde Daylight Time", - NULL, 0 - }, - { - "Morocco Standard Time", 0, TRUE, "(UTC) Casablanca", - "Morocco Standard Time", "Morocco Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_33, 4 - }, - { - "UTC", 0, FALSE, "(UTC) Coordinated Universal Time", - "Coordinated Universal Time", "Coordinated Universal Time", - NULL, 0 - }, - { - "GMT Standard Time", 0, TRUE, "(UTC) Dublin, Edinburgh, Lisbon, London", - "GMT Standard Time", "GMT Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_35, 1 - }, - { - "Greenwich Standard Time", 0, FALSE, "(UTC) Monrovia, Reykjavik", - "Greenwich Standard Time", "Greenwich Daylight Time", - NULL, 0 - }, - { - "W. Europe Standard Time", 60, TRUE, "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", - "W. Europe Standard Time", "W. Europe Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_37, 1 - }, - { - "Central Europe Standard Time", 60, TRUE, "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", - "Central Europe Standard Time", "Central Europe Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_38, 1 - }, - { - "Romance Standard Time", 60, TRUE, "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", - "Romance Standard Time", "Romance Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_39, 1 - }, - { - "Central European Standard Time", 60, TRUE, "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", - "Central European Standard Time", "Central European Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_40, 1 - }, - { - "W. Central Africa Standard Time", 60, FALSE, "(UTC+01:00) West Central Africa", - "W. Central Africa Standard Time", "W. Central Africa Daylight Time", - NULL, 0 - }, - { - "Namibia Standard Time", 60, TRUE, "(UTC+01:00) Windhoek", - "Namibia Standard Time", "Namibia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_42, 2 - }, - { - "Jordan Standard Time", 120, TRUE, "(UTC+02:00) Amman", - "Jordan Standard Time", "Jordan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_43, 2 - }, - { - "GTB Standard Time", 120, TRUE, "(UTC+02:00) Athens, Bucharest, Istanbul", - "GTB Standard Time", "GTB Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_44, 1 - }, - { - "Middle East Standard Time", 120, TRUE, "(UTC+02:00) Beirut", - "Middle East Standard Time", "Middle East Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_45, 13 - }, - { - "Egypt Standard Time", 120, TRUE, "(UTC+02:00) Cairo", - "Egypt Standard Time", "Egypt Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_46, 6 - }, - { - "Syria Standard Time", 120, TRUE, "(UTC+02:00) Damascus", - "Syria Standard Time", "Syria Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_47, 12 - }, - { - "South Africa Standard Time", 120, FALSE, "(UTC+02:00) Harare, Pretoria", - "South Africa Standard Time", "South Africa Daylight Time", - NULL, 0 - }, - { - "FLE Standard Time", 120, TRUE, "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", - "FLE Standard Time", "FLE Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_49, 1 - }, - { - "Turkey Standard Time", 120, TRUE, "(UTC+02:00) Istanbul", - "Turkey Standard Time", "Turkey Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_50, 3 - }, - { - "Israel Standard Time", 120, TRUE, "(UTC+02:00) Jerusalem", - "Jerusalem Standard Time", "Jerusalem Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_51, 18 - }, - { - "E. Europe Standard Time", 120, TRUE, "(UTC+02:00) Nicosia", - "E. Europe Standard Time", "E. Europe Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_52, 1 - }, - { - "Arabic Standard Time", 180, TRUE, "(UTC+03:00) Baghdad", - "Arabic Standard Time", "Arabic Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_53, 2 - }, - { - "Kaliningrad Standard Time", 180, TRUE, "(UTC+03:00) Kaliningrad, Minsk", - "Kaliningrad Standard Time", "Kaliningrad Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_54, 1 - }, - { - "Arab Standard Time", 180, FALSE, "(UTC+03:00) Kuwait, Riyadh", - "Arab Standard Time", "Arab Daylight Time", - NULL, 0 - }, - { - "E. Africa Standard Time", 180, FALSE, "(UTC+03:00) Nairobi", - "E. Africa Standard Time", "E. Africa Daylight Time", - NULL, 0 - }, - { - "Iran Standard Time", 210, TRUE, "(UTC+03:30) Tehran", - "Iran Standard Time", "Iran Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_57, 3 - }, - { - "Arabian Standard Time", 240, FALSE, "(UTC+04:00) Abu Dhabi, Muscat", - "Arabian Standard Time", "Arabian Daylight Time", - NULL, 0 - }, - { - "Azerbaijan Standard Time", 240, TRUE, "(UTC+04:00) Baku", - "Azerbaijan Standard Time", "Azerbaijan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_59, 1 - }, - { - "Russian Standard Time", 240, TRUE, "(UTC+04:00) Moscow, St. Petersburg, Volgograd", - "Russian Standard Time", "Russian Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_60, 1 - }, - { - "Mauritius Standard Time", 240, TRUE, "(UTC+04:00) Port Louis", - "Mauritius Standard Time", "Mauritius Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_61, 2 - }, - { - "Georgian Standard Time", 240, FALSE, "(UTC+04:00) Tbilisi", - "Georgian Standard Time", "Georgian Daylight Time", - NULL, 0 - }, - { - "Caucasus Standard Time", 240, TRUE, "(UTC+04:00) Yerevan", - "Caucasus Standard Time", "Caucasus Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_63, 1 - }, - { - "Afghanistan Standard Time", 270, FALSE, "(UTC+04:30) Kabul", - "Afghanistan Standard Time", "Afghanistan Daylight Time", - NULL, 0 - }, - { - "Pakistan Standard Time", 300, TRUE, "(UTC+05:00) Islamabad, Karachi", - "Pakistan Standard Time", "Pakistan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_65, 2 - }, - { - "West Asia Standard Time", 300, FALSE, "(UTC+05:00) Tashkent", - "West Asia Standard Time", "West Asia Daylight Time", - NULL, 0 - }, - { - "India Standard Time", 330, FALSE, "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", - "India Standard Time", "India Daylight Time", - NULL, 0 - }, - { - "Sri Lanka Standard Time", 330, FALSE, "(UTC+05:30) Sri Jayawardenepura", - "Sri Lanka Standard Time", "Sri Lanka Daylight Time", - NULL, 0 - }, - { - "Nepal Standard Time", 345, FALSE, "(UTC+05:45) Kathmandu", - "Nepal Standard Time", "Nepal Daylight Time", - NULL, 0 - }, - { - "Central Asia Standard Time", 360, FALSE, "(UTC+06:00) Astana", - "Central Asia Standard Time", "Central Asia Daylight Time", - NULL, 0 - }, - { - "Bangladesh Standard Time", 360, TRUE, "(UTC+06:00) Dhaka", - "Bangladesh Standard Time", "Bangladesh Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_71, 1 - }, - { - "Ekaterinburg Standard Time", 360, TRUE, "(UTC+06:00) Ekaterinburg", - "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_72, 1 - }, - { - "Myanmar Standard Time", 390, FALSE, "(UTC+06:30) Yangon (Rangoon)", - "Myanmar Standard Time", "Myanmar Daylight Time", - NULL, 0 - }, - { - "SE Asia Standard Time", 420, FALSE, "(UTC+07:00) Bangkok, Hanoi, Jakarta", - "SE Asia Standard Time", "SE Asia Daylight Time", - NULL, 0 - }, - { - "N. Central Asia Standard Time", 420, TRUE, "(UTC+07:00) Novosibirsk", - "N. Central Asia Standard Time", "N. Central Asia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_75, 1 - }, - { - "China Standard Time", 480, FALSE, "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", - "China Standard Time", "China Daylight Time", - NULL, 0 - }, - { - "North Asia Standard Time", 480, TRUE, "(UTC+08:00) Krasnoyarsk", - "North Asia Standard Time", "North Asia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_77, 1 - }, - { - "Singapore Standard Time", 480, FALSE, "(UTC+08:00) Kuala Lumpur, Singapore", - "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", - NULL, 0 - }, - { - "W. Australia Standard Time", 480, TRUE, "(UTC+08:00) Perth", - "W. Australia Standard Time", "W. Australia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_79, 4 - }, - { - "Taipei Standard Time", 480, FALSE, "(UTC+08:00) Taipei", - "Taipei Standard Time", "Taipei Daylight Time", - NULL, 0 - }, - { - "Ulaanbaatar Standard Time", 480, FALSE, "(UTC+08:00) Ulaanbaatar", - "Ulaanbaatar Standard Time", "Ulaanbaatar Daylight Time", - NULL, 0 - }, - { - "North Asia East Standard Time", 540, TRUE, "(UTC+09:00) Irkutsk", - "North Asia East Standard Time", "North Asia East Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_82, 1 - }, - { - "Tokyo Standard Time", 540, FALSE, "(UTC+09:00) Osaka, Sapporo, Tokyo", - "Tokyo Standard Time", "Tokyo Daylight Time", - NULL, 0 - }, - { - "Korea Standard Time", 540, FALSE, "(UTC+09:00) Seoul", - "Korea Standard Time", "Korea Daylight Time", - NULL, 0 - }, - { - "Cen. Australia Standard Time", 570, TRUE, "(UTC+09:30) Adelaide", - "Cen. Australia Standard Time", "Cen. Australia Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_85, 2 - }, - { - "AUS Central Standard Time", 570, FALSE, "(UTC+09:30) Darwin", - "AUS Central Standard Time", "AUS Central Daylight Time", - NULL, 0 - }, - { - "E. Australia Standard Time", 600, FALSE, "(UTC+10:00) Brisbane", - "E. Australia Standard Time", "E. Australia Daylight Time", - NULL, 0 - }, - { - "AUS Eastern Standard Time", 600, TRUE, "(UTC+10:00) Canberra, Melbourne, Sydney", - "AUS Eastern Standard Time", "AUS Eastern Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_88, 2 - }, - { - "West Pacific Standard Time", 600, FALSE, "(UTC+10:00) Guam, Port Moresby", - "West Pacific Standard Time", "West Pacific Daylight Time", - NULL, 0 - }, - { - "Tasmania Standard Time", 600, TRUE, "(UTC+10:00) Hobart", - "Tasmania Standard Time", "Tasmania Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_90, 2 - }, - { - "Yakutsk Standard Time", 600, TRUE, "(UTC+10:00) Yakutsk", - "Yakutsk Standard Time", "Yakutsk Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_91, 1 - }, - { - "Central Pacific Standard Time", 660, FALSE, "(UTC+11:00) Solomon Is., New Caledonia", - "Central Pacific Standard Time", "Central Pacific Daylight Time", - NULL, 0 - }, - { - "Vladivostok Standard Time", 660, TRUE, "(UTC+11:00) Vladivostok", - "Vladivostok Standard Time", "Vladivostok Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_93, 1 - }, - { - "New Zealand Standard Time", 720, TRUE, "(UTC+12:00) Auckland, Wellington", - "New Zealand Standard Time", "New Zealand Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_94, 3 - }, - { - "UTC+12", 720, FALSE, "(UTC+12:00) Coordinated Universal Time+12", - "UTC+12", "UTC+12", - NULL, 0 - }, - { - "Fiji Standard Time", 720, TRUE, "(UTC+12:00) Fiji", - "Fiji Standard Time", "Fiji Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_96, 5 - }, - { - "Magadan Standard Time", 720, TRUE, "(UTC+12:00) Magadan", - "Magadan Standard Time", "Magadan Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_97, 1 - }, - { - "Kamchatka Standard Time", 720, TRUE, "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", - "Kamchatka Standard Time", "Kamchatka Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_98, 1 - }, - { - "Tonga Standard Time", 780, FALSE, "(UTC+13:00) Nuku'alofa", - "Tonga Standard Time", "Tonga Daylight Time", - NULL, 0 - }, - { - "Samoa Standard Time", 780, TRUE, "(UTC+13:00) Samoa", - "Samoa Standard Time", "Samoa Daylight Time", - (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_100, 2 - } -}; - -/* Table generated with WindowsZones.cs */ - -struct _WINDOWS_TZID_ENTRY -{ - const char* windows; - const char* tzid; -}; -typedef struct _WINDOWS_TZID_ENTRY WINDOWS_TZID_ENTRY; - -const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] = -{ - { "Afghanistan Standard Time", "Asia/Kabul" }, - { "Alaskan Standard Time", "America/Anchorage America/Juneau " - "America/Nome America/Sitka America/Yakutat" }, - { "Alaskan Standard Time", "America/Anchorage" }, - { "Arab Standard Time", "Asia/Aden" }, - { "Arab Standard Time", "Asia/Bahrain" }, - { "Arab Standard Time", "Asia/Kuwait" }, - { "Arab Standard Time", "Asia/Qatar" }, - { "Arab Standard Time", "Asia/Riyadh" }, - { "Arabian Standard Time", "Asia/Dubai" }, - { "Arabian Standard Time", "Asia/Muscat" }, - { "Arabian Standard Time", "Etc/GMT-4" }, - { "Arabic Standard Time", "Asia/Baghdad" }, - { "Argentina Standard Time", "America/Buenos_Aires America/Argentina/La_Rioja " - "America/Argentina/Rio_Gallegos America/Argentina/Salta " - "America/Argentina/San_Juan America/Argentina/San_Luis " - "America/Argentina/Tucuman America/Argentina/Ushuaia America/Catamarca " - "America/Cordoba America/Jujuy America/Mendoza" }, - { "Argentina Standard Time", "America/Buenos_Aires" }, - { "Atlantic Standard Time", "America/Halifax America/Glace_Bay " - "America/Goose_Bay America/Moncton" }, - { "Atlantic Standard Time", "America/Halifax" }, - { "Atlantic Standard Time", "America/Thule" }, - { "Atlantic Standard Time", "Atlantic/Bermuda" }, - { "AUS Central Standard Time", "Australia/Darwin" }, - { "AUS Eastern Standard Time", "Australia/Sydney Australia/Melbourne" }, - { "AUS Eastern Standard Time", "Australia/Sydney" }, - { "Azerbaijan Standard Time", "Asia/Baku" }, - { "Azores Standard Time", "America/Scoresbysund" }, - { "Azores Standard Time", "Atlantic/Azores" }, - { "Bahia Standard Time", "America/Bahia" }, - { "Bangladesh Standard Time", "Asia/Dhaka" }, - { "Bangladesh Standard Time", "Asia/Thimphu" }, - { "Canada Central Standard Time", "America/Regina America/Swift_Current" }, - { "Canada Central Standard Time", "America/Regina" }, - { "Cape Verde Standard Time", "Atlantic/Cape_Verde" }, - { "Cape Verde Standard Time", "Etc/GMT+1" }, - { "Caucasus Standard Time", "Asia/Yerevan" }, - { "Cen. Australia Standard Time", "Australia/Adelaide Australia/Broken_Hill" }, - { "Cen. Australia Standard Time", "Australia/Adelaide" }, - { "Central America Standard Time", "America/Belize" }, - { "Central America Standard Time", "America/Costa_Rica" }, - { "Central America Standard Time", "America/El_Salvador" }, - { "Central America Standard Time", "America/Guatemala" }, - { "Central America Standard Time", "America/Managua" }, - { "Central America Standard Time", "America/Tegucigalpa" }, - { "Central America Standard Time", "Etc/GMT+6" }, - { "Central America Standard Time", "Pacific/Galapagos" }, - { "Central Asia Standard Time", "Antarctica/Vostok" }, - { "Central Asia Standard Time", "Asia/Almaty Asia/Qyzylorda" }, - { "Central Asia Standard Time", "Asia/Almaty" }, - { "Central Asia Standard Time", "Asia/Bishkek" }, - { "Central Asia Standard Time", "Etc/GMT-6" }, - { "Central Asia Standard Time", "Indian/Chagos" }, - { "Central Brazilian Standard Time", "America/Cuiaba America/Campo_Grande" }, - { "Central Brazilian Standard Time", "America/Cuiaba" }, - { "Central Europe Standard Time", "Europe/Belgrade" }, - { "Central Europe Standard Time", "Europe/Bratislava" }, - { "Central Europe Standard Time", "Europe/Budapest" }, - { "Central Europe Standard Time", "Europe/Ljubljana" }, - { "Central Europe Standard Time", "Europe/Podgorica" }, - { "Central Europe Standard Time", "Europe/Prague" }, - { "Central Europe Standard Time", "Europe/Tirane" }, - { "Central European Standard Time", "Europe/Sarajevo" }, - { "Central European Standard Time", "Europe/Skopje" }, - { "Central European Standard Time", "Europe/Warsaw" }, - { "Central European Standard Time", "Europe/Zagreb" }, - { "Central Pacific Standard Time", "Antarctica/Macquarie" }, - { "Central Pacific Standard Time", "Etc/GMT-11" }, - { "Central Pacific Standard Time", "Pacific/Efate" }, - { "Central Pacific Standard Time", "Pacific/Guadalcanal" }, - { "Central Pacific Standard Time", "Pacific/Noumea" }, - { "Central Pacific Standard Time", "Pacific/Ponape Pacific/Kosrae" }, - { "Central Standard Time (Mexico)", "America/Mexico_City America/Bahia_Banderas " - "America/Cancun America/Merida America/Monterrey" }, - { "Central Standard Time (Mexico)", "America/Mexico_City" }, - { "Central Standard Time", "America/Chicago America/Indiana/Knox " - "America/Indiana/Tell_City America/Menominee " - "America/North_Dakota/Beulah America/North_Dakota/Center " - "America/North_Dakota/New_Salem" }, - { "Central Standard Time", "America/Chicago" }, - { "Central Standard Time", "America/Matamoros" }, - { "Central Standard Time", "America/Winnipeg America/Rainy_River " - "America/Rankin_Inlet America/Resolute" }, - { "Central Standard Time", "CST6CDT" }, - { "China Standard Time", "Asia/Hong_Kong" }, - { "China Standard Time", "Asia/Macau" }, - { "China Standard Time", "Asia/Shanghai Asia/Chongqing Asia/Harbin Asia/Kashgar Asia/Urumqi" }, - { "China Standard Time", "Asia/Shanghai" }, - { "Dateline Standard Time", "Etc/GMT+12" }, - { "E. Africa Standard Time", "Africa/Addis_Ababa" }, - { "E. Africa Standard Time", "Africa/Asmera" }, - { "E. Africa Standard Time", "Africa/Dar_es_Salaam" }, - { "E. Africa Standard Time", "Africa/Djibouti" }, - { "E. Africa Standard Time", "Africa/Juba" }, - { "E. Africa Standard Time", "Africa/Kampala" }, - { "E. Africa Standard Time", "Africa/Khartoum" }, - { "E. Africa Standard Time", "Africa/Mogadishu" }, - { "E. Africa Standard Time", "Africa/Nairobi" }, - { "E. Africa Standard Time", "Antarctica/Syowa" }, - { "E. Africa Standard Time", "Etc/GMT-3" }, - { "E. Africa Standard Time", "Indian/Antananarivo" }, - { "E. Africa Standard Time", "Indian/Comoro" }, - { "E. Africa Standard Time", "Indian/Mayotte" }, - { "E. Australia Standard Time", "Australia/Brisbane Australia/Lindeman" }, - { "E. Australia Standard Time", "Australia/Brisbane" }, - { "E. Europe Standard Time", "Asia/Nicosia" }, - { "E. South America Standard Time", "America/Sao_Paulo" }, - { "Eastern Standard Time", "America/Grand_Turk" }, - { "Eastern Standard Time", "America/Nassau" }, - { "Eastern Standard Time", "America/New_York America/Detroit " - "America/Indiana/Petersburg America/Indiana/Vincennes " - "America/Indiana/Winamac America/Kentucky/Monticello America/Louisville" }, - { "Eastern Standard Time", "America/New_York" }, - { "Eastern Standard Time", "America/Toronto America/Iqaluit America/Montreal " - "America/Nipigon America/Pangnirtung America/Thunder_Bay" }, - { "Eastern Standard Time", "EST5EDT" }, - { "Egypt Standard Time", "Africa/Cairo" }, - { "Egypt Standard Time", "Asia/Gaza Asia/Hebron" }, - { "Ekaterinburg Standard Time", "Asia/Yekaterinburg" }, - { "Fiji Standard Time", "Pacific/Fiji" }, - { "FLE Standard Time", "Europe/Helsinki" }, - { "FLE Standard Time", "Europe/Kiev Europe/Simferopol Europe/Uzhgorod Europe/Zaporozhye" }, - { "FLE Standard Time", "Europe/Kiev" }, - { "FLE Standard Time", "Europe/Mariehamn" }, - { "FLE Standard Time", "Europe/Riga" }, - { "FLE Standard Time", "Europe/Sofia" }, - { "FLE Standard Time", "Europe/Tallinn" }, - { "FLE Standard Time", "Europe/Vilnius" }, - { "Georgian Standard Time", "Asia/Tbilisi" }, - { "GMT Standard Time", "Atlantic/Canary" }, - { "GMT Standard Time", "Atlantic/Faeroe" }, - { "GMT Standard Time", "Europe/Dublin" }, - { "GMT Standard Time", "Europe/Guernsey" }, - { "GMT Standard Time", "Europe/Isle_of_Man" }, - { "GMT Standard Time", "Europe/Jersey" }, - { "GMT Standard Time", "Europe/Lisbon Atlantic/Madeira" }, - { "GMT Standard Time", "Europe/London" }, - { "Greenland Standard Time", "America/Godthab" }, - { "Greenwich Standard Time", "Africa/Abidjan" }, - { "Greenwich Standard Time", "Africa/Accra" }, - { "Greenwich Standard Time", "Africa/Bamako" }, - { "Greenwich Standard Time", "Africa/Banjul" }, - { "Greenwich Standard Time", "Africa/Bissau" }, - { "Greenwich Standard Time", "Africa/Conakry" }, - { "Greenwich Standard Time", "Africa/Dakar" }, - { "Greenwich Standard Time", "Africa/El_Aaiun" }, - { "Greenwich Standard Time", "Africa/Freetown" }, - { "Greenwich Standard Time", "Africa/Lome" }, - { "Greenwich Standard Time", "Africa/Monrovia" }, - { "Greenwich Standard Time", "Africa/Nouakchott" }, - { "Greenwich Standard Time", "Africa/Ouagadougou" }, - { "Greenwich Standard Time", "Africa/Sao_Tome" }, - { "Greenwich Standard Time", "Atlantic/Reykjavik" }, - { "Greenwich Standard Time", "Atlantic/St_Helena" }, - { "GTB Standard Time", "Europe/Athens" }, - { "GTB Standard Time", "Europe/Bucharest" }, - { "GTB Standard Time", "Europe/Chisinau" }, - { "GTB Standard Time", "Europe/Istanbul" }, - { "Hawaiian Standard Time", "Etc/GMT+10" }, - { "Hawaiian Standard Time", "Pacific/Fakaofo" }, - { "Hawaiian Standard Time", "Pacific/Honolulu" }, - { "Hawaiian Standard Time", "Pacific/Johnston" }, - { "Hawaiian Standard Time", "Pacific/Rarotonga" }, - { "Hawaiian Standard Time", "Pacific/Tahiti" }, - { "India Standard Time", "Asia/Calcutta Asia/Kolkata" }, - { "Iran Standard Time", "Asia/Tehran" }, - { "Israel Standard Time", "Asia/Jerusalem" }, - { "Jordan Standard Time", "Asia/Amman" }, - { "Kaliningrad Standard Time", "Europe/Kaliningrad" }, - { "Kaliningrad Standard Time", "Europe/Minsk" }, - { "Korea Standard Time", "Asia/Pyongyang" }, - { "Korea Standard Time", "Asia/Seoul" }, - { "Magadan Standard Time", "Asia/Magadan Asia/Anadyr Asia/Kamchatka" }, - { "Magadan Standard Time", "Asia/Magadan" }, - { "Mauritius Standard Time", "Indian/Mahe" }, - { "Mauritius Standard Time", "Indian/Mauritius" }, - { "Mauritius Standard Time", "Indian/Reunion" }, - { "Middle East Standard Time", "Asia/Beirut" }, - { "Montevideo Standard Time", "America/Montevideo" }, - { "Morocco Standard Time", "Africa/Casablanca" }, - { "Mountain Standard Time (Mexico)", "America/Chihuahua America/Mazatlan" }, - { "Mountain Standard Time (Mexico)", "America/Chihuahua" }, - { "Mountain Standard Time", "America/Denver America/Boise America/Shiprock" }, - { "Mountain Standard Time", "America/Denver" }, - { "Mountain Standard Time", "America/Edmonton " - "America/Cambridge_Bay America/Inuvik America/Yellowknife" }, - { "Mountain Standard Time", "America/Ojinaga" }, - { "Mountain Standard Time", "MST7MDT" }, - { "Myanmar Standard Time", "Asia/Rangoon" }, - { "Myanmar Standard Time", "Indian/Cocos" }, - { "N. Central Asia Standard Time", "Asia/Novosibirsk Asia/Novokuznetsk Asia/Omsk" }, - { "N. Central Asia Standard Time", "Asia/Novosibirsk" }, - { "Namibia Standard Time", "Africa/Windhoek" }, - { "Nepal Standard Time", "Asia/Katmandu Asia/Kathmandu" }, - { "New Zealand Standard Time", "Antarctica/South_Pole Antarctica/McMurdo" }, - { "New Zealand Standard Time", "Pacific/Auckland" }, - { "Newfoundland Standard Time", "America/St_Johns" }, - { "North Asia East Standard Time", "Asia/Irkutsk" }, - { "North Asia Standard Time", "Asia/Krasnoyarsk" }, - { "Pacific SA Standard Time", "America/Santiago" }, - { "Pacific SA Standard Time", "Antarctica/Palmer" }, - { "Pacific Standard Time (Mexico)", "America/Santa_Isabel" }, - { "Pacific Standard Time", "America/Los_Angeles" }, - { "Pacific Standard Time", "America/Tijuana America/Ensenada" }, - { "Pacific Standard Time", "America/Vancouver America/Dawson America/Whitehorse" }, - { "Pacific Standard Time", "PST8PDT" }, - { "Pakistan Standard Time", "Asia/Karachi" }, - { "Paraguay Standard Time", "America/Asuncion" }, - { "Romance Standard Time", "Europe/Brussels" }, - { "Romance Standard Time", "Europe/Copenhagen" }, - { "Romance Standard Time", "Europe/Madrid Africa/Ceuta" }, - { "Romance Standard Time", "Europe/Paris" }, - { "Russian Standard Time", "Europe/Moscow Europe/Samara Europe/Volgograd" }, - { "Russian Standard Time", "Europe/Moscow" }, - { "SA Eastern Standard Time", "America/Cayenne" }, - { "SA Eastern Standard Time", "America/Fortaleza America/Araguaina " - "America/Belem America/Maceio America/Recife America/Santarem" }, - { "SA Eastern Standard Time", "America/Paramaribo" }, - { "SA Eastern Standard Time", "Antarctica/Rothera" }, - { "SA Eastern Standard Time", "Etc/GMT+3" }, - { "SA Pacific Standard Time", "America/Bogota" }, - { "SA Pacific Standard Time", "America/Cayman" }, - { "SA Pacific Standard Time", "America/Coral_Harbour" }, - { "SA Pacific Standard Time", "America/Guayaquil" }, - { "SA Pacific Standard Time", "America/Jamaica" }, - { "SA Pacific Standard Time", "America/Lima" }, - { "SA Pacific Standard Time", "America/Panama" }, - { "SA Pacific Standard Time", "America/Port-au-Prince" }, - { "SA Pacific Standard Time", "Etc/GMT+5" }, - { "SA Western Standard Time", "America/Anguilla" }, - { "SA Western Standard Time", "America/Antigua" }, - { "SA Western Standard Time", "America/Aruba" }, - { "SA Western Standard Time", "America/Barbados" }, - { "SA Western Standard Time", "America/Blanc-Sablon" }, - { "SA Western Standard Time", "America/Curacao" }, - { "SA Western Standard Time", "America/Dominica" }, - { "SA Western Standard Time", "America/Grenada" }, - { "SA Western Standard Time", "America/Guadeloupe" }, - { "SA Western Standard Time", "America/Guyana" }, - { "SA Western Standard Time", "America/La_Paz" }, - { "SA Western Standard Time", "America/Manaus America/Boa_Vista " - "America/Eirunepe America/Porto_Velho America/Rio_Branco" }, - { "SA Western Standard Time", "America/Marigot" }, - { "SA Western Standard Time", "America/Martinique" }, - { "SA Western Standard Time", "America/Montserrat" }, - { "SA Western Standard Time", "America/Port_of_Spain" }, - { "SA Western Standard Time", "America/Puerto_Rico" }, - { "SA Western Standard Time", "America/Santo_Domingo" }, - { "SA Western Standard Time", "America/St_Barthelemy" }, - { "SA Western Standard Time", "America/St_Kitts" }, - { "SA Western Standard Time", "America/St_Lucia" }, - { "SA Western Standard Time", "America/St_Thomas" }, - { "SA Western Standard Time", "America/St_Vincent" }, - { "SA Western Standard Time", "America/Tortola" }, - { "SA Western Standard Time", "Etc/GMT+4" }, - { "Samoa Standard Time", "Pacific/Apia Pacific/Samoa" }, - { "SE Asia Standard Time", "Antarctica/Davis" }, - { "SE Asia Standard Time", "Asia/Bangkok" }, - { "SE Asia Standard Time", "Asia/Hovd" }, - { "SE Asia Standard Time", "Asia/Jakarta Asia/Pontianak" }, - { "SE Asia Standard Time", "Asia/Phnom_Penh" }, - { "SE Asia Standard Time", "Asia/Saigon Asia/Ho_Chi_Minh" }, - { "SE Asia Standard Time", "Asia/Vientiane" }, - { "SE Asia Standard Time", "Etc/GMT-7" }, - { "SE Asia Standard Time", "Indian/Christmas" }, - { "Singapore Standard Time", "Asia/Brunei" }, - { "Singapore Standard Time", "Asia/Kuala_Lumpur Asia/Kuching" }, - { "Singapore Standard Time", "Asia/Makassar" }, - { "Singapore Standard Time", "Asia/Manila" }, - { "Singapore Standard Time", "Asia/Singapore" }, - { "Singapore Standard Time", "Etc/GMT-8" }, - { "South Africa Standard Time", "Africa/Blantyre" }, - { "South Africa Standard Time", "Africa/Bujumbura" }, - { "South Africa Standard Time", "Africa/Gaborone" }, - { "South Africa Standard Time", "Africa/Harare" }, - { "South Africa Standard Time", "Africa/Johannesburg" }, - { "South Africa Standard Time", "Africa/Kigali" }, - { "South Africa Standard Time", "Africa/Lubumbashi" }, - { "South Africa Standard Time", "Africa/Lusaka" }, - { "South Africa Standard Time", "Africa/Maputo" }, - { "South Africa Standard Time", "Africa/Maseru" }, - { "South Africa Standard Time", "Africa/Mbabane" }, - { "South Africa Standard Time", "Africa/Tripoli" }, - { "South Africa Standard Time", "Etc/GMT-2" }, - { "Sri Lanka Standard Time", "Asia/Colombo" }, - { "Syria Standard Time", "Asia/Damascus" }, - { "Taipei Standard Time", "Asia/Taipei" }, - { "Tasmania Standard Time", "Australia/Hobart Australia/Currie" }, - { "Tasmania Standard Time", "Australia/Hobart" }, - { "Tokyo Standard Time", "Asia/Dili" }, - { "Tokyo Standard Time", "Asia/Jayapura" }, - { "Tokyo Standard Time", "Asia/Tokyo" }, - { "Tokyo Standard Time", "Etc/GMT-9" }, - { "Tokyo Standard Time", "Pacific/Palau" }, - { "Tonga Standard Time", "Etc/GMT-13" }, - { "Tonga Standard Time", "Pacific/Enderbury" }, - { "Tonga Standard Time", "Pacific/Tongatapu" }, - /* { "Turkey Standard Time", "Europe/Istanbul" }, */ - { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar Asia/Choibalsan" }, - { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar" }, - { "US Eastern Standard Time", "America/Indianapolis " - "America/Indiana/Marengo America/Indiana/Vevay" }, - { "US Eastern Standard Time", "America/Indianapolis" }, - { "US Mountain Standard Time", "America/Dawson_Creek" }, - { "US Mountain Standard Time", "America/Hermosillo" }, - { "US Mountain Standard Time", "America/Phoenix" }, - { "US Mountain Standard Time", "Etc/GMT+7" }, - { "UTC", "America/Danmarkshavn" }, - { "UTC", "Etc/GMT" }, - { "UTC+12", "Etc/GMT-12" }, - { "UTC+12", "Pacific/Funafuti" }, - { "UTC+12", "Pacific/Majuro Pacific/Kwajalein" }, - { "UTC+12", "Pacific/Nauru" }, - { "UTC+12", "Pacific/Tarawa" }, - { "UTC+12", "Pacific/Wake" }, - { "UTC+12", "Pacific/Wallis" }, - { "UTC-02", "America/Noronha" }, - { "UTC-02", "Atlantic/South_Georgia" }, - { "UTC-02", "Etc/GMT+2" }, - { "UTC-11", "Etc/GMT+11" }, - { "UTC-11", "Pacific/Midway" }, - { "UTC-11", "Pacific/Niue" }, - { "UTC-11", "Pacific/Pago_Pago" }, - { "Venezuela Standard Time", "America/Caracas" }, - { "Vladivostok Standard Time", "Asia/Vladivostok Asia/Sakhalin" }, - { "Vladivostok Standard Time", "Asia/Vladivostok" }, - { "W. Australia Standard Time", "Antarctica/Casey" }, - { "W. Australia Standard Time", "Australia/Perth" }, - { "W. Central Africa Standard Time", "Africa/Algiers" }, - { "W. Central Africa Standard Time", "Africa/Bangui" }, - { "W. Central Africa Standard Time", "Africa/Brazzaville" }, - { "W. Central Africa Standard Time", "Africa/Douala" }, - { "W. Central Africa Standard Time", "Africa/Kinshasa" }, - { "W. Central Africa Standard Time", "Africa/Lagos" }, - { "W. Central Africa Standard Time", "Africa/Libreville" }, - { "W. Central Africa Standard Time", "Africa/Luanda" }, - { "W. Central Africa Standard Time", "Africa/Malabo" }, - { "W. Central Africa Standard Time", "Africa/Ndjamena" }, - { "W. Central Africa Standard Time", "Africa/Niamey" }, - { "W. Central Africa Standard Time", "Africa/Porto-Novo" }, - { "W. Central Africa Standard Time", "Africa/Tunis" }, - { "W. Central Africa Standard Time", "Etc/GMT-1" }, - { "W. Europe Standard Time", "Arctic/Longyearbyen" }, - { "W. Europe Standard Time", "Europe/Amsterdam" }, - { "W. Europe Standard Time", "Europe/Andorra" }, - { "W. Europe Standard Time", "Europe/Berlin" }, - { "W. Europe Standard Time", "Europe/Gibraltar" }, - { "W. Europe Standard Time", "Europe/Luxembourg" }, - { "W. Europe Standard Time", "Europe/Malta" }, - { "W. Europe Standard Time", "Europe/Monaco" }, - { "W. Europe Standard Time", "Europe/Oslo" }, - { "W. Europe Standard Time", "Europe/Rome" }, - { "W. Europe Standard Time", "Europe/San_Marino" }, - { "W. Europe Standard Time", "Europe/Stockholm" }, - { "W. Europe Standard Time", "Europe/Vaduz" }, - { "W. Europe Standard Time", "Europe/Vatican" }, - { "W. Europe Standard Time", "Europe/Vienna" }, - { "W. Europe Standard Time", "Europe/Zurich" }, - { "West Asia Standard Time", "Antarctica/Mawson" }, - { "West Asia Standard Time", "Asia/Ashgabat" }, - { "West Asia Standard Time", "Asia/Dushanbe" }, - { "West Asia Standard Time", "Asia/Oral Asia/Aqtau Asia/Aqtobe" }, - { "West Asia Standard Time", "Asia/Tashkent Asia/Samarkand" }, - { "West Asia Standard Time", "Asia/Tashkent" }, - { "West Asia Standard Time", "Etc/GMT-5" }, - { "West Asia Standard Time", "Indian/Kerguelen" }, - { "West Asia Standard Time", "Indian/Maldives" }, - { "West Pacific Standard Time", "Antarctica/DumontDUrville" }, - { "West Pacific Standard Time", "Etc/GMT-10" }, - { "West Pacific Standard Time", "Pacific/Guam" }, - { "West Pacific Standard Time", "Pacific/Port_Moresby" }, - { "West Pacific Standard Time", "Pacific/Saipan" }, - { "West Pacific Standard Time", "Pacific/Truk" }, - { "Yakutsk Standard Time", "Asia/Yakutsk" } -}; - -static UINT64 freerdp_windows_gmtime() -{ - time_t unix_time; - UINT64 windows_time; - - time(&unix_time); - windows_time = unix_time; - windows_time *= 10000000; - windows_time += 621355968000000000ULL; - - return windows_time; -} - -char* freerdp_get_unix_timezone_identifier() -{ -#ifndef _WIN32 - FILE* fp; - ssize_t len; - char* tz_env; - size_t length; - char* tzid = NULL; - char buf[1024]; - - tz_env = getenv("TZ"); - - if (tz_env != NULL) - { - tzid = _strdup(tz_env); - return tzid; - } - -#if defined(__FreeBSD__) || defined(__OpenBSD__) - fp = fopen("/var/db/zoneinfo", "r"); -#else - fp = fopen("/etc/timezone", "r"); -#endif - if (fp != NULL) - { - fseek(fp, 0, SEEK_END); - length = ftell(fp); - fseek(fp, 0, SEEK_SET); - - if (length < 2) - { - fclose(fp) ; - return NULL; - } - - tzid = (char*) malloc(length + 1); - if (!tzid) - { - fclose(fp); - return NULL; - } - - if (fread(tzid, length, 1, fp) != 1) - { - free(tzid); - fclose(fp); - return NULL; - } - tzid[length] = '\0'; - - if (tzid[length - 1] == '\n') - tzid[length - 1] = '\0'; - - fclose(fp); - - return tzid; - } - - /* - * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime - * will point to /usr/share/zoneinfo/region/place where region/place could be - * America/Montreal for example. - * Some distributions do have to symlink at /etc/TZ. - */ - - if ((len = readlink("/etc/localtime", buf, sizeof(buf) - 1)) != -1 || - (len = readlink("/etc/TZ", buf, sizeof(buf) - 1)) != -1) - { - int num = 0; - int pos = len; - - buf[len] = '\0'; - - /* find the position of the 2nd to last "/" */ - - while (num < 2) - { - if (pos == 0) - break; - - pos -= 1; - - if (buf[pos] == '/') - num++; - } - - tzid = (char*) malloc(len - pos + 1); - if (!tzid) - return NULL; - - strncpy(tzid, buf + pos + 1, len - pos); - - return tzid; - } - - WLog_ERR(TAG, "Unable to detect time zone"); - return tzid; -#else - return 0; -#endif -} - -BOOL freerdp_match_unix_timezone_identifier_with_list(const char* tzid, const char* list) -{ - char* p; - char* list_copy; - - list_copy = _strdup(list); - if (!list_copy) - return FALSE; - - p = strtok(list_copy, " "); - - while (p != NULL) - { - if (strcmp(p, tzid) == 0) - { - free(list_copy); - return TRUE; - } - - p = strtok(NULL, " "); - } - - free(list_copy); - - return FALSE; -} - -TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) -{ - int i, j; - char* tzid; - TIME_ZONE_ENTRY* timezone; - - tzid = freerdp_get_unix_timezone_identifier(); - - if (tzid == NULL) - return NULL; - - for (i = 0; i < ARRAYSIZE(TimeZoneTable); i++) - { - for (j = 0; j < ARRAYSIZE(WindowsTimeZoneIdTable); j++) - { - if (strcmp(TimeZoneTable[i].Id, WindowsTimeZoneIdTable[j].windows) != 0) - continue; - - if (freerdp_match_unix_timezone_identifier_with_list(tzid, WindowsTimeZoneIdTable[j].tzid)) - { - free(tzid); - - timezone = (TIME_ZONE_ENTRY*) malloc(sizeof(TIME_ZONE_ENTRY)); - if (!timezone) - return NULL; - memcpy((void*) timezone, (void*) &TimeZoneTable[i], sizeof(TIME_ZONE_ENTRY)); - timezone->Bias = bias; - return timezone; - } - } - } - - WLog_ERR(TAG, "Unable to find a match for unix timezone: %s", tzid); - free(tzid); - return NULL; -} - -TIME_ZONE_RULE_ENTRY* freerdp_get_current_time_zone_rule(TIME_ZONE_RULE_ENTRY* rules, UINT32 count) -{ - int i; - UINT64 windows_time; - - windows_time = freerdp_windows_gmtime(); - - for (i = 0; i < (int) count; i++) - { - if ((rules[i].TicksStart >= windows_time) && (windows_time >= rules[i].TicksEnd)) - { - /*WLog_ERR(TAG, "Got rule %d from table at %p with count %u", i, rules, count);*/ - return &rules[i]; - } - } - - WLog_ERR(TAG, "Unable to get current timezone rule"); - return NULL; -} - -void freerdp_time_zone_detect(TIME_ZONE_INFO* clientTimeZone) -{ - time_t t; - TIME_ZONE_ENTRY* tz; - struct tm* local_time; - - clientTimeZone->standardBias = 0; - - time(&t); - local_time = localtime(&t); - -#ifdef HAVE_TM_GMTOFF - #if defined(__FreeBSD__) || defined(__OpenBSD__) - if (local_time->tm_gmtoff >= 0) - clientTimeZone->bias = (UINT32) (local_time->tm_gmtoff / 60); - else - clientTimeZone->bias = (UINT32) (1440 + (INT32) (local_time->tm_gmtoff / 60)); - #else - clientTimeZone->bias = timezone / 60; - #endif - DEBUG_TIMEZONE("tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", tzname[0], tzname[1], timezone, daylight); -#elif defined(sun) - if (local_time->tm_isdst > 0) - clientTimeZone->bias = (UINT32) (altzone / 3600); - else - clientTimeZone->bias = (UINT32) (timezone / 3600); -#else - clientTimeZone->bias = 0; -#endif - - tz = freerdp_detect_windows_time_zone(clientTimeZone->bias); - - if (tz!= NULL) - { - DEBUG_TIMEZONE("tz: Id='%s' Bias=%d DST=%d dn='%s' sn='%s' dln='%s'", - tz->Id, tz->Bias, tz->SupportsDST, tz->DisplayName, - tz->StandardName, tz->DaylightName); - - sprintf(clientTimeZone->standardName, "%s", tz->StandardName); - sprintf(clientTimeZone->daylightName, "%s", tz->DaylightName); - - if ((tz->SupportsDST) && (tz->RuleTableCount > 0)) - { - TIME_ZONE_RULE_ENTRY* rule; - rule = freerdp_get_current_time_zone_rule(tz->RuleTable, tz->RuleTableCount); - - if (rule != NULL) - { - clientTimeZone->daylightBias = -rule->DaylightDelta; - - clientTimeZone->standardDate.wYear = rule->StandardDate.wYear; - clientTimeZone->standardDate.wMonth = rule->StandardDate.wMonth; - clientTimeZone->standardDate.wDayOfWeek = rule->StandardDate.wDayOfWeek; - clientTimeZone->standardDate.wDay = rule->StandardDate.wDay; - clientTimeZone->standardDate.wHour = rule->StandardDate.wHour; - clientTimeZone->standardDate.wMinute = rule->StandardDate.wMinute; - clientTimeZone->standardDate.wSecond = rule->StandardDate.wSecond; - clientTimeZone->standardDate.wMilliseconds = rule->StandardDate.wMilliseconds; - - clientTimeZone->daylightDate.wYear = rule->DaylightDate.wYear; - clientTimeZone->daylightDate.wMonth = rule->DaylightDate.wMonth; - clientTimeZone->daylightDate.wDayOfWeek = rule->DaylightDate.wDayOfWeek; - clientTimeZone->daylightDate.wDay = rule->DaylightDate.wDay; - clientTimeZone->daylightDate.wHour = rule->DaylightDate.wHour; - clientTimeZone->daylightDate.wMinute = rule->DaylightDate.wMinute; - clientTimeZone->daylightDate.wSecond = rule->DaylightDate.wSecond; - clientTimeZone->daylightDate.wMilliseconds = rule->DaylightDate.wMilliseconds; - } - } - free(tz); - } - else - { - /* could not detect timezone, fallback to using GMT */ - DEBUG_TIMEZONE("tz not found, using GMT."); - sprintf(clientTimeZone->standardName, "%s", "GMT Standard Time"); - sprintf(clientTimeZone->daylightName, "%s", "GMT Daylight Time"); - } -} diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index d910eaa39..b7d9cf9c4 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -22,12 +22,1720 @@ #endif #include +#include +#include "../log.h" + +#define TAG WINPR_TAG("timezone") #ifndef _WIN32 +#include +#include + +struct _TIME_ZONE_RULE_ENTRY +{ + UINT64 TicksStart; + UINT64 TicksEnd; + INT32 DaylightDelta; + SYSTEMTIME StandardDate; + SYSTEMTIME DaylightDate; +}; +typedef struct _TIME_ZONE_RULE_ENTRY TIME_ZONE_RULE_ENTRY; + +struct _TIME_ZONE_ENTRY +{ + const char* Id; + UINT32 Bias; + BOOL SupportsDST; + const char* DisplayName; + const char* StandardName; + const char* DaylightName; + TIME_ZONE_RULE_ENTRY* RuleTable; + UINT32 RuleTableCount; +}; +typedef struct _TIME_ZONE_ENTRY TIME_ZONE_ENTRY; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_3[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_4[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_5[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_7[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_8[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_10[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_11[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_14[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_15[] = +{ + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_17[] = +{ + { 633662964000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 9, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_18[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_19[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_21[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 4, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 5, 6, 1, 23, 59 }, { 0, 8, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_22[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 1 }, { 0, 4, 0, 1, 0, 1 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 11, 0, 1, 0, 1 }, { 0, 3, 0, 1, 0, 1 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 0, 1 }, }, + { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 11, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_23[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 2, 0, 1, 2, 0 }, { 0, 11, 0, 1, 0, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 0, 1, 0, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 2, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_24[] = +{ + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 1, 1, 1, 0, 0 }, { 0, 12, 0, 1, 0, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 6, 1, 23, 59 }, { 0, 1, 4, 1, 0, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_26[] = +{ + { 633662964000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, }, + { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 0 }, { 0, 3, 6, 1, 22, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_27[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_28[] = +{ + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 1, 6, 1, 0, 0 }, { 0, 10, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638395956000000000ULL, 638081460000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 638712180000000000ULL, 638396820000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639027540000000000ULL, 638713044000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639342900000000000ULL, 639028404000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639658260000000000ULL, 639343764000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 639974484000000000ULL, 639659124000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640289844000000000ULL, 639975348000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640605204000000000ULL, 640290708000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 640920564000000000ULL, 640606068000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641236788000000000ULL, 640921428000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641552148000000000ULL, 641237652000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 641867508000000000ULL, 641553012000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642182868000000000ULL, 641868372000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642499092000000000ULL, 642183732000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 642814452000000000ULL, 642499956000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643129812000000000ULL, 642815316000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 643445172000000000ULL, 643130676000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 643446036000000000ULL, 60, { 0, 2, 6, 1, 23, 59 }, { 0, 10, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_30[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_31[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_33[] = +{ + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 0, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 5, 0, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 8, 6, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 7, 6, 1, 23, 59 }, { 0, 4, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_35[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 0, 1, 1, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_37[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_38[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_39[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_40[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_42[] = +{ + { 634293684000000000ULL, 180000000000ULL, -60, { 0, 9, 0, 1, 2, 0 }, { 0, 4, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 2, 0 }, { 0, 9, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_43[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 5, 1, 1, 0 }, { 0, 3, 4, 1, 0, 0 }, }, + { 3155378292000000000ULL, 633032244000000000ULL, 60, { 0, 10, 5, 1, 1, 0 }, { 0, 3, 4, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_44[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_45[] = +{ + { 633978324000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 0, 0 }, { 0, 3, 0, 1, 0, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 637450740000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_46[] = +{ + { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 5, 1, 0, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 8, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_47[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 9, 3, 1, 23, 59 }, { 0, 3, 5, 1, 23, 59 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 11, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 3155378292000000000ULL, 636188436000000000ULL, 60, { 0, 10, 4, 1, 23, 59 }, { 0, 4, 4, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_49[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_50[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 1, 1, 3, 0 }, }, + { 3155378292000000000ULL, 634609908000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 3, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_51[] = +{ + { 632716020000000000ULL, 632401524000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 635240628000000000ULL, 634926132000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 635555988000000000ULL, 635241492000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 635871348000000000ULL, 635556852000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 636187572000000000ULL, 635872212000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, }, + { 636502932000000000ULL, 636188436000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 636818292000000000ULL, 636503796000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 637133652000000000ULL, 636819156000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 637449876000000000ULL, 637134516000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 637765236000000000ULL, 637450740000000000ULL, 60, { 0, 9, 0, 1, 2, 0 }, { 0, 3, 5, 1, 2, 0 }, }, + { 638080596000000000ULL, 637766100000000000ULL, 60, { 0, 10, 0, 1, 2, 0 }, { 0, 4, 5, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_52[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_53[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 10, 1, 1, 4, 0 }, { 0, 4, 0, 1, 3, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_54[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_57[] = +{ + { 632716020000000000ULL, 180000000000ULL, 60, { 0, 9, 2, 1, 2, 0 }, { 0, 3, 0, 1, 2, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 9, 6, 1, 23, 59 }, { 0, 3, 4, 1, 23, 59 }, }, + { 3155378292000000000ULL, 633663828000000000ULL, 60, { 0, 9, 1, 1, 23, 59 }, { 0, 3, 6, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_59[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 5, 0 }, { 0, 3, 0, 1, 4, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_60[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_61[] = +{ + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 1, 2, 1, 0, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 2, 0 }, { 0, 1, 4, 1, 0, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_63[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_65[] = +{ + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 10, 5, 1, 23, 59 }, { 0, 5, 6, 1, 23, 59 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 10, 6, 1, 23, 59 }, { 0, 4, 2, 1, 23, 59 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_71[] = +{ + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 12, 4, 1, 23, 59 }, { 0, 6, 5, 1, 23, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_72[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_75[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_77[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_79[] = +{ + { 633031380000000000ULL, 632716884000000000ULL, 60, { 0, 1, 0, 1, 0, 0 }, { 0, 12, 0, 1, 2, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633662964000000000ULL, 633347604000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 1, 4, 1, 0, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_82[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_85[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_88[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_90[] = +{ + { 633346740000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_91[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_93[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_94[] = +{ + { 633031380000000000ULL, 180000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 633346740000000000ULL, 633032244000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 633347604000000000ULL, 60, { 0, 4, 0, 1, 3, 0 }, { 0, 9, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_96[] = +{ + { 633978324000000000ULL, 633663828000000000ULL, 60, { 0, 1, 4, 1, 0, 0 }, { 0, 11, 0, 1, 2, 0 }, }, + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 634609044000000000ULL, 634294548000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 634925268000000000ULL, 634609908000000000ULL, 60, { 0, 1, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, }, + { 3155378292000000000ULL, 634926132000000000ULL, 60, { 0, 3, 0, 1, 3, 0 }, { 0, 10, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_97[] = +{ + { 634293684000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_98[] = +{ + { 3155378292000000000ULL, 180000000000ULL, 60, { 0, 10, 0, 1, 3, 0 }, { 0, 3, 0, 1, 2, 0 }, } +}; + +static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_100[] = +{ + { 634293684000000000ULL, 633979188000000000ULL, 60, { 0, 1, 5, 1, 0, 0 }, { 0, 9, 6, 1, 23, 59 }, }, + { 3155378292000000000ULL, 634294548000000000ULL, 60, { 0, 4, 0, 1, 1, 0 }, { 0, 9, 0, 1, 0, 0 }, } +}; + +static const TIME_ZONE_ENTRY TimeZoneTable[] = +{ + { + "Dateline Standard Time", 720, FALSE, "(UTC-12:00) International Date Line West", + "Dateline Standard Time", "Dateline Daylight Time", + NULL, 0 + }, + { + "UTC-11", 780, FALSE, "(UTC-11:00) Coordinated Universal Time-11", + "UTC-11", "UTC-11", + NULL, 0 + }, + { + "Hawaiian Standard Time", 840, FALSE, "(UTC-10:00) Hawaii", + "Hawaiian Standard Time", "Hawaiian Daylight Time", + NULL, 0 + }, + { + "Alaskan Standard Time", 900, TRUE, "(UTC-09:00) Alaska", + "Alaskan Standard Time", "Alaskan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_3, 2 + }, + { + "Pacific Standard Time (Mexico)", 960, TRUE, "(UTC-08:00) Baja California", + "Pacific Standard Time (Mexico)", "Pacific Daylight Time (Mexico)", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_4, 1 + }, + { + "Pacific Standard Time", 960, TRUE, "(UTC-08:00) Pacific Time (US & Canada)", + "Pacific Standard Time", "Pacific Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_5, 2 + }, + { + "US Mountain Standard Time", 1020, FALSE, "(UTC-07:00) Arizona", + "US Mountain Standard Time", "US Mountain Daylight Time", + NULL, 0 + }, + { + "Mountain Standard Time (Mexico)", 1020, TRUE, "(UTC-07:00) Chihuahua, La Paz, Mazatlan", + "Mountain Standard Time (Mexico)", "Mountain Daylight Time (Mexico)", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_7, 1 + }, + { + "Mountain Standard Time", 1020, TRUE, "(UTC-07:00) Mountain Time (US & Canada)", + "Mountain Standard Time", "Mountain Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_8, 2 + }, + { + "Central America Standard Time", 1080, FALSE, "(UTC-06:00) Central America", + "Central America Standard Time", "Central America Daylight Time", + NULL, 0 + }, + { + "Central Standard Time", 1080, TRUE, "(UTC-06:00) Central Time (US & Canada)", + "Central Standard Time", "Central Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_10, 2 + }, + { + "Central Standard Time (Mexico)", 1080, TRUE, "(UTC-06:00) Guadalajara, Mexico City, Monterrey", + "Central Standard Time (Mexico)", "Central Daylight Time (Mexico)", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_11, 1 + }, + { + "Canada Central Standard Time", 1080, FALSE, "(UTC-06:00) Saskatchewan", + "Canada Central Standard Time", "Canada Central Daylight Time", + NULL, 0 + }, + { + "SA Pacific Standard Time", 1140, FALSE, "(UTC-05:00) Bogota, Lima, Quito", + "SA Pacific Standard Time", "SA Pacific Daylight Time", + NULL, 0 + }, + { + "Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Eastern Time (US & Canada)", + "Eastern Standard Time", "Eastern Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_14, 2 + }, + { + "US Eastern Standard Time", 1140, TRUE, "(UTC-05:00) Indiana (East)", + "US Eastern Standard Time", "US Eastern Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_15, 2 + }, + { + "Venezuela Standard Time", 1170, FALSE, "(UTC-04:30) Caracas", + "Venezuela Standard Time", "Venezuela Daylight Time", + NULL, 0 + }, + { + "Paraguay Standard Time", 1200, TRUE, "(UTC-04:00) Asuncion", + "Paraguay Standard Time", "Paraguay Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_17, 14 + }, + { + "Atlantic Standard Time", 1200, TRUE, "(UTC-04:00) Atlantic Time (Canada)", + "Atlantic Standard Time", "Atlantic Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_18, 2 + }, + { + "Central Brazilian Standard Time", 1200, TRUE, "(UTC-04:00) Cuiaba", + "Central Brazilian Standard Time", "Central Brazilian Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_19, 35 + }, + { + "SA Western Standard Time", 1200, FALSE, "(UTC-04:00) Georgetown, La Paz, Manaus, San Juan", + "SA Western Standard Time", "SA Western Daylight Time", + NULL, 0 + }, + { + "Pacific SA Standard Time", 1200, TRUE, "(UTC-04:00) Santiago", + "Pacific SA Standard Time", "Pacific SA Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_21, 6 + }, + { + "Newfoundland Standard Time", 1230, TRUE, "(UTC-03:30) Newfoundland", + "Newfoundland Standard Time", "Newfoundland Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_22, 7 + }, + { + "E. South America Standard Time", 1260, TRUE, "(UTC-03:00) Brasilia", + "E. South America Standard Time", "E. South America Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_23, 35 + }, + { + "Argentina Standard Time", 1260, TRUE, "(UTC-03:00) Buenos Aires", + "Argentina Standard Time", "Argentina Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_24, 3 + }, + { + "SA Eastern Standard Time", 1260, FALSE, "(UTC-03:00) Cayenne, Fortaleza", + "SA Eastern Standard Time", "SA Eastern Daylight Time", + NULL, 0 + }, + { + "Greenland Standard Time", 1260, TRUE, "(UTC-03:00) Greenland", + "Greenland Standard Time", "Greenland Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_26, 14 + }, + { + "Montevideo Standard Time", 1260, TRUE, "(UTC-03:00) Montevideo", + "Montevideo Standard Time", "Montevideo Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_27, 2 + }, + { + "Bahia Standard Time", 1260, TRUE, "(UTC-03:00) Salvador", + "Bahia Standard Time", "Bahia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_28, 30 + }, + { + "UTC-02", 1320, FALSE, "(UTC-02:00) Coordinated Universal Time-02", + "UTC-02", "UTC-02", + NULL, 0 + }, + { + "Mid-Atlantic Standard Time", 1320, TRUE, "(UTC-02:00) Mid-Atlantic", + "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_30, 1 + }, + { + "Azores Standard Time", 1380, TRUE, "(UTC-01:00) Azores", + "Azores Standard Time", "Azores Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_31, 1 + }, + { + "Cape Verde Standard Time", 1380, FALSE, "(UTC-01:00) Cape Verde Is.", + "Cape Verde Standard Time", "Cape Verde Daylight Time", + NULL, 0 + }, + { + "Morocco Standard Time", 0, TRUE, "(UTC) Casablanca", + "Morocco Standard Time", "Morocco Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_33, 4 + }, + { + "UTC", 0, FALSE, "(UTC) Coordinated Universal Time", + "Coordinated Universal Time", "Coordinated Universal Time", + NULL, 0 + }, + { + "GMT Standard Time", 0, TRUE, "(UTC) Dublin, Edinburgh, Lisbon, London", + "GMT Standard Time", "GMT Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_35, 1 + }, + { + "Greenwich Standard Time", 0, FALSE, "(UTC) Monrovia, Reykjavik", + "Greenwich Standard Time", "Greenwich Daylight Time", + NULL, 0 + }, + { + "W. Europe Standard Time", 60, TRUE, "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", + "W. Europe Standard Time", "W. Europe Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_37, 1 + }, + { + "Central Europe Standard Time", 60, TRUE, "(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", + "Central Europe Standard Time", "Central Europe Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_38, 1 + }, + { + "Romance Standard Time", 60, TRUE, "(UTC+01:00) Brussels, Copenhagen, Madrid, Paris", + "Romance Standard Time", "Romance Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_39, 1 + }, + { + "Central European Standard Time", 60, TRUE, "(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb", + "Central European Standard Time", "Central European Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_40, 1 + }, + { + "W. Central Africa Standard Time", 60, FALSE, "(UTC+01:00) West Central Africa", + "W. Central Africa Standard Time", "W. Central Africa Daylight Time", + NULL, 0 + }, + { + "Namibia Standard Time", 60, TRUE, "(UTC+01:00) Windhoek", + "Namibia Standard Time", "Namibia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_42, 2 + }, + { + "Jordan Standard Time", 120, TRUE, "(UTC+02:00) Amman", + "Jordan Standard Time", "Jordan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_43, 2 + }, + { + "GTB Standard Time", 120, TRUE, "(UTC+02:00) Athens, Bucharest, Istanbul", + "GTB Standard Time", "GTB Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_44, 1 + }, + { + "Middle East Standard Time", 120, TRUE, "(UTC+02:00) Beirut", + "Middle East Standard Time", "Middle East Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_45, 13 + }, + { + "Egypt Standard Time", 120, TRUE, "(UTC+02:00) Cairo", + "Egypt Standard Time", "Egypt Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_46, 6 + }, + { + "Syria Standard Time", 120, TRUE, "(UTC+02:00) Damascus", + "Syria Standard Time", "Syria Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_47, 12 + }, + { + "South Africa Standard Time", 120, FALSE, "(UTC+02:00) Harare, Pretoria", + "South Africa Standard Time", "South Africa Daylight Time", + NULL, 0 + }, + { + "FLE Standard Time", 120, TRUE, "(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", + "FLE Standard Time", "FLE Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_49, 1 + }, + { + "Turkey Standard Time", 120, TRUE, "(UTC+02:00) Istanbul", + "Turkey Standard Time", "Turkey Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_50, 3 + }, + { + "Israel Standard Time", 120, TRUE, "(UTC+02:00) Jerusalem", + "Jerusalem Standard Time", "Jerusalem Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_51, 18 + }, + { + "E. Europe Standard Time", 120, TRUE, "(UTC+02:00) Nicosia", + "E. Europe Standard Time", "E. Europe Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_52, 1 + }, + { + "Arabic Standard Time", 180, TRUE, "(UTC+03:00) Baghdad", + "Arabic Standard Time", "Arabic Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_53, 2 + }, + { + "Kaliningrad Standard Time", 180, TRUE, "(UTC+03:00) Kaliningrad, Minsk", + "Kaliningrad Standard Time", "Kaliningrad Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_54, 1 + }, + { + "Arab Standard Time", 180, FALSE, "(UTC+03:00) Kuwait, Riyadh", + "Arab Standard Time", "Arab Daylight Time", + NULL, 0 + }, + { + "E. Africa Standard Time", 180, FALSE, "(UTC+03:00) Nairobi", + "E. Africa Standard Time", "E. Africa Daylight Time", + NULL, 0 + }, + { + "Iran Standard Time", 210, TRUE, "(UTC+03:30) Tehran", + "Iran Standard Time", "Iran Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_57, 3 + }, + { + "Arabian Standard Time", 240, FALSE, "(UTC+04:00) Abu Dhabi, Muscat", + "Arabian Standard Time", "Arabian Daylight Time", + NULL, 0 + }, + { + "Azerbaijan Standard Time", 240, TRUE, "(UTC+04:00) Baku", + "Azerbaijan Standard Time", "Azerbaijan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_59, 1 + }, + { + "Russian Standard Time", 240, TRUE, "(UTC+04:00) Moscow, St. Petersburg, Volgograd", + "Russian Standard Time", "Russian Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_60, 1 + }, + { + "Mauritius Standard Time", 240, TRUE, "(UTC+04:00) Port Louis", + "Mauritius Standard Time", "Mauritius Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_61, 2 + }, + { + "Georgian Standard Time", 240, FALSE, "(UTC+04:00) Tbilisi", + "Georgian Standard Time", "Georgian Daylight Time", + NULL, 0 + }, + { + "Caucasus Standard Time", 240, TRUE, "(UTC+04:00) Yerevan", + "Caucasus Standard Time", "Caucasus Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_63, 1 + }, + { + "Afghanistan Standard Time", 270, FALSE, "(UTC+04:30) Kabul", + "Afghanistan Standard Time", "Afghanistan Daylight Time", + NULL, 0 + }, + { + "Pakistan Standard Time", 300, TRUE, "(UTC+05:00) Islamabad, Karachi", + "Pakistan Standard Time", "Pakistan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_65, 2 + }, + { + "West Asia Standard Time", 300, FALSE, "(UTC+05:00) Tashkent", + "West Asia Standard Time", "West Asia Daylight Time", + NULL, 0 + }, + { + "India Standard Time", 330, FALSE, "(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi", + "India Standard Time", "India Daylight Time", + NULL, 0 + }, + { + "Sri Lanka Standard Time", 330, FALSE, "(UTC+05:30) Sri Jayawardenepura", + "Sri Lanka Standard Time", "Sri Lanka Daylight Time", + NULL, 0 + }, + { + "Nepal Standard Time", 345, FALSE, "(UTC+05:45) Kathmandu", + "Nepal Standard Time", "Nepal Daylight Time", + NULL, 0 + }, + { + "Central Asia Standard Time", 360, FALSE, "(UTC+06:00) Astana", + "Central Asia Standard Time", "Central Asia Daylight Time", + NULL, 0 + }, + { + "Bangladesh Standard Time", 360, TRUE, "(UTC+06:00) Dhaka", + "Bangladesh Standard Time", "Bangladesh Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_71, 1 + }, + { + "Ekaterinburg Standard Time", 360, TRUE, "(UTC+06:00) Ekaterinburg", + "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_72, 1 + }, + { + "Myanmar Standard Time", 390, FALSE, "(UTC+06:30) Yangon (Rangoon)", + "Myanmar Standard Time", "Myanmar Daylight Time", + NULL, 0 + }, + { + "SE Asia Standard Time", 420, FALSE, "(UTC+07:00) Bangkok, Hanoi, Jakarta", + "SE Asia Standard Time", "SE Asia Daylight Time", + NULL, 0 + }, + { + "N. Central Asia Standard Time", 420, TRUE, "(UTC+07:00) Novosibirsk", + "N. Central Asia Standard Time", "N. Central Asia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_75, 1 + }, + { + "China Standard Time", 480, FALSE, "(UTC+08:00) Beijing, Chongqing, Hong Kong, Urumqi", + "China Standard Time", "China Daylight Time", + NULL, 0 + }, + { + "North Asia Standard Time", 480, TRUE, "(UTC+08:00) Krasnoyarsk", + "North Asia Standard Time", "North Asia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_77, 1 + }, + { + "Singapore Standard Time", 480, FALSE, "(UTC+08:00) Kuala Lumpur, Singapore", + "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time", + NULL, 0 + }, + { + "W. Australia Standard Time", 480, TRUE, "(UTC+08:00) Perth", + "W. Australia Standard Time", "W. Australia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_79, 4 + }, + { + "Taipei Standard Time", 480, FALSE, "(UTC+08:00) Taipei", + "Taipei Standard Time", "Taipei Daylight Time", + NULL, 0 + }, + { + "Ulaanbaatar Standard Time", 480, FALSE, "(UTC+08:00) Ulaanbaatar", + "Ulaanbaatar Standard Time", "Ulaanbaatar Daylight Time", + NULL, 0 + }, + { + "North Asia East Standard Time", 540, TRUE, "(UTC+09:00) Irkutsk", + "North Asia East Standard Time", "North Asia East Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_82, 1 + }, + { + "Tokyo Standard Time", 540, FALSE, "(UTC+09:00) Osaka, Sapporo, Tokyo", + "Tokyo Standard Time", "Tokyo Daylight Time", + NULL, 0 + }, + { + "Korea Standard Time", 540, FALSE, "(UTC+09:00) Seoul", + "Korea Standard Time", "Korea Daylight Time", + NULL, 0 + }, + { + "Cen. Australia Standard Time", 570, TRUE, "(UTC+09:30) Adelaide", + "Cen. Australia Standard Time", "Cen. Australia Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_85, 2 + }, + { + "AUS Central Standard Time", 570, FALSE, "(UTC+09:30) Darwin", + "AUS Central Standard Time", "AUS Central Daylight Time", + NULL, 0 + }, + { + "E. Australia Standard Time", 600, FALSE, "(UTC+10:00) Brisbane", + "E. Australia Standard Time", "E. Australia Daylight Time", + NULL, 0 + }, + { + "AUS Eastern Standard Time", 600, TRUE, "(UTC+10:00) Canberra, Melbourne, Sydney", + "AUS Eastern Standard Time", "AUS Eastern Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_88, 2 + }, + { + "West Pacific Standard Time", 600, FALSE, "(UTC+10:00) Guam, Port Moresby", + "West Pacific Standard Time", "West Pacific Daylight Time", + NULL, 0 + }, + { + "Tasmania Standard Time", 600, TRUE, "(UTC+10:00) Hobart", + "Tasmania Standard Time", "Tasmania Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_90, 2 + }, + { + "Yakutsk Standard Time", 600, TRUE, "(UTC+10:00) Yakutsk", + "Yakutsk Standard Time", "Yakutsk Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_91, 1 + }, + { + "Central Pacific Standard Time", 660, FALSE, "(UTC+11:00) Solomon Is., New Caledonia", + "Central Pacific Standard Time", "Central Pacific Daylight Time", + NULL, 0 + }, + { + "Vladivostok Standard Time", 660, TRUE, "(UTC+11:00) Vladivostok", + "Vladivostok Standard Time", "Vladivostok Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_93, 1 + }, + { + "New Zealand Standard Time", 720, TRUE, "(UTC+12:00) Auckland, Wellington", + "New Zealand Standard Time", "New Zealand Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_94, 3 + }, + { + "UTC+12", 720, FALSE, "(UTC+12:00) Coordinated Universal Time+12", + "UTC+12", "UTC+12", + NULL, 0 + }, + { + "Fiji Standard Time", 720, TRUE, "(UTC+12:00) Fiji", + "Fiji Standard Time", "Fiji Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_96, 5 + }, + { + "Magadan Standard Time", 720, TRUE, "(UTC+12:00) Magadan", + "Magadan Standard Time", "Magadan Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_97, 1 + }, + { + "Kamchatka Standard Time", 720, TRUE, "(UTC+12:00) Petropavlovsk-Kamchatsky - Old", + "Kamchatka Standard Time", "Kamchatka Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_98, 1 + }, + { + "Tonga Standard Time", 780, FALSE, "(UTC+13:00) Nuku'alofa", + "Tonga Standard Time", "Tonga Daylight Time", + NULL, 0 + }, + { + "Samoa Standard Time", 780, TRUE, "(UTC+13:00) Samoa", + "Samoa Standard Time", "Samoa Daylight Time", + (TIME_ZONE_RULE_ENTRY*) &TimeZoneRuleTable_100, 2 + } +}; + +/* Table generated with WindowsZones.cs */ + +struct _WINDOWS_TZID_ENTRY +{ + const char* windows; + const char* tzid; +}; +typedef struct _WINDOWS_TZID_ENTRY WINDOWS_TZID_ENTRY; + +const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] = +{ + { "Afghanistan Standard Time", "Asia/Kabul" }, + { "Alaskan Standard Time", "America/Anchorage America/Juneau " + "America/Nome America/Sitka America/Yakutat" }, + { "Alaskan Standard Time", "America/Anchorage" }, + { "Arab Standard Time", "Asia/Aden" }, + { "Arab Standard Time", "Asia/Bahrain" }, + { "Arab Standard Time", "Asia/Kuwait" }, + { "Arab Standard Time", "Asia/Qatar" }, + { "Arab Standard Time", "Asia/Riyadh" }, + { "Arabian Standard Time", "Asia/Dubai" }, + { "Arabian Standard Time", "Asia/Muscat" }, + { "Arabian Standard Time", "Etc/GMT-4" }, + { "Arabic Standard Time", "Asia/Baghdad" }, + { "Argentina Standard Time", "America/Buenos_Aires America/Argentina/La_Rioja " + "America/Argentina/Rio_Gallegos America/Argentina/Salta " + "America/Argentina/San_Juan America/Argentina/San_Luis " + "America/Argentina/Tucuman America/Argentina/Ushuaia America/Catamarca " + "America/Cordoba America/Jujuy America/Mendoza" }, + { "Argentina Standard Time", "America/Buenos_Aires" }, + { "Atlantic Standard Time", "America/Halifax America/Glace_Bay " + "America/Goose_Bay America/Moncton" }, + { "Atlantic Standard Time", "America/Halifax" }, + { "Atlantic Standard Time", "America/Thule" }, + { "Atlantic Standard Time", "Atlantic/Bermuda" }, + { "AUS Central Standard Time", "Australia/Darwin" }, + { "AUS Eastern Standard Time", "Australia/Sydney Australia/Melbourne" }, + { "AUS Eastern Standard Time", "Australia/Sydney" }, + { "Azerbaijan Standard Time", "Asia/Baku" }, + { "Azores Standard Time", "America/Scoresbysund" }, + { "Azores Standard Time", "Atlantic/Azores" }, + { "Bahia Standard Time", "America/Bahia" }, + { "Bangladesh Standard Time", "Asia/Dhaka" }, + { "Bangladesh Standard Time", "Asia/Thimphu" }, + { "Canada Central Standard Time", "America/Regina America/Swift_Current" }, + { "Canada Central Standard Time", "America/Regina" }, + { "Cape Verde Standard Time", "Atlantic/Cape_Verde" }, + { "Cape Verde Standard Time", "Etc/GMT+1" }, + { "Caucasus Standard Time", "Asia/Yerevan" }, + { "Cen. Australia Standard Time", "Australia/Adelaide Australia/Broken_Hill" }, + { "Cen. Australia Standard Time", "Australia/Adelaide" }, + { "Central America Standard Time", "America/Belize" }, + { "Central America Standard Time", "America/Costa_Rica" }, + { "Central America Standard Time", "America/El_Salvador" }, + { "Central America Standard Time", "America/Guatemala" }, + { "Central America Standard Time", "America/Managua" }, + { "Central America Standard Time", "America/Tegucigalpa" }, + { "Central America Standard Time", "Etc/GMT+6" }, + { "Central America Standard Time", "Pacific/Galapagos" }, + { "Central Asia Standard Time", "Antarctica/Vostok" }, + { "Central Asia Standard Time", "Asia/Almaty Asia/Qyzylorda" }, + { "Central Asia Standard Time", "Asia/Almaty" }, + { "Central Asia Standard Time", "Asia/Bishkek" }, + { "Central Asia Standard Time", "Etc/GMT-6" }, + { "Central Asia Standard Time", "Indian/Chagos" }, + { "Central Brazilian Standard Time", "America/Cuiaba America/Campo_Grande" }, + { "Central Brazilian Standard Time", "America/Cuiaba" }, + { "Central Europe Standard Time", "Europe/Belgrade" }, + { "Central Europe Standard Time", "Europe/Bratislava" }, + { "Central Europe Standard Time", "Europe/Budapest" }, + { "Central Europe Standard Time", "Europe/Ljubljana" }, + { "Central Europe Standard Time", "Europe/Podgorica" }, + { "Central Europe Standard Time", "Europe/Prague" }, + { "Central Europe Standard Time", "Europe/Tirane" }, + { "Central European Standard Time", "Europe/Sarajevo" }, + { "Central European Standard Time", "Europe/Skopje" }, + { "Central European Standard Time", "Europe/Warsaw" }, + { "Central European Standard Time", "Europe/Zagreb" }, + { "Central Pacific Standard Time", "Antarctica/Macquarie" }, + { "Central Pacific Standard Time", "Etc/GMT-11" }, + { "Central Pacific Standard Time", "Pacific/Efate" }, + { "Central Pacific Standard Time", "Pacific/Guadalcanal" }, + { "Central Pacific Standard Time", "Pacific/Noumea" }, + { "Central Pacific Standard Time", "Pacific/Ponape Pacific/Kosrae" }, + { "Central Standard Time (Mexico)", "America/Mexico_City America/Bahia_Banderas " + "America/Cancun America/Merida America/Monterrey" }, + { "Central Standard Time (Mexico)", "America/Mexico_City" }, + { "Central Standard Time", "America/Chicago America/Indiana/Knox " + "America/Indiana/Tell_City America/Menominee " + "America/North_Dakota/Beulah America/North_Dakota/Center " + "America/North_Dakota/New_Salem" }, + { "Central Standard Time", "America/Chicago" }, + { "Central Standard Time", "America/Matamoros" }, + { "Central Standard Time", "America/Winnipeg America/Rainy_River " + "America/Rankin_Inlet America/Resolute" }, + { "Central Standard Time", "CST6CDT" }, + { "China Standard Time", "Asia/Hong_Kong" }, + { "China Standard Time", "Asia/Macau" }, + { "China Standard Time", "Asia/Shanghai Asia/Chongqing Asia/Harbin Asia/Kashgar Asia/Urumqi" }, + { "China Standard Time", "Asia/Shanghai" }, + { "Dateline Standard Time", "Etc/GMT+12" }, + { "E. Africa Standard Time", "Africa/Addis_Ababa" }, + { "E. Africa Standard Time", "Africa/Asmera" }, + { "E. Africa Standard Time", "Africa/Dar_es_Salaam" }, + { "E. Africa Standard Time", "Africa/Djibouti" }, + { "E. Africa Standard Time", "Africa/Juba" }, + { "E. Africa Standard Time", "Africa/Kampala" }, + { "E. Africa Standard Time", "Africa/Khartoum" }, + { "E. Africa Standard Time", "Africa/Mogadishu" }, + { "E. Africa Standard Time", "Africa/Nairobi" }, + { "E. Africa Standard Time", "Antarctica/Syowa" }, + { "E. Africa Standard Time", "Etc/GMT-3" }, + { "E. Africa Standard Time", "Indian/Antananarivo" }, + { "E. Africa Standard Time", "Indian/Comoro" }, + { "E. Africa Standard Time", "Indian/Mayotte" }, + { "E. Australia Standard Time", "Australia/Brisbane Australia/Lindeman" }, + { "E. Australia Standard Time", "Australia/Brisbane" }, + { "E. Europe Standard Time", "Asia/Nicosia" }, + { "E. South America Standard Time", "America/Sao_Paulo" }, + { "Eastern Standard Time", "America/Grand_Turk" }, + { "Eastern Standard Time", "America/Nassau" }, + { "Eastern Standard Time", "America/New_York America/Detroit " + "America/Indiana/Petersburg America/Indiana/Vincennes " + "America/Indiana/Winamac America/Kentucky/Monticello America/Louisville" }, + { "Eastern Standard Time", "America/New_York" }, + { "Eastern Standard Time", "America/Toronto America/Iqaluit America/Montreal " + "America/Nipigon America/Pangnirtung America/Thunder_Bay" }, + { "Eastern Standard Time", "EST5EDT" }, + { "Egypt Standard Time", "Africa/Cairo" }, + { "Egypt Standard Time", "Asia/Gaza Asia/Hebron" }, + { "Ekaterinburg Standard Time", "Asia/Yekaterinburg" }, + { "Fiji Standard Time", "Pacific/Fiji" }, + { "FLE Standard Time", "Europe/Helsinki" }, + { "FLE Standard Time", "Europe/Kiev Europe/Simferopol Europe/Uzhgorod Europe/Zaporozhye" }, + { "FLE Standard Time", "Europe/Kiev" }, + { "FLE Standard Time", "Europe/Mariehamn" }, + { "FLE Standard Time", "Europe/Riga" }, + { "FLE Standard Time", "Europe/Sofia" }, + { "FLE Standard Time", "Europe/Tallinn" }, + { "FLE Standard Time", "Europe/Vilnius" }, + { "Georgian Standard Time", "Asia/Tbilisi" }, + { "GMT Standard Time", "Atlantic/Canary" }, + { "GMT Standard Time", "Atlantic/Faeroe" }, + { "GMT Standard Time", "Europe/Dublin" }, + { "GMT Standard Time", "Europe/Guernsey" }, + { "GMT Standard Time", "Europe/Isle_of_Man" }, + { "GMT Standard Time", "Europe/Jersey" }, + { "GMT Standard Time", "Europe/Lisbon Atlantic/Madeira" }, + { "GMT Standard Time", "Europe/London" }, + { "Greenland Standard Time", "America/Godthab" }, + { "Greenwich Standard Time", "Africa/Abidjan" }, + { "Greenwich Standard Time", "Africa/Accra" }, + { "Greenwich Standard Time", "Africa/Bamako" }, + { "Greenwich Standard Time", "Africa/Banjul" }, + { "Greenwich Standard Time", "Africa/Bissau" }, + { "Greenwich Standard Time", "Africa/Conakry" }, + { "Greenwich Standard Time", "Africa/Dakar" }, + { "Greenwich Standard Time", "Africa/El_Aaiun" }, + { "Greenwich Standard Time", "Africa/Freetown" }, + { "Greenwich Standard Time", "Africa/Lome" }, + { "Greenwich Standard Time", "Africa/Monrovia" }, + { "Greenwich Standard Time", "Africa/Nouakchott" }, + { "Greenwich Standard Time", "Africa/Ouagadougou" }, + { "Greenwich Standard Time", "Africa/Sao_Tome" }, + { "Greenwich Standard Time", "Atlantic/Reykjavik" }, + { "Greenwich Standard Time", "Atlantic/St_Helena" }, + { "GTB Standard Time", "Europe/Athens" }, + { "GTB Standard Time", "Europe/Bucharest" }, + { "GTB Standard Time", "Europe/Chisinau" }, + { "GTB Standard Time", "Europe/Istanbul" }, + { "Hawaiian Standard Time", "Etc/GMT+10" }, + { "Hawaiian Standard Time", "Pacific/Fakaofo" }, + { "Hawaiian Standard Time", "Pacific/Honolulu" }, + { "Hawaiian Standard Time", "Pacific/Johnston" }, + { "Hawaiian Standard Time", "Pacific/Rarotonga" }, + { "Hawaiian Standard Time", "Pacific/Tahiti" }, + { "India Standard Time", "Asia/Calcutta Asia/Kolkata" }, + { "Iran Standard Time", "Asia/Tehran" }, + { "Israel Standard Time", "Asia/Jerusalem" }, + { "Jordan Standard Time", "Asia/Amman" }, + { "Kaliningrad Standard Time", "Europe/Kaliningrad" }, + { "Kaliningrad Standard Time", "Europe/Minsk" }, + { "Korea Standard Time", "Asia/Pyongyang" }, + { "Korea Standard Time", "Asia/Seoul" }, + { "Magadan Standard Time", "Asia/Magadan Asia/Anadyr Asia/Kamchatka" }, + { "Magadan Standard Time", "Asia/Magadan" }, + { "Mauritius Standard Time", "Indian/Mahe" }, + { "Mauritius Standard Time", "Indian/Mauritius" }, + { "Mauritius Standard Time", "Indian/Reunion" }, + { "Middle East Standard Time", "Asia/Beirut" }, + { "Montevideo Standard Time", "America/Montevideo" }, + { "Morocco Standard Time", "Africa/Casablanca" }, + { "Mountain Standard Time (Mexico)", "America/Chihuahua America/Mazatlan" }, + { "Mountain Standard Time (Mexico)", "America/Chihuahua" }, + { "Mountain Standard Time", "America/Denver America/Boise America/Shiprock" }, + { "Mountain Standard Time", "America/Denver" }, + { "Mountain Standard Time", "America/Edmonton " + "America/Cambridge_Bay America/Inuvik America/Yellowknife" }, + { "Mountain Standard Time", "America/Ojinaga" }, + { "Mountain Standard Time", "MST7MDT" }, + { "Myanmar Standard Time", "Asia/Rangoon" }, + { "Myanmar Standard Time", "Indian/Cocos" }, + { "N. Central Asia Standard Time", "Asia/Novosibirsk Asia/Novokuznetsk Asia/Omsk" }, + { "N. Central Asia Standard Time", "Asia/Novosibirsk" }, + { "Namibia Standard Time", "Africa/Windhoek" }, + { "Nepal Standard Time", "Asia/Katmandu Asia/Kathmandu" }, + { "New Zealand Standard Time", "Antarctica/South_Pole Antarctica/McMurdo" }, + { "New Zealand Standard Time", "Pacific/Auckland" }, + { "Newfoundland Standard Time", "America/St_Johns" }, + { "North Asia East Standard Time", "Asia/Irkutsk" }, + { "North Asia Standard Time", "Asia/Krasnoyarsk" }, + { "Pacific SA Standard Time", "America/Santiago" }, + { "Pacific SA Standard Time", "Antarctica/Palmer" }, + { "Pacific Standard Time (Mexico)", "America/Santa_Isabel" }, + { "Pacific Standard Time", "America/Los_Angeles" }, + { "Pacific Standard Time", "America/Tijuana America/Ensenada" }, + { "Pacific Standard Time", "America/Vancouver America/Dawson America/Whitehorse" }, + { "Pacific Standard Time", "PST8PDT" }, + { "Pakistan Standard Time", "Asia/Karachi" }, + { "Paraguay Standard Time", "America/Asuncion" }, + { "Romance Standard Time", "Europe/Brussels" }, + { "Romance Standard Time", "Europe/Copenhagen" }, + { "Romance Standard Time", "Europe/Madrid Africa/Ceuta" }, + { "Romance Standard Time", "Europe/Paris" }, + { "Russian Standard Time", "Europe/Moscow Europe/Samara Europe/Volgograd" }, + { "Russian Standard Time", "Europe/Moscow" }, + { "SA Eastern Standard Time", "America/Cayenne" }, + { "SA Eastern Standard Time", "America/Fortaleza America/Araguaina " + "America/Belem America/Maceio America/Recife America/Santarem" }, + { "SA Eastern Standard Time", "America/Paramaribo" }, + { "SA Eastern Standard Time", "Antarctica/Rothera" }, + { "SA Eastern Standard Time", "Etc/GMT+3" }, + { "SA Pacific Standard Time", "America/Bogota" }, + { "SA Pacific Standard Time", "America/Cayman" }, + { "SA Pacific Standard Time", "America/Coral_Harbour" }, + { "SA Pacific Standard Time", "America/Guayaquil" }, + { "SA Pacific Standard Time", "America/Jamaica" }, + { "SA Pacific Standard Time", "America/Lima" }, + { "SA Pacific Standard Time", "America/Panama" }, + { "SA Pacific Standard Time", "America/Port-au-Prince" }, + { "SA Pacific Standard Time", "Etc/GMT+5" }, + { "SA Western Standard Time", "America/Anguilla" }, + { "SA Western Standard Time", "America/Antigua" }, + { "SA Western Standard Time", "America/Aruba" }, + { "SA Western Standard Time", "America/Barbados" }, + { "SA Western Standard Time", "America/Blanc-Sablon" }, + { "SA Western Standard Time", "America/Curacao" }, + { "SA Western Standard Time", "America/Dominica" }, + { "SA Western Standard Time", "America/Grenada" }, + { "SA Western Standard Time", "America/Guadeloupe" }, + { "SA Western Standard Time", "America/Guyana" }, + { "SA Western Standard Time", "America/La_Paz" }, + { "SA Western Standard Time", "America/Manaus America/Boa_Vista " + "America/Eirunepe America/Porto_Velho America/Rio_Branco" }, + { "SA Western Standard Time", "America/Marigot" }, + { "SA Western Standard Time", "America/Martinique" }, + { "SA Western Standard Time", "America/Montserrat" }, + { "SA Western Standard Time", "America/Port_of_Spain" }, + { "SA Western Standard Time", "America/Puerto_Rico" }, + { "SA Western Standard Time", "America/Santo_Domingo" }, + { "SA Western Standard Time", "America/St_Barthelemy" }, + { "SA Western Standard Time", "America/St_Kitts" }, + { "SA Western Standard Time", "America/St_Lucia" }, + { "SA Western Standard Time", "America/St_Thomas" }, + { "SA Western Standard Time", "America/St_Vincent" }, + { "SA Western Standard Time", "America/Tortola" }, + { "SA Western Standard Time", "Etc/GMT+4" }, + { "Samoa Standard Time", "Pacific/Apia Pacific/Samoa" }, + { "SE Asia Standard Time", "Antarctica/Davis" }, + { "SE Asia Standard Time", "Asia/Bangkok" }, + { "SE Asia Standard Time", "Asia/Hovd" }, + { "SE Asia Standard Time", "Asia/Jakarta Asia/Pontianak" }, + { "SE Asia Standard Time", "Asia/Phnom_Penh" }, + { "SE Asia Standard Time", "Asia/Saigon Asia/Ho_Chi_Minh" }, + { "SE Asia Standard Time", "Asia/Vientiane" }, + { "SE Asia Standard Time", "Etc/GMT-7" }, + { "SE Asia Standard Time", "Indian/Christmas" }, + { "Singapore Standard Time", "Asia/Brunei" }, + { "Singapore Standard Time", "Asia/Kuala_Lumpur Asia/Kuching" }, + { "Singapore Standard Time", "Asia/Makassar" }, + { "Singapore Standard Time", "Asia/Manila" }, + { "Singapore Standard Time", "Asia/Singapore" }, + { "Singapore Standard Time", "Etc/GMT-8" }, + { "South Africa Standard Time", "Africa/Blantyre" }, + { "South Africa Standard Time", "Africa/Bujumbura" }, + { "South Africa Standard Time", "Africa/Gaborone" }, + { "South Africa Standard Time", "Africa/Harare" }, + { "South Africa Standard Time", "Africa/Johannesburg" }, + { "South Africa Standard Time", "Africa/Kigali" }, + { "South Africa Standard Time", "Africa/Lubumbashi" }, + { "South Africa Standard Time", "Africa/Lusaka" }, + { "South Africa Standard Time", "Africa/Maputo" }, + { "South Africa Standard Time", "Africa/Maseru" }, + { "South Africa Standard Time", "Africa/Mbabane" }, + { "South Africa Standard Time", "Africa/Tripoli" }, + { "South Africa Standard Time", "Etc/GMT-2" }, + { "Sri Lanka Standard Time", "Asia/Colombo" }, + { "Syria Standard Time", "Asia/Damascus" }, + { "Taipei Standard Time", "Asia/Taipei" }, + { "Tasmania Standard Time", "Australia/Hobart Australia/Currie" }, + { "Tasmania Standard Time", "Australia/Hobart" }, + { "Tokyo Standard Time", "Asia/Dili" }, + { "Tokyo Standard Time", "Asia/Jayapura" }, + { "Tokyo Standard Time", "Asia/Tokyo" }, + { "Tokyo Standard Time", "Etc/GMT-9" }, + { "Tokyo Standard Time", "Pacific/Palau" }, + { "Tonga Standard Time", "Etc/GMT-13" }, + { "Tonga Standard Time", "Pacific/Enderbury" }, + { "Tonga Standard Time", "Pacific/Tongatapu" }, + /* { "Turkey Standard Time", "Europe/Istanbul" }, */ + { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar Asia/Choibalsan" }, + { "Ulaanbaatar Standard Time", "Asia/Ulaanbaatar" }, + { "US Eastern Standard Time", "America/Indianapolis " + "America/Indiana/Marengo America/Indiana/Vevay" }, + { "US Eastern Standard Time", "America/Indianapolis" }, + { "US Mountain Standard Time", "America/Dawson_Creek" }, + { "US Mountain Standard Time", "America/Hermosillo" }, + { "US Mountain Standard Time", "America/Phoenix" }, + { "US Mountain Standard Time", "Etc/GMT+7" }, + { "UTC", "America/Danmarkshavn" }, + { "UTC", "Etc/GMT" }, + { "UTC+12", "Etc/GMT-12" }, + { "UTC+12", "Pacific/Funafuti" }, + { "UTC+12", "Pacific/Majuro Pacific/Kwajalein" }, + { "UTC+12", "Pacific/Nauru" }, + { "UTC+12", "Pacific/Tarawa" }, + { "UTC+12", "Pacific/Wake" }, + { "UTC+12", "Pacific/Wallis" }, + { "UTC-02", "America/Noronha" }, + { "UTC-02", "Atlantic/South_Georgia" }, + { "UTC-02", "Etc/GMT+2" }, + { "UTC-11", "Etc/GMT+11" }, + { "UTC-11", "Pacific/Midway" }, + { "UTC-11", "Pacific/Niue" }, + { "UTC-11", "Pacific/Pago_Pago" }, + { "Venezuela Standard Time", "America/Caracas" }, + { "Vladivostok Standard Time", "Asia/Vladivostok Asia/Sakhalin" }, + { "Vladivostok Standard Time", "Asia/Vladivostok" }, + { "W. Australia Standard Time", "Antarctica/Casey" }, + { "W. Australia Standard Time", "Australia/Perth" }, + { "W. Central Africa Standard Time", "Africa/Algiers" }, + { "W. Central Africa Standard Time", "Africa/Bangui" }, + { "W. Central Africa Standard Time", "Africa/Brazzaville" }, + { "W. Central Africa Standard Time", "Africa/Douala" }, + { "W. Central Africa Standard Time", "Africa/Kinshasa" }, + { "W. Central Africa Standard Time", "Africa/Lagos" }, + { "W. Central Africa Standard Time", "Africa/Libreville" }, + { "W. Central Africa Standard Time", "Africa/Luanda" }, + { "W. Central Africa Standard Time", "Africa/Malabo" }, + { "W. Central Africa Standard Time", "Africa/Ndjamena" }, + { "W. Central Africa Standard Time", "Africa/Niamey" }, + { "W. Central Africa Standard Time", "Africa/Porto-Novo" }, + { "W. Central Africa Standard Time", "Africa/Tunis" }, + { "W. Central Africa Standard Time", "Etc/GMT-1" }, + { "W. Europe Standard Time", "Arctic/Longyearbyen" }, + { "W. Europe Standard Time", "Europe/Amsterdam" }, + { "W. Europe Standard Time", "Europe/Andorra" }, + { "W. Europe Standard Time", "Europe/Berlin" }, + { "W. Europe Standard Time", "Europe/Gibraltar" }, + { "W. Europe Standard Time", "Europe/Luxembourg" }, + { "W. Europe Standard Time", "Europe/Malta" }, + { "W. Europe Standard Time", "Europe/Monaco" }, + { "W. Europe Standard Time", "Europe/Oslo" }, + { "W. Europe Standard Time", "Europe/Rome" }, + { "W. Europe Standard Time", "Europe/San_Marino" }, + { "W. Europe Standard Time", "Europe/Stockholm" }, + { "W. Europe Standard Time", "Europe/Vaduz" }, + { "W. Europe Standard Time", "Europe/Vatican" }, + { "W. Europe Standard Time", "Europe/Vienna" }, + { "W. Europe Standard Time", "Europe/Zurich" }, + { "West Asia Standard Time", "Antarctica/Mawson" }, + { "West Asia Standard Time", "Asia/Ashgabat" }, + { "West Asia Standard Time", "Asia/Dushanbe" }, + { "West Asia Standard Time", "Asia/Oral Asia/Aqtau Asia/Aqtobe" }, + { "West Asia Standard Time", "Asia/Tashkent Asia/Samarkand" }, + { "West Asia Standard Time", "Asia/Tashkent" }, + { "West Asia Standard Time", "Etc/GMT-5" }, + { "West Asia Standard Time", "Indian/Kerguelen" }, + { "West Asia Standard Time", "Indian/Maldives" }, + { "West Pacific Standard Time", "Antarctica/DumontDUrville" }, + { "West Pacific Standard Time", "Etc/GMT-10" }, + { "West Pacific Standard Time", "Pacific/Guam" }, + { "West Pacific Standard Time", "Pacific/Port_Moresby" }, + { "West Pacific Standard Time", "Pacific/Saipan" }, + { "West Pacific Standard Time", "Pacific/Truk" }, + { "Yakutsk Standard Time", "Asia/Yakutsk" } +}; + +static UINT64 freerdp_windows_gmtime() +{ + time_t unix_time; + UINT64 windows_time; + + time(&unix_time); + windows_time = unix_time; + windows_time *= 10000000; + windows_time += 621355968000000000ULL; + + return windows_time; +} + +static char* freerdp_get_unix_timezone_identifier() +{ + FILE* fp; + ssize_t len; + char* tz_env; + size_t length; + char* tzid = NULL; + char buf[1024]; + + tz_env = getenv("TZ"); + + if (tz_env != NULL) + { + tzid = _strdup(tz_env); + return tzid; + } + +#if defined(__FreeBSD__) || defined(__OpenBSD__) + fp = fopen("/var/db/zoneinfo", "r"); +#else + fp = fopen("/etc/timezone", "r"); +#endif + if (fp != NULL) + { + fseek(fp, 0, SEEK_END); + length = ftell(fp); + fseek(fp, 0, SEEK_SET); + + if (length < 2) + { + fclose(fp) ; + return NULL; + } + + tzid = (char*) malloc(length + 1); + if (!tzid) + { + fclose(fp); + return NULL; + } + + if (fread(tzid, length, 1, fp) != 1) + { + free(tzid); + fclose(fp); + return NULL; + } + tzid[length] = '\0'; + + if (tzid[length - 1] == '\n') + tzid[length - 1] = '\0'; + + fclose(fp); + + return tzid; + } + + /* + * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime + * will point to /usr/share/zoneinfo/region/place where region/place could be + * America/Montreal for example. + */ + + if ((len = readlink("/etc/localtime", buf, sizeof(buf) - 1)) != -1) + { + int num = 0; + int pos = len; + + buf[len] = '\0'; + + /* find the position of the 2nd to last "/" */ + + while (num < 2) + { + if (pos == 0) + break; + + pos -= 1; + + if (buf[pos] == '/') + num++; + } + + tzid = (char*) malloc(len - pos + 1); + if (!tzid) + return NULL; + + strncpy(tzid, buf + pos + 1, len - pos); + + return tzid; + } + + WLog_ERR(TAG, "Unable to detect time zone"); + return tzid; +} + +static BOOL freerdp_match_unix_timezone_identifier_with_list(const char* tzid, const char* list) +{ + char* p; + char* list_copy; + + list_copy = _strdup(list); + if (!list_copy) + return FALSE; + + p = strtok(list_copy, " "); + + while (p != NULL) + { + if (strcmp(p, tzid) == 0) + { + free(list_copy); + return TRUE; + } + + p = strtok(NULL, " "); + } + + free(list_copy); + + return FALSE; +} + +static TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) +{ + int i, j; + char* tzid; + TIME_ZONE_ENTRY* timezone; + + tzid = freerdp_get_unix_timezone_identifier(); + + if (tzid == NULL) + return NULL; + + for (i = 0; i < ARRAYSIZE(TimeZoneTable); i++) + { + for (j = 0; j < ARRAYSIZE(WindowsTimeZoneIdTable); j++) + { + if (strcmp(TimeZoneTable[i].Id, WindowsTimeZoneIdTable[j].windows) != 0) + continue; + + if (freerdp_match_unix_timezone_identifier_with_list(tzid, WindowsTimeZoneIdTable[j].tzid)) + { + free(tzid); + + timezone = (TIME_ZONE_ENTRY*) malloc(sizeof(TIME_ZONE_ENTRY)); + if (!timezone) + return NULL; + memcpy((void*) timezone, (void*) &TimeZoneTable[i], sizeof(TIME_ZONE_ENTRY)); + timezone->Bias = bias; + return timezone; + } + } + } + + WLog_ERR(TAG, "Unable to find a match for unix timezone: %s", tzid); + free(tzid); + return NULL; +} + +static TIME_ZONE_RULE_ENTRY* freerdp_get_current_time_zone_rule(TIME_ZONE_RULE_ENTRY* rules, UINT32 count) +{ + int i; + UINT64 windows_time; + + windows_time = freerdp_windows_gmtime(); + + for (i = 0; i < (int) count; i++) + { + if ((rules[i].TicksStart >= windows_time) && (windows_time >= rules[i].TicksEnd)) + { + /*WLog_ERR(TAG, "Got rule %d from table at %p with count %u", i, rules, count);*/ + return &rules[i]; + } + } + + WLog_ERR(TAG, "Unable to get current timezone rule"); + return NULL; +} + DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { - return 0; + time_t t; + struct tm* local_time; + TIME_ZONE_ENTRY* dtz; + LPTIME_ZONE_INFORMATION tz = lpTimeZoneInformation; + + lpTimeZoneInformation->StandardBias = 0; + + time(&t); + local_time = localtime(&t); + + memset(tz, 0, sizeof(TIME_ZONE_INFORMATION)); + +#ifdef HAVE_TM_GMTOFF + #if defined(__FreeBSD__) || defined(__OpenBSD__) + if (local_time->tm_gmtoff >= 0) + tz->Bias = (UINT32) (local_time->tm_gmtoff / 60); + else + tz->Bias = (UINT32) (1440 + (INT32) (local_time->tm_gmtoff / 60)); + #else + tz->Bias = (UINT32) (local_time->tm_gmtoff / 60); + #endif +#else + tz->Bias = 0; +#endif + WLog_DBG(TAG, "tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", + tzname[0], tzname[1], timezone, daylight); + + dtz = freerdp_detect_windows_time_zone(tz->Bias); + + if (dtz!= NULL) + { + WLog_DBG(TAG, "tz: Bias=%d sn='%s' dln='%s'", + dtz->Bias, dtz->StandardName, dtz->DaylightName); + + tz->Bias = dtz->Bias; + tz->StandardBias = dtz->Bias; + tz->DaylightBias = dtz->Bias; + + ConvertToUnicode(CP_UTF8, 0, dtz->StandardName, sizeof(dtz->StandardName), + &tz->StandardName, sizeof(tz->StandardName)/sizeof(WCHAR)); + ConvertToUnicode(CP_UTF8, 0, dtz->DaylightName, sizeof(dtz->DaylightName), + &tz->DaylightName, sizeof(tz->DaylightName)/sizeof(WCHAR)); + + if ((dtz->SupportsDST) && (dtz->RuleTableCount > 0)) + { + TIME_ZONE_RULE_ENTRY* rule; + rule = freerdp_get_current_time_zone_rule(dtz->RuleTable, dtz->RuleTableCount); + + if (rule != NULL) + { + tz->DaylightBias = -rule->DaylightDelta; + + tz->StandardDate = rule->StandardDate; + tz->DaylightDate = rule->DaylightDate; + } + } + free(dtz); + + /* 1 ... TIME_ZONE_ID_STANDARD + * 2 ... TIME_ZONE_ID_DAYLIGHT */ + return dtz->SupportsDST ? 2 : 1; + } + else + { + /* could not detect timezone, fallback to using GMT */ + WLog_DBG(TAG, "tz not found, using GMT."); + memcpy(tz->StandardName, L"GMT Standard Time", sizeof(tz->StandardName)); + memcpy(tz->DaylightName, L"GMT Daylight Time", sizeof(tz->DaylightName)); + return 0; /* TIME_ZONE_ID_UNKNOWN */ + } } BOOL SetTimeZoneInformation(const TIME_ZONE_INFORMATION* lpTimeZoneInformation) From 1cd6697bca541cb1decd7a0393d905a212a67781 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 23 Feb 2016 18:15:25 +0100 Subject: [PATCH 051/128] Implemented timezone detection for android Refactored version of patch from pxx02134 --- winpr/libwinpr/timezone/timezone.c | 126 ++++++++++------------------- 1 file changed, 44 insertions(+), 82 deletions(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index b7d9cf9c4..bce7d2adf 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -1484,102 +1484,64 @@ static UINT64 freerdp_windows_gmtime() return windows_time; } -static char* freerdp_get_unix_timezone_identifier() +static char* freerdp_read_unix_timezone_identifier_from_file(FILE* fp) { - FILE* fp; - ssize_t len; - char* tz_env; - size_t length; + long length; char* tzid = NULL; - char buf[1024]; - tz_env = getenv("TZ"); + if (fseek(fp, 0, SEEK_END) != 0) + return NULL; + length = ftell(fp); + if (fseek(fp, 0, SEEK_SET) != 0) + return NULL; - if (tz_env != NULL) + if (length < 2) + return NULL; + + tzid = (char*) malloc(length + 1); + if (!tzid) + return NULL; + + if (fread(tzid, length, 1, fp) != 1) { - tzid = _strdup(tz_env); - return tzid; + free(tzid); + return NULL; } -#if defined(__FreeBSD__) || defined(__OpenBSD__) + tzid[length] = '\0'; + if (tzid[length - 1] == '\n') + tzid[length - 1] = '\0'; + + return tzid; +} + +static char* freerdp_get_unix_timezone_identifier_from_file(void) +{ + FILE* fp; + char* tzid = NULL; + +#if defined(ANDROID) + fp = popen("getprop persist.sys.timezone", "r"); +#elif defined(__FreeBSD__) || defined(__OpenBSD__) fp = fopen("/var/db/zoneinfo", "r"); #else fp = fopen("/etc/timezone", "r"); #endif - if (fp != NULL) - { - fseek(fp, 0, SEEK_END); - length = ftell(fp); - fseek(fp, 0, SEEK_SET); - if (length < 2) - { - fclose(fp) ; - return NULL; - } + if (NULL == fp ) + return NULL; - tzid = (char*) malloc(length + 1); - if (!tzid) - { - fclose(fp); - return NULL; - } + tzid = freerdp_read_unix_timezone_identifier_from_file(fp); - if (fread(tzid, length, 1, fp) != 1) - { - free(tzid); - fclose(fp); - return NULL; - } - tzid[length] = '\0'; - - if (tzid[length - 1] == '\n') - tzid[length - 1] = '\0'; - - fclose(fp); - - return tzid; - } - - /* - * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime - * will point to /usr/share/zoneinfo/region/place where region/place could be - * America/Montreal for example. - */ - - if ((len = readlink("/etc/localtime", buf, sizeof(buf) - 1)) != -1) - { - int num = 0; - int pos = len; - - buf[len] = '\0'; - - /* find the position of the 2nd to last "/" */ - - while (num < 2) - { - if (pos == 0) - break; - - pos -= 1; - - if (buf[pos] == '/') - num++; - } - - tzid = (char*) malloc(len - pos + 1); - if (!tzid) - return NULL; - - strncpy(tzid, buf + pos + 1, len - pos); - - return tzid; - } - - WLog_ERR(TAG, "Unable to detect time zone"); +#if defined(ANDROID) + pclose(fp) ; +#else + fclose(fp) ; +#endif return tzid; } + static BOOL freerdp_match_unix_timezone_identifier_with_list(const char* tzid, const char* list) { char* p; @@ -1613,7 +1575,7 @@ static TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) char* tzid; TIME_ZONE_ENTRY* timezone; - tzid = freerdp_get_unix_timezone_identifier(); + tzid = freerdp_get_unix_timezone_identifier_from_file(); if (tzid == NULL) return NULL; @@ -1705,9 +1667,9 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) tz->DaylightBias = dtz->Bias; ConvertToUnicode(CP_UTF8, 0, dtz->StandardName, sizeof(dtz->StandardName), - &tz->StandardName, sizeof(tz->StandardName)/sizeof(WCHAR)); + (WCHAR**)&tz->StandardName, sizeof(tz->StandardName)/sizeof(WCHAR)); ConvertToUnicode(CP_UTF8, 0, dtz->DaylightName, sizeof(dtz->DaylightName), - &tz->DaylightName, sizeof(tz->DaylightName)/sizeof(WCHAR)); + (WCHAR**)&tz->DaylightName, sizeof(tz->DaylightName)/sizeof(WCHAR)); if ((dtz->SupportsDST) && (dtz->RuleTableCount > 0)) { From 495df6d6ec47b2dead89870c16d2642f2d0e082d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 09:42:12 +0100 Subject: [PATCH 052/128] Readded read timezone from link. --- winpr/libwinpr/timezone/timezone.c | 61 +++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index bce7d2adf..534b92ac6 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -1515,6 +1515,62 @@ static char* freerdp_read_unix_timezone_identifier_from_file(FILE* fp) return tzid; } +static char* freerdp_get_timezone_from_link(void) +{ + const char* links[] = + { + "/etc/localtime", + "/etc/TZ" + }; + size_t x; + ssize_t len; + char buf[1024]; + char* tzid = NULL; + + /* + * On linux distros such as Redhat or Archlinux, a symlink at /etc/localtime + * will point to /usr/share/zoneinfo/region/place where region/place could be + * America/Montreal for example. + * Some distributions do have to symlink at /etc/TZ. + */ + + for (x=0; xBias = 0; #endif WLog_DBG(TAG, "tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", - tzname[0], tzname[1], timezone, daylight); + tzname[0], tzname[1], timezone, daylight); dtz = freerdp_detect_windows_time_zone(tz->Bias); From 7795ebdc155f585bbc3b048e8b20ae00185ab648 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 09:43:53 +0100 Subject: [PATCH 053/128] Fixed return value for DST. --- winpr/libwinpr/timezone/timezone.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 534b92ac6..4a1f3e8c5 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -1747,7 +1747,7 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) /* 1 ... TIME_ZONE_ID_STANDARD * 2 ... TIME_ZONE_ID_DAYLIGHT */ - return dtz->SupportsDST ? 2 : 1; + return local_time->tm_isdst ? 2 : 1; } else { From 0e4ea3943a7dafc018a568a1282551fd2d62a130 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 16:36:15 +0100 Subject: [PATCH 054/128] Unified sha1 functions. --- include/freerdp/crypto/crypto.h | 13 --- libfreerdp/core/security.c | 152 ++++++++++++-------------------- libfreerdp/crypto/crypto.c | 20 ----- winpr/include/winpr/crypto.h | 2 + 4 files changed, 59 insertions(+), 128 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 25d98bde3..ce0ec3138 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -44,11 +43,6 @@ #include #include -struct crypto_sha1_struct -{ - SHA_CTX sha_ctx; -}; - struct crypto_md5_struct { MD5_CTX md5_ctx; @@ -79,13 +73,6 @@ struct crypto_cert_struct extern "C" { #endif -#define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH -typedef struct crypto_sha1_struct* CryptoSha1; - -FREERDP_API CryptoSha1 crypto_sha1_init(void); -FREERDP_API void crypto_sha1_update(CryptoSha1 sha1, const BYTE* data, UINT32 length); -FREERDP_API void crypto_sha1_final(CryptoSha1 sha1, BYTE* out_data); - #define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH typedef struct crypto_md5_struct* CryptoMd5; diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 44c7190f9..b03eca5ba 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -25,6 +25,7 @@ #include "security.h" #include +#include #define TAG FREERDP_TAG("core") @@ -127,23 +128,18 @@ static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length const BYTE* salt1, const BYTE* salt2, BYTE* output) { CryptoMd5 md5; - CryptoSha1 sha1; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + WINPR_SHA1_CTX sha1; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */ /* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, input, length); /* Input */ - crypto_sha1_update(sha1, salt, 48); /* Salt (48 bytes) */ - crypto_sha1_update(sha1, salt1, 32); /* Salt1 (32 bytes) */ - crypto_sha1_update(sha1, salt2, 32); /* Salt2 (32 bytes) */ - crypto_sha1_final(sha1, sha1_digest); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, input, length); /* Input */ + winpr_SHA1_Update(&sha1, salt, 48); /* Salt (48 bytes) */ + winpr_SHA1_Update(&sha1, salt1, 32); /* Salt1 (32 bytes) */ + winpr_SHA1_Update(&sha1, salt2, 32); /* Salt2 (32 bytes) */ + winpr_SHA1_Final(&sha1, sha1_digest); /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ md5 = crypto_md5_init(); @@ -233,26 +229,21 @@ BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length BYTE* output) { CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_SHA1_CTX sha1; BYTE length_le[4]; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; /* MacData = MD5(MacSaltKey + pad2 + SHA1(MacSaltKey + pad1 + length + data)) */ security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, mac_salt_key, 16); /* MacSaltKey */ - crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ - crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ - crypto_sha1_update(sha1, data, length); /* data */ - crypto_sha1_final(sha1, sha1_digest); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, mac_salt_key, 16); /* MacSaltKey */ + winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); /* pad1 */ + winpr_SHA1_Update(&sha1, length_le, sizeof(length_le)); /* length */ + winpr_SHA1_Update(&sha1, data, length); /* data */ + winpr_SHA1_Final(&sha1, sha1_digest); /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ md5 = crypto_md5_init(); @@ -271,25 +262,20 @@ BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* output) { CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_SHA1_CTX sha1; BYTE length_le[4]; BYTE md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ - crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ - crypto_sha1_update(sha1, data, length); /* data */ - crypto_sha1_final(sha1, sha1_digest); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); /* pad1 */ + winpr_SHA1_Update(&sha1, length_le, sizeof(length_le)); /* length */ + winpr_SHA1_Update(&sha1, data, length); /* data */ + winpr_SHA1_Final(&sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ md5 = crypto_md5_init(); @@ -311,11 +297,11 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BOOL encryption, BYTE* output) { CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_SHA1_CTX sha1; BYTE length_le[4]; BYTE use_count_le[4]; BYTE md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; - BYTE sha1_digest[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; security_UINT32_le(length_le, length); /* length must be little-endian */ @@ -333,18 +319,13 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, } /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_sha1_update(sha1, pad1, sizeof(pad1)); /* pad1 */ - crypto_sha1_update(sha1, length_le, sizeof(length_le)); /* length */ - crypto_sha1_update(sha1, data, length); /* data */ - crypto_sha1_update(sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ - crypto_sha1_final(sha1, sha1_digest); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); /* pad1 */ + winpr_SHA1_Update(&sha1, length_le, sizeof(length_le)); /* length */ + winpr_SHA1_Update(&sha1, data, length); /* data */ + winpr_SHA1_Update(&sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ + winpr_SHA1_Final(&sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ md5 = crypto_md5_init(); @@ -428,40 +409,26 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - CryptoSha1 sha1; - BYTE client_encrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; - BYTE client_decrypt_key_t[CRYPTO_SHA1_DIGEST_LENGTH + 1]; - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, client_random + 16, 16); - crypto_sha1_update(sha1, server_random + 16, 16); - crypto_sha1_final(sha1, client_encrypt_key_t); + WINPR_SHA1_CTX sha1; + BYTE client_encrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1]; + BYTE client_decrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1]; + + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, client_random + 16, 16); + winpr_SHA1_Update(&sha1, server_random + 16, 16); + winpr_SHA1_Final(&sha1, client_encrypt_key_t); client_encrypt_key_t[20] = client_encrypt_key_t[0]; - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, client_random, 16); - crypto_sha1_update(sha1, server_random, 16); - crypto_sha1_final(sha1, client_decrypt_key_t); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, client_random, 16); + winpr_SHA1_Update(&sha1, server_random, 16); + winpr_SHA1_Final(&sha1, client_decrypt_key_t); client_decrypt_key_t[20] = client_decrypt_key_t[0]; - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, client_decrypt_key_t, 20); - crypto_sha1_update(sha1, client_encrypt_key_t, 20); - crypto_sha1_final(sha1, rdp->fips_sign_key); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, client_decrypt_key_t, 20); + winpr_SHA1_Update(&sha1, client_encrypt_key_t, 20); + winpr_SHA1_Final(&sha1, rdp->fips_sign_key); if (rdp->settings->ServerMode) { @@ -532,22 +499,17 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) { - BYTE sha1h[CRYPTO_SHA1_DIGEST_LENGTH]; + BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH]; CryptoMd5 md5; - CryptoSha1 sha1; + WINPR_SHA1_CTX sha1; CryptoRc4 rc4; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ - sha1 = crypto_sha1_init(); - if (!sha1) - { - WLog_ERR(TAG, "unable to allocate a sha1"); - return FALSE; - } - crypto_sha1_update(sha1, update_key, key_len); - crypto_sha1_update(sha1, pad1, sizeof(pad1)); - crypto_sha1_update(sha1, key, key_len); - crypto_sha1_final(sha1, sha1h); + winpr_SHA1_Init(&sha1); + winpr_SHA1_Update(&sha1, update_key, key_len); + winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); + winpr_SHA1_Update(&sha1, key, key_len); + winpr_SHA1_Final(&sha1, sha1h); md5 = crypto_md5_init(); if (!md5) diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index d014ec20c..c6dd0b153 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -28,26 +28,6 @@ #define TAG FREERDP_TAG("crypto") -CryptoSha1 crypto_sha1_init(void) -{ - CryptoSha1 sha1 = malloc(sizeof(*sha1)); - if (!sha1) - return NULL; - SHA1_Init(&sha1->sha_ctx); - return sha1; -} - -void crypto_sha1_update(CryptoSha1 sha1, const BYTE* data, UINT32 length) -{ - SHA1_Update(&sha1->sha_ctx, data, length); -} - -void crypto_sha1_final(CryptoSha1 sha1, BYTE* out_data) -{ - SHA1_Final(out_data, &sha1->sha_ctx); - free(sha1); -} - CryptoMd5 crypto_md5_init(void) { CryptoMd5 md5 = malloc(sizeof(*md5)); diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 7754700dd..2a2d91812 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -700,6 +700,8 @@ WINPR_API void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); * SHA1 Hashing */ +#define WINPR_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH + struct _OPENSSL_SHA1_CTX { UINT32 h0, h1, h2, h3, h4; From 06da644007a86d75805efd7590d795ddc7be763f Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 16:46:25 +0100 Subject: [PATCH 055/128] Unified md5 functions. --- include/freerdp/crypto/crypto.h | 13 ---- libfreerdp/core/certificate.c | 15 ++--- libfreerdp/core/gcc.c | 15 ++--- libfreerdp/core/license.c | 15 ++--- libfreerdp/core/security.c | 104 ++++++++++++-------------------- libfreerdp/crypto/crypto.c | 20 ------ winpr/include/winpr/crypto.h | 4 +- 7 files changed, 56 insertions(+), 130 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index ce0ec3138..5bc04254c 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -43,11 +42,6 @@ #include #include -struct crypto_md5_struct -{ - MD5_CTX md5_ctx; -}; - struct crypto_rc4_struct { RC4_KEY rc4_key; @@ -73,13 +67,6 @@ struct crypto_cert_struct extern "C" { #endif -#define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH -typedef struct crypto_md5_struct* CryptoMd5; - -FREERDP_API CryptoMd5 crypto_md5_init(void); -FREERDP_API void crypto_md5_update(CryptoMd5 md5, const BYTE* data, UINT32 length); -FREERDP_API void crypto_md5_final(CryptoMd5 md5, BYTE* out_data); - typedef struct crypto_rc4_struct* CryptoRc4; FREERDP_API CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length); diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c index a793af831..e5999b836 100644 --- a/libfreerdp/core/certificate.c +++ b/libfreerdp/core/certificate.c @@ -29,6 +29,7 @@ #include #include +#include #include #include @@ -398,18 +399,14 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific const BYTE* sigdata, int sigdatalen, wStream* s, UINT32 siglen) { int i, sum; - CryptoMd5 md5ctx; + WINPR_MD5_CTX md5ctx; BYTE sig[TSSK_KEY_LENGTH]; BYTE encsig[TSSK_KEY_LENGTH + 8]; - BYTE md5hash[CRYPTO_MD5_DIGEST_LENGTH]; + BYTE md5hash[WINPR_MD5_DIGEST_LENGTH]; - md5ctx = crypto_md5_init(); - - if (!md5ctx) - return FALSE; - - crypto_md5_update(md5ctx, sigdata, sigdatalen); - crypto_md5_final(md5ctx, md5hash); + winpr_MD5_Init(&md5ctx); + winpr_MD5_Update(&md5ctx, sigdata, sigdatalen); + winpr_MD5_Final(&md5ctx, md5hash); Stream_Read(s, encsig, siglen); /* Last 8 bytes shall be all zero. */ diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index c2354423e..5914b64cd 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -24,6 +24,7 @@ #endif #include +#include #include @@ -1178,7 +1179,7 @@ const BYTE tssk_exponent[] = BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; BYTE* sigData; int expLen, keyLen, sigDataLen; BYTE encryptedSignature[TSSK_KEY_LENGTH]; @@ -1375,15 +1376,9 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) memcpy(signature, initial_signature, sizeof(initial_signature)); - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - - crypto_md5_update(md5, sigData, sigDataLen); - crypto_md5_final(md5, signature); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, sigData, sigDataLen); + winpr_MD5_Final(&md5, signature); crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 23de184bb..c1b3d763b 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -23,6 +23,7 @@ #endif #include +#include #include #include "redirection.h" @@ -384,22 +385,16 @@ BOOL license_generate_keys(rdpLicense* license) BOOL license_generate_hwid(rdpLicense* license) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; BYTE macAddress[6]; ZeroMemory(macAddress, sizeof(macAddress)); ZeroMemory(license->HardwareId, HWID_LENGTH); - md5 = crypto_md5_init(); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, macAddress, sizeof(macAddress)); + winpr_MD5_Final(&md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH]); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - - crypto_md5_update(md5, macAddress, sizeof(macAddress)); - crypto_md5_final(md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH]); return TRUE; } diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index b03eca5ba..acabcaa89 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -127,7 +127,7 @@ fips_oddparity_table[256] = static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length, const BYTE* salt1, const BYTE* salt2, BYTE* output) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; @@ -142,15 +142,10 @@ static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length winpr_SHA1_Final(&sha1, sha1_digest); /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - crypto_md5_update(md5, salt, 48); /* Salt (48 bytes) */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, output); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, salt, 48); /* Salt (48 bytes) */ + winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + winpr_MD5_Final(&md5, output); return TRUE; } @@ -195,18 +190,13 @@ void security_mac_salt_key(const BYTE* session_key_blob, const BYTE* client_rand BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BYTE* output) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - crypto_md5_update(md5, in0, 16); - crypto_md5_update(md5, in1, 32); - crypto_md5_update(md5, in2, 32); - crypto_md5_final(md5, output); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, in0, 16); + winpr_MD5_Update(&md5, in1, 32); + winpr_MD5_Update(&md5, in2, 32); + winpr_MD5_Final(&md5, output); return TRUE; } @@ -228,7 +218,7 @@ void security_UINT32_le(BYTE* output, UINT32 value) BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length, BYTE* output) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; BYTE length_le[4]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; @@ -246,25 +236,20 @@ BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length winpr_SHA1_Final(&sha1, sha1_digest); /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - crypto_md5_update(md5, mac_salt_key, 16); /* MacSaltKey */ - crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, output); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, mac_salt_key, 16); /* MacSaltKey */ + winpr_MD5_Update(&md5, pad2, sizeof(pad2)); /* pad2 */ + winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + winpr_MD5_Final(&md5, output); return TRUE; } BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* output) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; BYTE length_le[4]; - BYTE md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; + BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; security_UINT32_le(length_le, length); /* length must be little-endian */ @@ -278,16 +263,11 @@ BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* winpr_SHA1_Final(&sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, md5_digest); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + winpr_MD5_Update(&md5, pad2, sizeof(pad2)); /* pad2 */ + winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + winpr_MD5_Final(&md5, md5_digest); memcpy(output, md5_digest, 8); return TRUE; @@ -296,11 +276,11 @@ BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BOOL encryption, BYTE* output) { - CryptoMd5 md5; + WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; BYTE length_le[4]; BYTE use_count_le[4]; - BYTE md5_digest[CRYPTO_MD5_DIGEST_LENGTH]; + BYTE md5_digest[WINPR_MD5_DIGEST_LENGTH]; BYTE sha1_digest[WINPR_SHA1_DIGEST_LENGTH]; security_UINT32_le(length_le, length); /* length must be little-endian */ @@ -328,16 +308,11 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, winpr_SHA1_Final(&sha1, sha1_digest); /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - crypto_md5_update(md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - crypto_md5_update(md5, pad2, sizeof(pad2)); /* pad2 */ - crypto_md5_update(md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - crypto_md5_final(md5, md5_digest); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ + winpr_MD5_Update(&md5, pad2, sizeof(pad2)); /* pad2 */ + winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ + winpr_MD5_Final(&md5, md5_digest); memcpy(output, md5_digest, 8); return TRUE; @@ -500,7 +475,7 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) { BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH]; - CryptoMd5 md5; + WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; CryptoRc4 rc4; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ @@ -511,16 +486,11 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) winpr_SHA1_Update(&sha1, key, key_len); winpr_SHA1_Final(&sha1, sha1h); - md5 = crypto_md5_init(); - if (!md5) - { - WLog_ERR(TAG, "unable to allocate a md5"); - return FALSE; - } - crypto_md5_update(md5, update_key, key_len); - crypto_md5_update(md5, pad2, sizeof(pad2)); - crypto_md5_update(md5, sha1h, sizeof(sha1h)); - crypto_md5_final(md5, key); + winpr_MD5_Init(&md5); + winpr_MD5_Update(&md5, update_key, key_len); + winpr_MD5_Update(&md5, pad2, sizeof(pad2)); + winpr_MD5_Update(&md5, sha1h, sizeof(sha1h)); + winpr_MD5_Final(&md5, key); rc4 = crypto_rc4_init(key, key_len); if (!rc4) diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index c6dd0b153..62e819935 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -28,26 +28,6 @@ #define TAG FREERDP_TAG("crypto") -CryptoMd5 crypto_md5_init(void) -{ - CryptoMd5 md5 = malloc(sizeof(*md5)); - if (!md5) - return NULL; - MD5_Init(&md5->md5_ctx); - return md5; -} - -void crypto_md5_update(CryptoMd5 md5, const BYTE* data, UINT32 length) -{ - MD5_Update(&md5->md5_ctx, data, length); -} - -void crypto_md5_final(CryptoMd5 md5, BYTE* out_data) -{ - MD5_Final(out_data, &md5->md5_ctx); - free(md5); -} - CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length) { CryptoRc4 rc4 = malloc(sizeof(*rc4)); diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 2a2d91812..2cf013f87 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -642,6 +642,8 @@ union _WINPR_MD5_CTX }; typedef union _WINPR_MD5_CTX WINPR_MD5_CTX; +#define WINPR_MD5_DIGEST_LENGTH 16 + #ifdef __cplusplus extern "C" { #endif @@ -700,7 +702,7 @@ WINPR_API void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); * SHA1 Hashing */ -#define WINPR_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH +#define WINPR_SHA1_DIGEST_LENGTH 20 struct _OPENSSL_SHA1_CTX { From ada2b16c50fe27a5a912ec12fdae72d9a292664c Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 17:04:03 +0100 Subject: [PATCH 056/128] Unified RC4 functions. --- include/freerdp/crypto/crypto.h | 12 ----------- libfreerdp/core/connection.c | 29 +++++--------------------- libfreerdp/core/license.c | 30 +++++++++------------------ libfreerdp/core/nla.h | 3 ++- libfreerdp/core/rdp.c | 8 ++++---- libfreerdp/core/rdp.h | 5 +++-- libfreerdp/core/security.c | 36 ++++++++++----------------------- libfreerdp/crypto/crypto.c | 19 ----------------- 8 files changed, 34 insertions(+), 108 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 5bc04254c..ae74e1d90 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -25,7 +25,6 @@ #include #include -#include #include #include #include @@ -42,11 +41,6 @@ #include #include -struct crypto_rc4_struct -{ - RC4_KEY rc4_key; -}; - struct crypto_des3_struct { EVP_CIPHER_CTX des3_ctx; @@ -67,12 +61,6 @@ struct crypto_cert_struct extern "C" { #endif -typedef struct crypto_rc4_struct* CryptoRc4; - -FREERDP_API CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length); -FREERDP_API void crypto_rc4(CryptoRc4 rc4, UINT32 length, const BYTE* in_data, BYTE* out_data); -FREERDP_API void crypto_rc4_free(CryptoRc4 rc4); - typedef struct crypto_des3_struct* CryptoDes3; FREERDP_API CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec); diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 286643e10..91e498f17 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -31,6 +31,7 @@ #include "transport.h" #include +#include #include #include @@ -512,19 +513,9 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) goto end; } - rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_decrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); - goto end; - } + winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); + winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); - rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_encrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); - goto end; - } ret = TRUE; end: free(crypt_client_random); @@ -630,19 +621,9 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) goto end; } - rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_decrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); - goto end; - } + winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); + winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); - rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_encrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); - goto end; - } ret = TRUE; end: free(crypt_client_random); diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index c1b3d763b..2dba07c40 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -455,27 +455,19 @@ BOOL license_encrypt_premaster_secret(rdpLicense* license) BOOL license_decrypt_platform_challenge(rdpLicense* license) { - CryptoRc4 rc4; + WINPR_RC4_CTX rc4; license->PlatformChallenge->data = (BYTE *)malloc(license->EncryptedPlatformChallenge->length); if (!license->PlatformChallenge->data) return FALSE; license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length; - rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); - if (!rc4) - { - WLog_ERR(TAG, "unable to allocate a rc4"); - free(license->PlatformChallenge->data); - license->PlatformChallenge->data = NULL; - return FALSE; - } - - crypto_rc4(rc4, license->EncryptedPlatformChallenge->length, + winpr_RC4_Init(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); + winpr_RC4_Update(&rc4, license->EncryptedPlatformChallenge->length, license->EncryptedPlatformChallenge->data, license->PlatformChallenge->data); - crypto_rc4_free(rc4); + winpr_RC4_Final(&rc4); return TRUE; } @@ -1020,7 +1012,7 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) wStream* s; int length; BYTE* buffer; - CryptoRc4 rc4; + WINPR_RC4_CTX rc4; BYTE mac_data[16]; BOOL status; @@ -1041,19 +1033,15 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) if (!status) return FALSE; - rc4 = crypto_rc4_init(license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); - if (!rc4) - { - WLog_ERR(TAG, "unable to allocate a rc4"); - return FALSE; - } + winpr_RC4_Init(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); buffer = (BYTE*) malloc(HWID_LENGTH); if (!buffer) return FALSE; - crypto_rc4(rc4, HWID_LENGTH, license->HardwareId, buffer); - crypto_rc4_free(rc4); + winpr_RC4_Update(&rc4, HWID_LENGTH, license->HardwareId, buffer); + winpr_RC4_Final(&rc4); + license->EncryptedHardwareId->type = BB_DATA_BLOB; license->EncryptedHardwareId->data = buffer; license->EncryptedHardwareId->length = HWID_LENGTH; diff --git a/libfreerdp/core/nla.h b/libfreerdp/core/nla.h index 774bcc985..b1afeba85 100644 --- a/libfreerdp/core/nla.h +++ b/libfreerdp/core/nla.h @@ -27,6 +27,7 @@ typedef struct rdp_nla rdpNla; #include #include +#include #include #include @@ -75,7 +76,7 @@ struct rdp_nla SecBuffer authInfo; SecBuffer PublicKey; SecBuffer tsCredentials; - CryptoRc4 rc4SealState; + WINPR_RC4_CTX rc4SealState; LPTSTR ServicePrincipalName; SEC_WINNT_AUTH_IDENTITY* identity; PSecurityFunctionTable table; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index c3488f4f5..abb6cd0ed 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1590,13 +1590,13 @@ void rdp_reset(rdpRdp* rdp) if (rdp->rc4_decrypt_key) { - crypto_rc4_free(rdp->rc4_decrypt_key); + winpr_RC4_Final(rdp->rc4_decrypt_key); rdp->rc4_decrypt_key = NULL; } if (rdp->rc4_encrypt_key) { - crypto_rc4_free(rdp->rc4_encrypt_key); + winpr_RC4_Final(rdp->rc4_encrypt_key); rdp->rc4_encrypt_key = NULL; } @@ -1661,8 +1661,8 @@ void rdp_free(rdpRdp* rdp) { if (rdp) { - crypto_rc4_free(rdp->rc4_decrypt_key); - crypto_rc4_free(rdp->rc4_encrypt_key); + winpr_RC4_Final(rdp->rc4_decrypt_key); + winpr_RC4_Final(rdp->rc4_encrypt_key); crypto_des3_free(rdp->fips_encrypt); crypto_des3_free(rdp->fips_decrypt); crypto_hmac_free(rdp->fips_hmac); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index ad24bd4f1..e5eae3dcb 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -51,6 +51,7 @@ #include #include +#include /* Security Header Flags */ #define SEC_EXCHANGE_PKT 0x0001 @@ -147,10 +148,10 @@ struct rdp_rdp rdpAutoDetect* autodetect; rdpHeartbeat* heartbeat; rdpMultitransport* multitransport; - struct crypto_rc4_struct* rc4_decrypt_key; + WINPR_RC4_CTX* rc4_decrypt_key; int decrypt_use_count; int decrypt_checksum_use_count; - struct crypto_rc4_struct* rc4_encrypt_key; + WINPR_RC4_CTX* rc4_encrypt_key; int encrypt_use_count; int encrypt_checksum_use_count; struct crypto_des3_struct* fips_encrypt; diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index acabcaa89..67e0c5d16 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -477,7 +477,7 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH]; WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; - CryptoRc4 rc4; + WINPR_RC4_CTX rc4; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ winpr_SHA1_Init(&sha1); @@ -492,14 +492,9 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) winpr_MD5_Update(&md5, sha1h, sizeof(sha1h)); winpr_MD5_Final(&md5, key); - rc4 = crypto_rc4_init(key, key_len); - if (!rc4) - { - WLog_ERR(TAG, "unable to allocate a rc4"); - return FALSE; - } - crypto_rc4(rc4, key_len, key, key); - crypto_rc4_free(rc4); + winpr_RC4_Init(&rc4, key, key_len); + winpr_RC4_Update(&rc4, key_len, key, key); + winpr_RC4_Final(&rc4); if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT) memcpy(key, salt, 3); @@ -516,17 +511,13 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp) if (!security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - crypto_rc4_free(rdp->rc4_encrypt_key); - rdp->rc4_encrypt_key = crypto_rc4_init(rdp->encrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_encrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 encrypt key"); - return FALSE; - } + winpr_RC4_Final(rdp->rc4_encrypt_key); + winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); + rdp->encrypt_use_count = 0; } - crypto_rc4(rdp->rc4_encrypt_key, length, data, data); + winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data); rdp->encrypt_use_count++; rdp->encrypt_checksum_use_count++; return TRUE; @@ -541,17 +532,12 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) { if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - crypto_rc4_free(rdp->rc4_decrypt_key); - rdp->rc4_decrypt_key = crypto_rc4_init(rdp->decrypt_key, rdp->rc4_key_len); - if (!rdp->rc4_decrypt_key) - { - WLog_ERR(TAG, "unable to allocate rc4 decrypt key"); - return FALSE; - } + winpr_RC4_Final(rdp->rc4_decrypt_key); + winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); rdp->decrypt_use_count = 0; } - crypto_rc4(rdp->rc4_decrypt_key, length, data, data); + winpr_RC4_Update(rdp->rc4_decrypt_key, length, data, data); rdp->decrypt_use_count += 1; rdp->decrypt_checksum_use_count++; return TRUE; diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 62e819935..de885bda5 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -28,25 +28,6 @@ #define TAG FREERDP_TAG("crypto") -CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length) -{ - CryptoRc4 rc4 = malloc(sizeof(*rc4)); - if (!rc4) - return NULL; - RC4_set_key(&rc4->rc4_key, length, key); - return rc4; -} - -void crypto_rc4(CryptoRc4 rc4, UINT32 length, const BYTE* in_data, BYTE* out_data) -{ - RC4(&rc4->rc4_key, length, in_data, out_data); -} - -void crypto_rc4_free(CryptoRc4 rc4) -{ - free(rc4); -} - CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec) { CryptoDes3 des3 = malloc(sizeof(*des3)); From 0bfe5bad85150b9facca2b293ffc005203392e59 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 20:16:19 +0100 Subject: [PATCH 057/128] Fixed naming of static functions. --- winpr/libwinpr/timezone/timezone.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 4a1f3e8c5..79cb6f36b 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -1471,7 +1471,7 @@ const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] = { "Yakutsk Standard Time", "Asia/Yakutsk" } }; -static UINT64 freerdp_windows_gmtime() +static UINT64 winpr_windows_gmtime() { time_t unix_time; UINT64 windows_time; @@ -1484,7 +1484,7 @@ static UINT64 freerdp_windows_gmtime() return windows_time; } -static char* freerdp_read_unix_timezone_identifier_from_file(FILE* fp) +static char* winpr_read_unix_timezone_identifier_from_file(FILE* fp) { long length; char* tzid = NULL; @@ -1515,7 +1515,7 @@ static char* freerdp_read_unix_timezone_identifier_from_file(FILE* fp) return tzid; } -static char* freerdp_get_timezone_from_link(void) +static char* winpr_get_timezone_from_link(void) { const char* links[] = { @@ -1571,7 +1571,7 @@ static char* freerdp_get_timezone_from_link(void) return NULL; } -static char* freerdp_get_unix_timezone_identifier_from_file(void) +static char* winpr_get_unix_timezone_identifier_from_file(void) { FILE* fp; char* tzid = NULL; @@ -1587,7 +1587,7 @@ static char* freerdp_get_unix_timezone_identifier_from_file(void) if (NULL == fp ) return NULL; - tzid = freerdp_read_unix_timezone_identifier_from_file(fp); + tzid = winpr_read_unix_timezone_identifier_from_file(fp); #if defined(ANDROID) pclose(fp) ; @@ -1598,7 +1598,7 @@ static char* freerdp_get_unix_timezone_identifier_from_file(void) } -static BOOL freerdp_match_unix_timezone_identifier_with_list(const char* tzid, const char* list) +static BOOL winpr_match_unix_timezone_identifier_with_list(const char* tzid, const char* list) { char* p; char* list_copy; @@ -1625,16 +1625,16 @@ static BOOL freerdp_match_unix_timezone_identifier_with_list(const char* tzid, c return FALSE; } -static TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) +static TIME_ZONE_ENTRY* winpr_detect_windows_time_zone(UINT32 bias) { int i, j; char* tzid; TIME_ZONE_ENTRY* timezone; - tzid = freerdp_get_unix_timezone_identifier_from_file(); + tzid = winpr_get_unix_timezone_identifier_from_file(); if (tzid == NULL) - tzid = freerdp_get_timezone_from_link(); + tzid = winpr_get_timezone_from_link(); if (tzid == NULL) return NULL; @@ -1646,7 +1646,7 @@ static TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) if (strcmp(TimeZoneTable[i].Id, WindowsTimeZoneIdTable[j].windows) != 0) continue; - if (freerdp_match_unix_timezone_identifier_with_list(tzid, WindowsTimeZoneIdTable[j].tzid)) + if (winpr_match_unix_timezone_identifier_with_list(tzid, WindowsTimeZoneIdTable[j].tzid)) { free(tzid); @@ -1665,12 +1665,12 @@ static TIME_ZONE_ENTRY* freerdp_detect_windows_time_zone(UINT32 bias) return NULL; } -static TIME_ZONE_RULE_ENTRY* freerdp_get_current_time_zone_rule(TIME_ZONE_RULE_ENTRY* rules, UINT32 count) +static TIME_ZONE_RULE_ENTRY* winpr_get_current_time_zone_rule(TIME_ZONE_RULE_ENTRY* rules, UINT32 count) { int i; UINT64 windows_time; - windows_time = freerdp_windows_gmtime(); + windows_time = winpr_windows_gmtime(); for (i = 0; i < (int) count; i++) { @@ -1714,7 +1714,7 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) WLog_DBG(TAG, "tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", tzname[0], tzname[1], timezone, daylight); - dtz = freerdp_detect_windows_time_zone(tz->Bias); + dtz = winpr_detect_windows_time_zone(tz->Bias); if (dtz!= NULL) { @@ -1733,7 +1733,7 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) if ((dtz->SupportsDST) && (dtz->RuleTableCount > 0)) { TIME_ZONE_RULE_ENTRY* rule; - rule = freerdp_get_current_time_zone_rule(dtz->RuleTable, dtz->RuleTableCount); + rule = winpr_get_current_time_zone_rule(dtz->RuleTable, dtz->RuleTableCount); if (rule != NULL) { From 95058c64d193939465666419319f384c48d1a0a2 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 20:16:33 +0100 Subject: [PATCH 058/128] Fixed argument checks and return values. --- libfreerdp/core/timezone.c | 13 ++++++++++++- libfreerdp/core/timezone.h | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/libfreerdp/core/timezone.c b/libfreerdp/core/timezone.c index 1aee3ba87..637afa64e 100644 --- a/libfreerdp/core/timezone.c +++ b/libfreerdp/core/timezone.c @@ -82,10 +82,15 @@ BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) { LPTIME_ZONE_INFORMATION tz; + if (!s || !settings) + return FALSE; + if (Stream_GetRemainingLength(s) < 172) return FALSE; tz = settings->ClientTimeZone; + if (!tz) + return FALSE; Stream_Read_UINT32(s, tz->Bias); /* Bias */ @@ -111,12 +116,15 @@ BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) * @param settings settings */ -void rdp_write_client_time_zone(wStream* s, rdpSettings* settings) +BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings) { LPTIME_ZONE_INFORMATION tz; DWORD rc; tz = settings->ClientTimeZone; + if (!tz) + return FALSE; + rc = GetTimeZoneInformation(tz); /* Bias */ @@ -146,4 +154,7 @@ void rdp_write_client_time_zone(wStream* s, rdpSettings* settings) /* DaylightBias */ Stream_Write_UINT32(s, tz->DaylightBias); DEBUG_TIMEZONE("DaylightBias=%d", tz->DaylightBias); + + return TRUE } + diff --git a/libfreerdp/core/timezone.h b/libfreerdp/core/timezone.h index d40940988..92b2c7af1 100644 --- a/libfreerdp/core/timezone.h +++ b/libfreerdp/core/timezone.h @@ -32,7 +32,7 @@ #include BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings); -void rdp_write_client_time_zone(wStream* s, rdpSettings* settings); +BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings); #define TIMEZONE_TAG FREERDP_TAG("core.timezone") #ifdef WITH_DEBUG_TIMEZONE From 6e8ea34f061804a6a441c10a269b33eeb9b580ae Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 20:32:20 +0100 Subject: [PATCH 059/128] Updated cryto wrapper API. --- winpr/include/winpr/crypto.h | 30 +++++------ winpr/libwinpr/crypto/cipher.c | 14 +++-- winpr/libwinpr/crypto/hash.c | 95 +++++++++++++++++++++++----------- 3 files changed, 89 insertions(+), 50 deletions(-) diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 2cf013f87..b0f2ef57e 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -648,10 +648,10 @@ typedef union _WINPR_MD5_CTX WINPR_MD5_CTX; extern "C" { #endif -WINPR_API void winpr_MD5_Init(WINPR_MD5_CTX* ctx); -WINPR_API void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API void winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output); -WINPR_API void winpr_MD5(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx); +WINPR_API BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output); +WINPR_API BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output); #ifdef __cplusplus } @@ -689,10 +689,10 @@ typedef union _WINPR_MD4_CTX WINPR_MD4_CTX; extern "C" { #endif -WINPR_API void winpr_MD4_Init(WINPR_MD4_CTX* ctx); -WINPR_API void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API void winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output); -WINPR_API void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx); +WINPR_API BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output); +WINPR_API BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); #ifdef __cplusplus } @@ -732,10 +732,10 @@ typedef union _WINPR_SHA1_CTX WINPR_SHA1_CTX; extern "C" { #endif -WINPR_API void winpr_SHA1_Init(WINPR_SHA1_CTX* ctx); -WINPR_API void winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API void winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output); -WINPR_API void winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx); +WINPR_API BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output); +WINPR_API BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output); #ifdef __cplusplus } @@ -896,9 +896,9 @@ typedef union _WINPR_RC4_CTX WINPR_RC4_CTX; extern "C" { #endif -WINPR_API void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen); -WINPR_API int winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); -WINPR_API void winpr_RC4_Final(WINPR_RC4_CTX* ctx); +WINPR_API BOOL winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen); +WINPR_API BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); +WINPR_API BOOL winpr_RC4_Final(WINPR_RC4_CTX* ctx); #ifdef __cplusplus } diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index 7eef590c2..5f4521a2d 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -43,7 +43,7 @@ * RC4 */ -void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen) +BOOL winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen) { #if defined(WITH_OPENSSL) RC4_set_key((RC4_KEY*) ctx, keylen, key); @@ -51,25 +51,29 @@ void winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen) mbedtls_arc4_init((mbedtls_arc4_context*) ctx); mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, keylen); #endif + return TRUE; } -int winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) +BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) { #if defined(WITH_OPENSSL) RC4((RC4_KEY*) ctx, length, input, output); - return 0; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) - return mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output); + if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) != 0) + return FALSE; #endif + + return TRUE; } -void winpr_RC4_Final(WINPR_RC4_CTX* ctx) +BOOL winpr_RC4_Final(WINPR_RC4_CTX* ctx) { #if defined(WITH_OPENSSL) #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) mbedtls_arc4_free((mbedtls_arc4_context*) ctx); #endif + return TRUE; } /** diff --git a/winpr/libwinpr/crypto/hash.c b/winpr/libwinpr/crypto/hash.c index ba7fdb720..8b5e11599 100644 --- a/winpr/libwinpr/crypto/hash.c +++ b/winpr/libwinpr/crypto/hash.c @@ -43,123 +43,158 @@ * MD5 */ -void winpr_MD5_Init(WINPR_MD5_CTX* ctx) +BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx) { #if defined(WITH_OPENSSL) - MD5_Init((MD5_CTX*) ctx); + if (MD5_Init((MD5_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_init((mbedtls_md5_context*) ctx); mbedtls_md5_starts((mbedtls_md5_context*) ctx); #endif + + return TRUE; } -void winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) - MD5_Update((MD5_CTX*) ctx, input, ilen); + if (MD5_Update((MD5_CTX*) ctx, input, ilen) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_update((mbedtls_md5_context*) ctx, input, ilen); #endif + + return TRUE; } -void winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output) +BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output) { #if defined(WITH_OPENSSL) - MD5_Final(output, (MD5_CTX*) ctx); + if (MD5_Final(output, (MD5_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_finish((mbedtls_md5_context*) ctx, output); mbedtls_md5_free((mbedtls_md5_context*) ctx); #endif + + return TRUE; } -void winpr_MD5(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output) { WINPR_MD5_CTX ctx; - winpr_MD5_Init(&ctx); - winpr_MD5_Update(&ctx, input, ilen); - winpr_MD5_Final(&ctx, output); + + if (!winpr_MD5_Init(&ctx)) + return FALSE; + if (!winpr_MD5_Update(&ctx, input, ilen)) + return FALSE; + return winpr_MD5_Final(&ctx, output); } /** * MD4 */ -void winpr_MD4_Init(WINPR_MD4_CTX* ctx) +BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx) { #if defined(WITH_OPENSSL) - MD4_Init((MD4_CTX*) ctx); + if (MD4_Init((MD4_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_init((mbedtls_md4_context*) ctx); mbedtls_md4_starts((mbedtls_md4_context*) ctx); #endif + return TRUE; } -void winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) - MD4_Update((MD4_CTX*) ctx, input, ilen); + if (MD4_Update((MD4_CTX*) ctx, input, ilen) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_update((mbedtls_md4_context*) ctx, input, ilen); #endif + + return TRUE; } -void winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output) +BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output) { #if defined(WITH_OPENSSL) - MD4_Final(output, (MD4_CTX*) ctx); + if (MD4_Final(output, (MD4_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_finish((mbedtls_md4_context*) ctx, output); mbedtls_md4_free((mbedtls_md4_context*) ctx); #endif + + return TRUE; } -void winpr_MD4(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output) { WINPR_MD4_CTX ctx; - winpr_MD4_Init(&ctx); - winpr_MD4_Update(&ctx, input, ilen); - winpr_MD4_Final(&ctx, output); + + if (!winpr_MD4_Init(&ctx)) + return FALSE; + if (!winpr_MD4_Update(&ctx, input, ilen)) + return FALSE; + return winpr_MD4_Final(&ctx, output); } /** * SHA1 */ -void winpr_SHA1_Init(WINPR_SHA1_CTX* ctx) +BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx) { #if defined(WITH_OPENSSL) - SHA1_Init((SHA_CTX*) ctx); + if (SHA1_Init((SHA_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_init((mbedtls_sha1_context*) ctx); mbedtls_sha1_starts((mbedtls_sha1_context*) ctx); #endif + + return TRUE; } -void winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) - SHA1_Update((SHA_CTX*) ctx, input, ilen); + if (SHA1_Update((SHA_CTX*) ctx, input, ilen) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_update((mbedtls_sha1_context*) ctx, input, ilen); #endif + + return TRUE; } -void winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output) +BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output) { #if defined(WITH_OPENSSL) - SHA1_Final(output, (SHA_CTX*) ctx); + if (SHA1_Final(output, (SHA_CTX*) ctx) != 1) + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_finish((mbedtls_sha1_context*) ctx, output); mbedtls_sha1_free((mbedtls_sha1_context*) ctx); #endif + + return TRUE; } -void winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output) { WINPR_SHA1_CTX ctx; - winpr_SHA1_Init(&ctx); - winpr_SHA1_Update(&ctx, input, ilen); - winpr_SHA1_Final(&ctx, output); + + if (!winpr_SHA1_Init(&ctx)) + return FALSE; + if (!winpr_SHA1_Update(&ctx, input, ilen)) + return FALSE; + return winpr_SHA1_Final(&ctx, output); } /** From 4ca6b9bf1053751194f37568dcc03bf986d77eb8 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 20:39:49 +0100 Subject: [PATCH 060/128] Unified random functions and remaining MD5. --- libfreerdp/common/assistance.c | 30 +++++++++++++++++++--------- libfreerdp/core/autodetect.c | 6 ++++-- libfreerdp/core/gateway/ncacn_http.c | 2 -- libfreerdp/core/gateway/ntlm.c | 1 - libfreerdp/core/gateway/rpc.c | 1 - libfreerdp/core/gateway/rts.c | 3 ++- libfreerdp/crypto/crypto.c | 3 ++- 7 files changed, 29 insertions(+), 17 deletions(-) diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index 9e4702e7c..c69d72998 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -22,16 +22,13 @@ #endif #include +#include #include #include #include -#include -#include -#include #include #include -#include #include #include @@ -523,7 +520,7 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) * Example: WB^6HsrIaFmEpi */ - RAND_bytes((BYTE*) nums, sizeof(nums)); + winpr_RAND((BYTE*) nums, sizeof(nums)); passStub[0] = set1[nums[0] % sizeof(set1)]; /* character 0 */ passStub[1] = set2[nums[1] % sizeof(set2)]; /* character 1 */ @@ -547,7 +544,7 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize) { int status; - MD5_CTX md5Ctx; + WINPR_MD5_CTX md5Ctx; int cbPasswordW; int cbPassStubW; int EncryptedSize; @@ -565,14 +562,29 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas cbPasswordW = (status - 1) * 2; - MD5_Init(&md5Ctx); - MD5_Update(&md5Ctx, PasswordW, cbPasswordW); - MD5_Final((void*) PasswordHash, &md5Ctx); + if (!winpr_MD5_Init(&md5Ctx)) + { + free (PasswordW); + return NULL; + } + if (!winpr_MD5_Update(&md5Ctx, (BYTE*)PasswordW, cbPasswordW)) + { + free (PasswordW); + return NULL; + } + if (!winpr_MD5_Final(&md5Ctx, (BYTE*) PasswordHash)) + { + free (PasswordW); + return NULL; + } status = ConvertToUnicode(CP_UTF8, 0, passStub, -1, &PassStubW, 0); if (status <= 0) + { + free (PasswordW); return NULL; + } cbPassStubW = (status - 1) * 2; diff --git a/libfreerdp/core/autodetect.c b/libfreerdp/core/autodetect.c index 1a89737c6..178e989ce 100644 --- a/libfreerdp/core/autodetect.c +++ b/libfreerdp/core/autodetect.c @@ -21,6 +21,8 @@ #include "config.h" #endif +#include + #include "autodetect.h" #define RDP_RTT_REQUEST_TYPE_CONTINUOUS 0x0001 @@ -173,7 +175,7 @@ BOOL autodetect_send_bandwidth_measure_payload(rdpContext* context, UINT16 paylo return FALSE; } - RAND_bytes(buffer, payloadLength); + winpr_RAND(buffer, payloadLength); Stream_Write(s, buffer, payloadLength); bResult = rdp_send_message_channel_pdu(context->rdp, s, SEC_AUTODETECT_REQ); @@ -225,7 +227,7 @@ static BOOL autodetect_send_bandwidth_measure_stop(rdpContext* context, UINT16 p return FALSE; } - RAND_bytes(buffer, payloadLength); + winpr_RAND(buffer, payloadLength); Stream_Write(s, buffer, payloadLength); } } diff --git a/libfreerdp/core/gateway/ncacn_http.c b/libfreerdp/core/gateway/ncacn_http.c index 175aab3c3..f6f680118 100644 --- a/libfreerdp/core/gateway/ncacn_http.c +++ b/libfreerdp/core/gateway/ncacn_http.c @@ -29,8 +29,6 @@ #include #include -#include - #define TAG FREERDP_TAG("core.gateway.ntlm") wStream* rpc_ntlm_http_request(rdpRpc* rpc, HttpContext* http, const char* method, int contentLength, SecBuffer* ntlmToken) diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index c9795b648..ce6925bbd 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -28,7 +28,6 @@ #include #include -#include #include "http.h" diff --git a/libfreerdp/core/gateway/rpc.c b/libfreerdp/core/gateway/rpc.c index 16f4af1eb..d7309b957 100644 --- a/libfreerdp/core/gateway/rpc.c +++ b/libfreerdp/core/gateway/rpc.c @@ -30,7 +30,6 @@ #include -#include #include #ifdef HAVE_VALGRIND_MEMCHECK_H diff --git a/libfreerdp/core/gateway/rts.c b/libfreerdp/core/gateway/rts.c index 31edc8676..df939b9d8 100644 --- a/libfreerdp/core/gateway/rts.c +++ b/libfreerdp/core/gateway/rts.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -422,7 +423,7 @@ int rts_ping_traffic_sent_notify_command_write(BYTE* buffer, UINT32 PingTrafficS void rts_generate_cookie(BYTE* cookie) { - RAND_pseudo_bytes(cookie, 16); + winpr_RAND(cookie, 16); } /* CONN/A Sequence */ diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index de885bda5..654efeb38 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -22,6 +22,7 @@ #endif #include +#include #include #include @@ -290,7 +291,7 @@ void crypto_reverse(BYTE* data, int length) void crypto_nonce(BYTE* nonce, int size) { - RAND_bytes((void*) nonce, size); + winpr_RAND((void*) nonce, size); } char* crypto_cert_fingerprint(X509* xcert) From f997421098d7b67230497fac3842f770ea68a12c Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 24 Feb 2016 21:45:09 +0100 Subject: [PATCH 061/128] Unified hmac functions. --- include/freerdp/crypto/crypto.h | 16 -- libfreerdp/common/assistance.c | 4 +- libfreerdp/core/certificate.c | 9 +- libfreerdp/core/connection.c | 4 +- libfreerdp/core/gcc.c | 9 +- libfreerdp/core/info.c | 16 +- libfreerdp/core/license.c | 9 +- libfreerdp/core/rdp.c | 4 +- libfreerdp/core/rdp.h | 2 +- libfreerdp/core/security.c | 263 +++++++++++++------- libfreerdp/crypto/crypto.c | 49 ---- winpr/include/winpr/crypto.h | 61 ++--- winpr/libwinpr/crypto/cipher.c | 30 +-- winpr/libwinpr/crypto/hash.c | 126 ++++++---- winpr/libwinpr/crypto/test/TestCryptoHash.c | 85 ++++--- winpr/libwinpr/sspi/NTLM/ntlm.c | 14 +- winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c | 4 +- winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 39 +-- winpr/libwinpr/utils/ntlm.c | 25 +- 19 files changed, 421 insertions(+), 348 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index ae74e1d90..89b3eef26 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -25,10 +25,8 @@ #include #include -#include #include #include -#include #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f) #define D2I_X509_CONST const @@ -46,11 +44,6 @@ struct crypto_des3_struct EVP_CIPHER_CTX des3_ctx; }; -struct crypto_hmac_struct -{ - HMAC_CTX hmac_ctx; -}; - struct crypto_cert_struct { X509 * px509; @@ -69,15 +62,6 @@ FREERDP_API BOOL crypto_des3_encrypt(CryptoDes3 des3, UINT32 length, const BYTE FREERDP_API BOOL crypto_des3_decrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE* out_data); FREERDP_API void crypto_des3_free(CryptoDes3 des3); -typedef struct crypto_hmac_struct* CryptoHmac; - -FREERDP_API CryptoHmac crypto_hmac_new(void); -FREERDP_API BOOL crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE *data, UINT32 length); -FREERDP_API BOOL crypto_hmac_md5_init(CryptoHmac hmac, const BYTE *data, UINT32 length); -FREERDP_API void crypto_hmac_update(CryptoHmac hmac, const BYTE *data, UINT32 length); -FREERDP_API void crypto_hmac_final(CryptoHmac hmac, BYTE *out_data, UINT32 length); -FREERDP_API void crypto_hmac_free(CryptoHmac hmac); - typedef struct crypto_cert_struct* CryptoCert; #include diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index c69d72998..32b7bb534 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -548,7 +548,7 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas int cbPasswordW; int cbPassStubW; int EncryptedSize; - BYTE PasswordHash[16]; + BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH]; EVP_CIPHER_CTX rc4Ctx; BYTE* pbIn, *pbOut; int cbOut, cbIn, cbFinal; @@ -572,7 +572,7 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas free (PasswordW); return NULL; } - if (!winpr_MD5_Final(&md5Ctx, (BYTE*) PasswordHash)) + if (!winpr_MD5_Final(&md5Ctx, (BYTE*) PasswordHash, sizeof(PasswordHash))) { free (PasswordW); return NULL; diff --git a/libfreerdp/core/certificate.c b/libfreerdp/core/certificate.c index e5999b836..9ce68f355 100644 --- a/libfreerdp/core/certificate.c +++ b/libfreerdp/core/certificate.c @@ -404,9 +404,12 @@ static BOOL certificate_process_server_public_signature(rdpCertificate* certific BYTE encsig[TSSK_KEY_LENGTH + 8]; BYTE md5hash[WINPR_MD5_DIGEST_LENGTH]; - winpr_MD5_Init(&md5ctx); - winpr_MD5_Update(&md5ctx, sigdata, sigdatalen); - winpr_MD5_Final(&md5ctx, md5hash); + if (!winpr_MD5_Init(&md5ctx)) + return FALSE; + if (!winpr_MD5_Update(&md5ctx, sigdata, sigdatalen)) + return FALSE; + if (!winpr_MD5_Final(&md5ctx, md5hash, sizeof(md5hash))) + return FALSE; Stream_Read(s, encsig, siglen); /* Last 8 bytes shall be all zero. */ diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 91e498f17..44b6deb5c 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -503,7 +503,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) goto end; } - rdp->fips_hmac = crypto_hmac_new(); + rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX)); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); @@ -611,7 +611,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) goto end; } - rdp->fips_hmac = crypto_hmac_new(); + rdp->fips_hmac = calloc(1, sizeof(WINPR_HMAC_CTX)); if (!rdp->fips_hmac) { WLog_ERR(TAG, "unable to allocate fips hmac"); diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 5914b64cd..86aff0004 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -1376,9 +1376,12 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) memcpy(signature, initial_signature, sizeof(initial_signature)); - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, sigData, sigDataLen); - winpr_MD5_Final(&md5, signature); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, sigData, sigDataLen)) + return FALSE; + if (!winpr_MD5_Final(&md5, signature, sizeof(signature))) + return FALSE; crypto_rsa_private_encrypt(signature, sizeof(signature), TSSK_KEY_LENGTH, tssk_modulus, tssk_privateExponent, encryptedSignature); diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 6fbff79da..dc034b90e 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -44,7 +44,7 @@ static const char* const INFO_TYPE_LOGON_STRINGS[4] = BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) { - CryptoHmac hmac; + WINPR_HMAC_CTX hmac; BYTE ClientRandom[32]; BYTE AutoReconnectRandom[32]; ARC_SC_PRIVATE_PACKET* serverCookie; @@ -67,18 +67,14 @@ BOOL rdp_compute_client_auto_reconnect_cookie(rdpRdp* rdp) if (settings->SelectedProtocol == PROTOCOL_RDP) CopyMemory(ClientRandom, settings->ClientRandom, settings->ClientRandomLength); - hmac = crypto_hmac_new(); - - if (!hmac) - return FALSE; - /* SecurityVerifier = HMAC_MD5(AutoReconnectRandom, ClientRandom) */ - if (!crypto_hmac_md5_init(hmac, AutoReconnectRandom, 16)) + if (!winpr_HMAC_Init(&hmac, WINPR_MD_MD5, AutoReconnectRandom, 16)) + return FALSE; + if (!winpr_HMAC_Update(&hmac, ClientRandom, 32)) + return FALSE; + if (!winpr_HMAC_Final(&hmac, clientCookie->securityVerifier, 16)) return FALSE; - crypto_hmac_update(hmac, ClientRandom, 32); - crypto_hmac_final(hmac, clientCookie->securityVerifier, 16); - crypto_hmac_free(hmac); return TRUE; } diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 2dba07c40..bfb988192 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -391,9 +391,12 @@ BOOL license_generate_hwid(rdpLicense* license) ZeroMemory(macAddress, sizeof(macAddress)); ZeroMemory(license->HardwareId, HWID_LENGTH); - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, macAddress, sizeof(macAddress)); - winpr_MD5_Final(&md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH]); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, macAddress, sizeof(macAddress))) + return FALSE; + if (!winpr_MD5_Final(&md5, &license->HardwareId[HWID_PLATFORM_ID_LENGTH], WINPR_MD5_DIGEST_LENGTH)) + return FALSE; return TRUE; } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index abb6cd0ed..8c507ff76 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1614,7 +1614,7 @@ void rdp_reset(rdpRdp* rdp) if (rdp->fips_hmac) { - crypto_hmac_free(rdp->fips_hmac); + free(rdp->fips_hmac); rdp->fips_hmac = NULL; } @@ -1665,7 +1665,7 @@ void rdp_free(rdpRdp* rdp) winpr_RC4_Final(rdp->rc4_encrypt_key); crypto_des3_free(rdp->fips_encrypt); crypto_des3_free(rdp->fips_decrypt); - crypto_hmac_free(rdp->fips_hmac); + free(rdp->fips_hmac); freerdp_settings_free(rdp->settings); freerdp_settings_free(rdp->settingsCopy); transport_free(rdp->transport); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index e5eae3dcb..1fb88effc 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -156,7 +156,7 @@ struct rdp_rdp int encrypt_checksum_use_count; struct crypto_des3_struct* fips_encrypt; struct crypto_des3_struct* fips_decrypt; - struct crypto_hmac_struct* fips_hmac; + WINPR_HMAC_CTX* fips_hmac; UINT32 sec_flags; BOOL do_crypt; BOOL do_crypt_license; diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 67e0c5d16..b63022763 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -134,18 +134,28 @@ static BOOL security_salted_hash(const BYTE* salt, const BYTE* input, int length /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1(Input + Salt + Salt1 + Salt2)) */ /* SHA1_Digest = SHA1(Input + Salt + Salt1 + Salt2) */ - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, input, length); /* Input */ - winpr_SHA1_Update(&sha1, salt, 48); /* Salt (48 bytes) */ - winpr_SHA1_Update(&sha1, salt1, 32); /* Salt1 (32 bytes) */ - winpr_SHA1_Update(&sha1, salt2, 32); /* Salt2 (32 bytes) */ - winpr_SHA1_Final(&sha1, sha1_digest); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, input, length)) /* Input */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, salt, 48)) /* Salt (48 bytes) */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, salt1, 32)) /* Salt1 (32 bytes) */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, salt2, 32)) /* Salt2 (32 bytes) */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) + return FALSE; /* SaltedHash(Salt, Input, Salt1, Salt2) = MD5(S + SHA1_Digest) */ - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, salt, 48); /* Salt (48 bytes) */ - winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - winpr_MD5_Final(&md5, output); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, salt, 48)) /* Salt (48 bytes) */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) + return FALSE; return TRUE; } @@ -192,11 +202,16 @@ BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BY { WINPR_MD5_CTX md5; - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, in0, 16); - winpr_MD5_Update(&md5, in1, 32); - winpr_MD5_Update(&md5, in2, 32); - winpr_MD5_Final(&md5, output); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, in0, 16)) + return FALSE; + if (!winpr_MD5_Update(&md5, in1, 32)) + return FALSE; + if (!winpr_MD5_Update(&md5, in2, 32)) + return FALSE; + if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) + return FALSE; return TRUE; } @@ -228,19 +243,30 @@ BOOL security_mac_data(const BYTE* mac_salt_key, const BYTE* data, UINT32 length security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MacSaltKey + pad1 + length + data) */ - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, mac_salt_key, 16); /* MacSaltKey */ - winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); /* pad1 */ - winpr_SHA1_Update(&sha1, length_le, sizeof(length_le)); /* length */ - winpr_SHA1_Update(&sha1, data, length); /* data */ - winpr_SHA1_Final(&sha1, sha1_digest); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, mac_salt_key, 16)) /* MacSaltKey */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, data, length)) /* data */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) + return FALSE; /* MacData = MD5(MacSaltKey + pad2 + SHA1_Digest) */ - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, mac_salt_key, 16); /* MacSaltKey */ - winpr_MD5_Update(&md5, pad2, sizeof(pad2)); /* pad2 */ - winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - winpr_MD5_Final(&md5, output); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, mac_salt_key, 16)) /* MacSaltKey */ + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) + return FALSE; return TRUE; } @@ -255,19 +281,30 @@ BOOL security_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, BYTE* security_UINT32_le(length_le, length); /* length must be little-endian */ /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); /* pad1 */ - winpr_SHA1_Update(&sha1, length_le, sizeof(length_le)); /* length */ - winpr_SHA1_Update(&sha1, data, length); /* data */ - winpr_SHA1_Final(&sha1, sha1_digest); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, data, length)) /* data */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) + return FALSE; /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - winpr_MD5_Update(&md5, pad2, sizeof(pad2)); /* pad2 */ - winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - winpr_MD5_Final(&md5, md5_digest); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, md5_digest, sizeof(md5_digest))) + return FALSE; memcpy(output, md5_digest, 8); return TRUE; @@ -299,20 +336,32 @@ BOOL security_salted_mac_signature(rdpRdp *rdp, const BYTE* data, UINT32 length, } /* SHA1_Digest = SHA1(MACKeyN + pad1 + length + data) */ - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); /* pad1 */ - winpr_SHA1_Update(&sha1, length_le, sizeof(length_le)); /* length */ - winpr_SHA1_Update(&sha1, data, length); /* data */ - winpr_SHA1_Update(&sha1, use_count_le, sizeof(use_count_le)); /* encryptionCount */ - winpr_SHA1_Final(&sha1, sha1_digest); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) /* pad1 */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, length_le, sizeof(length_le))) /* length */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, data, length)) /* data */ + return FALSE; + if (!winpr_SHA1_Update(&sha1, use_count_le, sizeof(use_count_le))) /* encryptionCount */ + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1_digest, sizeof(sha1_digest))) + return FALSE; /* MACSignature = First64Bits(MD5(MACKeyN + pad2 + SHA1_Digest)) */ - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len); /* MacKeyN */ - winpr_MD5_Update(&md5, pad2, sizeof(pad2)); /* pad2 */ - winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest)); /* SHA1_Digest */ - winpr_MD5_Final(&md5, md5_digest); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, rdp->sign_key, rdp->rc4_key_len)) /* MacKeyN */ + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) /* pad2 */ + return FALSE; + if (!winpr_MD5_Update(&md5, sha1_digest, sizeof(sha1_digest))) /* SHA1_Digest */ + return FALSE; + if (!winpr_MD5_Final(&md5, md5_digest, sizeof(md5_digest))) + return FALSE; memcpy(output, md5_digest, 8); return TRUE; @@ -388,22 +437,34 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) BYTE client_encrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1]; BYTE client_decrypt_key_t[WINPR_SHA1_DIGEST_LENGTH + 1]; - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, client_random + 16, 16); - winpr_SHA1_Update(&sha1, server_random + 16, 16); - winpr_SHA1_Final(&sha1, client_encrypt_key_t); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_random + 16, 16)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, server_random + 16, 16)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, client_encrypt_key_t, sizeof(client_encrypt_key_t))) + return FALSE; client_encrypt_key_t[20] = client_encrypt_key_t[0]; - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, client_random, 16); - winpr_SHA1_Update(&sha1, server_random, 16); - winpr_SHA1_Final(&sha1, client_decrypt_key_t); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_random, 16)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, server_random, 16)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, client_decrypt_key_t, sizeof(client_decrypt_key_t))) + return FALSE; client_decrypt_key_t[20] = client_decrypt_key_t[0]; - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, client_decrypt_key_t, 20); - winpr_SHA1_Update(&sha1, client_encrypt_key_t, 20); - winpr_SHA1_Final(&sha1, rdp->fips_sign_key); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_decrypt_key_t, 20)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, client_encrypt_key_t, 20)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; if (rdp->settings->ServerMode) { @@ -480,21 +541,34 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) WINPR_RC4_CTX rc4; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ - winpr_SHA1_Init(&sha1); - winpr_SHA1_Update(&sha1, update_key, key_len); - winpr_SHA1_Update(&sha1, pad1, sizeof(pad1)); - winpr_SHA1_Update(&sha1, key, key_len); - winpr_SHA1_Final(&sha1, sha1h); + if (!winpr_SHA1_Init(&sha1)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, update_key, key_len)) + return FALSE; + if (!winpr_SHA1_Update(&sha1, pad1, sizeof(pad1))) + return FALSE; + if (!winpr_SHA1_Update(&sha1, key, key_len)) + return FALSE; + if (!winpr_SHA1_Final(&sha1, sha1h, sizeof(sha1h))) + return FALSE; - winpr_MD5_Init(&md5); - winpr_MD5_Update(&md5, update_key, key_len); - winpr_MD5_Update(&md5, pad2, sizeof(pad2)); - winpr_MD5_Update(&md5, sha1h, sizeof(sha1h)); - winpr_MD5_Final(&md5, key); + if (!winpr_MD5_Init(&md5)) + return FALSE; + if (!winpr_MD5_Update(&md5, update_key, key_len)) + return FALSE; + if (!winpr_MD5_Update(&md5, pad2, sizeof(pad2))) + return FALSE; + if (!winpr_MD5_Update(&md5, sha1h, sizeof(sha1h))) + return FALSE; + if (!winpr_MD5_Final(&md5, key, WINPR_MD5_DIGEST_LENGTH)) + return FALSE; - winpr_RC4_Init(&rc4, key, key_len); - winpr_RC4_Update(&rc4, key_len, key, key); - winpr_RC4_Final(&rc4); + if (!winpr_RC4_Init(&rc4, key, key_len)) + return FALSE; + if (!winpr_RC4_Update(&rc4, key_len, key, key)) + return FALSE; + if (!winpr_RC4_Final(&rc4)) + return FALSE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT) memcpy(key, salt, 3); @@ -511,13 +585,16 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp) if (!security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - winpr_RC4_Final(rdp->rc4_encrypt_key); - winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); + if (!winpr_RC4_Final(rdp->rc4_encrypt_key)) + return FALSE; + if (!winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + return FALSE; rdp->encrypt_use_count = 0; } - winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data); + if (!winpr_RC4_Update(rdp->rc4_encrypt_key, length, data, data)) + return FALSE; rdp->encrypt_use_count++; rdp->encrypt_checksum_use_count++; return TRUE; @@ -532,12 +609,15 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) { if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - winpr_RC4_Final(rdp->rc4_decrypt_key); - winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); + if (!winpr_RC4_Final(rdp->rc4_decrypt_key)) + return FALSE; + if (!winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) + return FALSE; rdp->decrypt_use_count = 0; } - winpr_RC4_Update(rdp->rc4_decrypt_key, length, data, data); + if (!winpr_RC4_Update(rdp->rc4_decrypt_key, length, data, data)) + return FALSE; rdp->decrypt_use_count += 1; rdp->decrypt_checksum_use_count++; return TRUE; @@ -550,12 +630,14 @@ BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* security_UINT32_le(use_count_le, rdp->encrypt_use_count); - if (!crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20)) + if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, rdp->fips_sign_key, 20)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, data, length)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4)) + return FALSE; + if (!winpr_HMAC_Final(rdp->fips_hmac, buf, 20)) return FALSE; - - crypto_hmac_update(rdp->fips_hmac, data, length); - crypto_hmac_update(rdp->fips_hmac, use_count_le, 4); - crypto_hmac_final(rdp->fips_hmac, buf, 20); memmove(output, buf, 8); return TRUE; @@ -581,11 +663,14 @@ BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig security_UINT32_le(use_count_le, rdp->decrypt_use_count); - if (!crypto_hmac_sha1_init(rdp->fips_hmac, rdp->fips_sign_key, 20)) + if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, rdp->fips_sign_key, 20)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, data, length)) + return FALSE; + if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4)) + return FALSE; + if (!winpr_HMAC_Final(rdp->fips_hmac, buf, 20)) return FALSE; - crypto_hmac_update(rdp->fips_hmac, data, length); - crypto_hmac_update(rdp->fips_hmac, use_count_le, 4); - crypto_hmac_final(rdp->fips_hmac, buf, 20); rdp->decrypt_use_count++; diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 654efeb38..dfb1dbc8b 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -77,55 +77,6 @@ void crypto_des3_free(CryptoDes3 des3) free(des3); } -CryptoHmac crypto_hmac_new(void) -{ - CryptoHmac hmac = malloc(sizeof(*hmac)); - if (!hmac) - return NULL; - - HMAC_CTX_init(&hmac->hmac_ctx); - return hmac; -} - -BOOL crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE* data, UINT32 length) -{ -#if (OPENSSL_VERSION_NUMBER >= 0x00909000) - return HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL) == 1; -#else - HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_sha1(), NULL); - return TRUE; -#endif -} - -BOOL crypto_hmac_md5_init(CryptoHmac hmac, const BYTE* data, UINT32 length) -{ -#if (OPENSSL_VERSION_NUMBER >= 0x00909000) - return HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_md5(), NULL) == 1; -#else - HMAC_Init_ex(&hmac->hmac_ctx, data, length, EVP_md5(), NULL); - return TRUE; -#endif -} - -void crypto_hmac_update(CryptoHmac hmac, const BYTE* data, UINT32 length) -{ - HMAC_Update(&hmac->hmac_ctx, data, length); -} - -void crypto_hmac_final(CryptoHmac hmac, BYTE* out_data, UINT32 length) -{ - HMAC_Final(&hmac->hmac_ctx, out_data, &length); -} - -void crypto_hmac_free(CryptoHmac hmac) -{ - if (hmac == NULL) - return; - - HMAC_CTX_cleanup(&hmac->hmac_ctx); - free(hmac); -} - CryptoCert crypto_cert_read(BYTE* data, UINT32 length) { CryptoCert cert = malloc(sizeof(*cert)); diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index b0f2ef57e..886a5174f 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -650,8 +650,8 @@ extern "C" { WINPR_API BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx); WINPR_API BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output); -WINPR_API BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -685,14 +685,16 @@ union _WINPR_MD4_CTX }; typedef union _WINPR_MD4_CTX WINPR_MD4_CTX; +#define WINPR_MD4_DIGEST_LENGTH 16 + #ifdef __cplusplus extern "C" { #endif WINPR_API BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx); WINPR_API BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output); -WINPR_API BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -734,8 +736,8 @@ extern "C" { WINPR_API BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx); WINPR_API BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output); -WINPR_API BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -744,17 +746,19 @@ WINPR_API BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output); /** * HMAC */ - -#define WINPR_MD_NONE 0 -#define WINPR_MD_MD2 1 -#define WINPR_MD_MD4 2 -#define WINPR_MD_MD5 3 -#define WINPR_MD_SHA1 4 -#define WINPR_MD_SHA224 5 -#define WINPR_MD_SHA256 6 -#define WINPR_MD_SHA384 7 -#define WINPR_MD_SHA512 8 -#define WINPR_MD_RIPEMD160 9 +typedef enum +{ + WINPR_MD_NONE = 0, + WINPR_MD_MD2 = 1, + WINPR_MD_MD4 = 2, + WINPR_MD_MD5 = 3, + WINPR_MD_SHA1 = 4, + WINPR_MD_SHA224 = 5, + WINPR_MD_SHA256 = 6, + WINPR_MD_SHA384 = 7, + WINPR_MD_SHA512 = 8, + WINPR_MD_RIPEMD160 = 9 +} WINPR_MD_TYPE; struct _OPENSSL_EVP_MD_CTX { @@ -797,10 +801,11 @@ typedef union _WINPR_HMAC_CTX WINPR_HMAC_CTX; extern "C" { #endif -WINPR_API int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen); -WINPR_API int winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API int winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output); -WINPR_API int winpr_HMAC(int md, const BYTE* key, size_t keylen, const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen); +WINPR_API BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, + const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -842,10 +847,10 @@ typedef union _WINPR_DIGEST_CTX WINPR_DIGEST_CTX; extern "C" { #endif -WINPR_API int winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, int md); -WINPR_API int winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen); -WINPR_API int winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output); -WINPR_API int winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output); +WINPR_API BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md); +WINPR_API BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen); +WINPR_API BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t ilen); +WINPR_API BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen); #ifdef __cplusplus } @@ -1011,9 +1016,9 @@ typedef union _WINPR_CIPHER_CTX WINPR_CIPHER_CTX; extern "C" { #endif -WINPR_API int winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv); -WINPR_API int winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen); -WINPR_API int winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen); +WINPR_API BOOL winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv); +WINPR_API BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen); +WINPR_API BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen); #ifdef __cplusplus } diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index 5f4521a2d..7c5461273 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -500,7 +500,7 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) } #endif -int winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv) +BOOL winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv) { #if defined(WITH_OPENSSL) int operation; @@ -508,13 +508,13 @@ int winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key evp = winpr_openssl_get_evp_cipher(cipher); if (!evp) - return -1; + return FALSE; operation = (op == WINPR_ENCRYPT) ? 1 : 0; EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*) ctx); if (EVP_CipherInit_ex((EVP_CIPHER_CTX*) ctx, evp, NULL, key, iv, operation) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) int key_bitlen; mbedtls_operation_t operation; @@ -524,55 +524,55 @@ int winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (!cipher_info) - return -1; + return FALSE; operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; mbedtls_cipher_init((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setup((mbedtls_cipher_context_t*) ctx, cipher_info) != 0) - return -1; + return FALSE; key_bitlen = mbedtls_cipher_get_key_bitlen((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setkey((mbedtls_cipher_context_t*) ctx, key, key_bitlen, operation) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen) +BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen) { #if defined(WITH_OPENSSL) int outl = (int) *olen; if (EVP_CipherUpdate((EVP_CIPHER_CTX*) ctx, output, &outl, input, ilen) != 1) - return -1; + return FALSE; *olen = (size_t) outl; #elif defined(WITH_MBEDTLS) if (mbedtls_cipher_update((mbedtls_cipher_context_t*) ctx, input, ilen, output, olen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) +BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) { #if defined(WITH_OPENSSL) int outl = (int) *olen; if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) != 1) - return -1; + return FALSE; EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx); *olen = (size_t) outl; #elif defined(WITH_MBEDTLS) if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) != 0) - return -1; + return FALSE; mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx); #endif - return 0; + return TRUE; } /** diff --git a/winpr/libwinpr/crypto/hash.c b/winpr/libwinpr/crypto/hash.c index 8b5e11599..9761d7893 100644 --- a/winpr/libwinpr/crypto/hash.c +++ b/winpr/libwinpr/crypto/hash.c @@ -68,8 +68,11 @@ BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen) return TRUE; } -BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output) +BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen) { + if (ilen < WINPR_MD5_DIGEST_LENGTH) + return FALSE; + #if defined(WITH_OPENSSL) if (MD5_Final(output, (MD5_CTX*) ctx) != 1) return FALSE; @@ -81,7 +84,7 @@ BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output) return TRUE; } -BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_MD5_CTX ctx; @@ -89,7 +92,7 @@ BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output) return FALSE; if (!winpr_MD5_Update(&ctx, input, ilen)) return FALSE; - return winpr_MD5_Final(&ctx, output); + return winpr_MD5_Final(&ctx, output, olen); } /** @@ -120,8 +123,11 @@ BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen) return TRUE; } -BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output) +BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t olen) { + if (olen < WINPR_MD4_DIGEST_LENGTH) + return FALSE; + #if defined(WITH_OPENSSL) if (MD4_Final(output, (MD4_CTX*) ctx) != 1) return FALSE; @@ -133,7 +139,7 @@ BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output) return TRUE; } -BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_MD4_CTX ctx; @@ -141,7 +147,7 @@ BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output) return FALSE; if (!winpr_MD4_Update(&ctx, input, ilen)) return FALSE; - return winpr_MD4_Final(&ctx, output); + return winpr_MD4_Final(&ctx, output, olen); } /** @@ -173,8 +179,11 @@ BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen) return TRUE; } -BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output) +BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t olen) { + if (olen < WINPR_SHA1_DIGEST_LENGTH) + return FALSE; + #if defined(WITH_OPENSSL) if (SHA1_Final(output, (SHA_CTX*) ctx) != 1) return FALSE; @@ -186,7 +195,7 @@ BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output) return TRUE; } -BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_SHA1_CTX ctx; @@ -194,7 +203,7 @@ BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output) return FALSE; if (!winpr_SHA1_Update(&ctx, input, ilen)) return FALSE; - return winpr_SHA1_Final(&ctx, output); + return winpr_SHA1_Final(&ctx, output, olen); } /** @@ -299,13 +308,13 @@ mbedtls_md_type_t winpr_mbedtls_get_md_type(int md) } #endif -int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen) +BOOL winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, WINPR_MD_TYPE md, const BYTE* key, size_t keylen) { #if defined(WITH_OPENSSL) const EVP_MD* evp = winpr_openssl_get_evp_md(md); if (!evp) - return -1; + return FALSE; HMAC_CTX_init((HMAC_CTX*) ctx); @@ -313,7 +322,7 @@ int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen) HMAC_Init_ex((HMAC_CTX*) ctx, key, keylen, evp, NULL); #else if (HMAC_Init_ex((HMAC_CTX*) ctx, key, keylen, evp, NULL) != 1) - return -1; + return FALSE; #endif #elif defined(WITH_MBEDTLS) @@ -322,143 +331,150 @@ int winpr_HMAC_Init(WINPR_HMAC_CTX* ctx, int md, const BYTE* key, size_t keylen) md_info = mbedtls_md_info_from_type(md_type); if (!md_info) - return -1; + return FALSE; mbedtls_md_init((mbedtls_md_context_t*) ctx); if (mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 1) != 0) - return -1; + return FALSE; if (mbedtls_md_hmac_starts((mbedtls_md_context_t*) ctx, key, keylen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) #if (OPENSSL_VERSION_NUMBER < 0x10000000L) HMAC_Update((HMAC_CTX*) ctx, input, ilen); #else if (HMAC_Update((HMAC_CTX*) ctx, input, ilen) != 1) - return -1; + return FALSE; #endif #elif defined(WITH_MBEDTLS) if (mbedtls_md_hmac_update((mbedtls_md_context_t*) ctx, input, ilen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output) +BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen) { + /* TODO + if (olen < ctx->digestLength) + return FALSE; + */ + #if defined(WITH_OPENSSL) #if (OPENSSL_VERSION_NUMBER < 0x10000000L) HMAC_Final((HMAC_CTX*) ctx, output, NULL); #else if (HMAC_Final((HMAC_CTX*) ctx, output, NULL) != 1) - return -1; + return FALSE; #endif HMAC_CTX_cleanup((HMAC_CTX*) ctx); #elif defined(WITH_MBEDTLS) if (mbedtls_md_hmac_finish((mbedtls_md_context_t*) ctx, output) != 0) - return -1; + return FALSE; mbedtls_md_free((mbedtls_md_context_t*) ctx); #endif - return 0; + return TRUE; } -int winpr_HMAC(int md, const BYTE* key, size_t keylen, const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, + const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_HMAC_CTX ctx; - if (winpr_HMAC_Init(&ctx, md, key, keylen) != 0) - return -1; + if (!winpr_HMAC_Init(&ctx, md, key, keylen)) + return FALSE; - if (winpr_HMAC_Update(&ctx, input, ilen) != 0) - return -1; + if (!winpr_HMAC_Update(&ctx, input, ilen)) + return FALSE; - if (winpr_HMAC_Final(&ctx, output) != 0) - return -1; + if (!winpr_HMAC_Final(&ctx, output, olen)) + return FALSE; - return 0; + return TRUE; } /** * Generic Digest API */ -int winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, int md) +BOOL winpr_Digest_Init(WINPR_DIGEST_CTX* ctx, WINPR_MD_TYPE md) { #if defined(WITH_OPENSSL) const EVP_MD* evp = winpr_openssl_get_evp_md(md); if (!evp) - return -1; + return FALSE; EVP_MD_CTX_init((EVP_MD_CTX*) ctx); if (EVP_DigestInit_ex((EVP_MD_CTX*) ctx, evp, NULL) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) const mbedtls_md_info_t* md_info; mbedtls_md_type_t md_type = winpr_mbedtls_get_md_type(md); md_info = mbedtls_md_info_from_type(md_type); if (!md_info) - return -1; + return FALSE; mbedtls_md_init((mbedtls_md_context_t*) ctx); if (mbedtls_md_setup((mbedtls_md_context_t*) ctx, md_info, 0) != 0) - return -1; + return FALSE; if (mbedtls_md_starts((mbedtls_md_context_t*) ctx) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen) +BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) if (EVP_DigestUpdate((EVP_MD_CTX*) ctx, input, ilen) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) if (mbedtls_md_update((mbedtls_md_context_t*) ctx, input, ilen) != 0) - return -1; + return FALSE; #endif - return 0; + return TRUE; } -int winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output) +BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen) { + // TODO: output length check #if defined(WITH_OPENSSL) if (EVP_DigestFinal_ex((EVP_MD_CTX*) ctx, output, NULL) != 1) - return -1; + return FALSE; #elif defined(WITH_MBEDTLS) if (mbedtls_md_finish((mbedtls_md_context_t*) ctx, output) != 0) - return -1; + return FALSE; mbedtls_md_free((mbedtls_md_context_t*) ctx); #endif - return 0; + return TRUE; } -int winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output) +BOOL winpr_Digest(int md, const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_DIGEST_CTX ctx; - if (winpr_Digest_Init(&ctx, md) != 0) - return -1; + if (!winpr_Digest_Init(&ctx, md)) + return FALSE; - if (winpr_Digest_Update(&ctx, input, ilen) != 0) - return -1; + if (!winpr_Digest_Update(&ctx, input, ilen)) + return FALSE; - if (winpr_Digest_Final(&ctx, output) != 0) - return -1; + if (!winpr_Digest_Final(&ctx, output, olen)) + return FALSE; - return 0; + return TRUE; } diff --git a/winpr/libwinpr/crypto/test/TestCryptoHash.c b/winpr/libwinpr/crypto/test/TestCryptoHash.c index 8178469ac..ec6d5ad6d 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoHash.c +++ b/winpr/libwinpr/crypto/test/TestCryptoHash.c @@ -8,20 +8,23 @@ static const BYTE* TEST_MD5_HASH = (BYTE*) "\x09\x8f\x6b\xcd\x46\x21\xd3\x73\xca BOOL test_crypto_hash_md5() { - BYTE hash[16]; + BYTE hash[WINPR_MD5_DIGEST_LENGTH]; WINPR_MD5_CTX ctx; - winpr_MD5_Init(&ctx); - winpr_MD5_Update(&ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA)); - winpr_MD5_Final(&ctx, hash); + if (!winpr_MD5_Init(&ctx)) + return FALSE; + if (!winpr_MD5_Update(&ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA))) + return FALSE; + if (!winpr_MD5_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_MD5_HASH, 16) != 0) + if (memcmp(hash, TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 16, FALSE); - expected = winpr_BinToHexString(TEST_MD5_HASH, 16, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected MD5 hash: Actual: %s Expected: %s\n", actual, expected); @@ -39,20 +42,23 @@ static const BYTE* TEST_MD4_HASH = (BYTE*) "\xdb\x34\x6d\x69\x1d\x7a\xcc\x4d\xc2 BOOL test_crypto_hash_md4() { - BYTE hash[16]; + BYTE hash[WINPR_MD4_DIGEST_LENGTH]; WINPR_MD4_CTX ctx; - winpr_MD4_Init(&ctx); - winpr_MD4_Update(&ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA)); - winpr_MD4_Final(&ctx, hash); + if (!winpr_MD4_Init(&ctx)) + return FALSE; + if (!winpr_MD4_Update(&ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA))) + return FALSE; + if (!winpr_MD4_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_MD4_HASH, 16) != 0) + if (memcmp(hash, TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 16, FALSE); - expected = winpr_BinToHexString(TEST_MD4_HASH, 16, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD4_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected MD4 hash: Actual: %s Expected: %s\n", actual, expected); @@ -70,20 +76,23 @@ static const BYTE* TEST_SHA1_HASH = (BYTE*) "\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1 BOOL test_crypto_hash_sha1() { - BYTE hash[20]; + BYTE hash[WINPR_SHA1_DIGEST_LENGTH]; WINPR_SHA1_CTX ctx; - winpr_SHA1_Init(&ctx); - winpr_SHA1_Update(&ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA)); - winpr_SHA1_Final(&ctx, hash); + if (!winpr_SHA1_Init(&ctx)) + return FALSE; + if (!winpr_SHA1_Update(&ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA))) + return FALSE; + if (!winpr_SHA1_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_SHA1_HASH, 20) != 0) + if (memcmp(hash, TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 20, FALSE); - expected = winpr_BinToHexString(TEST_SHA1_HASH, 20, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected SHA1 hash: Actual: %s Expected: %s\n", actual, expected); @@ -102,20 +111,23 @@ static const BYTE* TEST_HMAC_MD5_HASH = (BYTE*) "\x92\x94\x72\x7a\x36\x38\xbb\x1 BOOL test_crypto_hash_hmac_md5() { - BYTE hash[16]; + BYTE hash[WINPR_MD5_DIGEST_LENGTH]; WINPR_HMAC_CTX ctx; - winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, 16); - winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA)); - winpr_HMAC_Final(&ctx, hash); + if (!winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA))) + return FALSE; + if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_HMAC_MD5_HASH, 16) != 0) + if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 16, FALSE); - expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, 16, FALSE); + actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected HMAC-MD5 hash: Actual: %s Expected: %s\n", actual, expected); @@ -134,20 +146,23 @@ static const BYTE* TEST_HMAC_SHA1_HASH = (BYTE*) "\xb6\x17\x31\x86\x55\x05\x72\x BOOL test_crypto_hash_hmac_sha1() { - BYTE hash[20]; + BYTE hash[WINPR_SHA1_DIGEST_LENGTH]; WINPR_HMAC_CTX ctx; - winpr_HMAC_Init(&ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, 20); - winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA)); - winpr_HMAC_Final(&ctx, hash); + if (!winpr_HMAC_Init(&ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH)) + return FALSE; + if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA))) + return FALSE; + if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) + return FALSE; - if (memcmp(hash, TEST_HMAC_SHA1_HASH, 20) != 0) + if (memcmp(hash, TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, 20, FALSE); - expected = winpr_BinToHexString(TEST_HMAC_SHA1_HASH, 20, FALSE); + actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected HMAC-SHA1 hash: Actual: %s Expected: %s\n", actual, expected); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 2a7beb0b5..99d63dd2e 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -889,7 +889,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, int length; void* data; UINT32 SeqNo; - BYTE digest[16]; + BYTE digest[WINPR_MD5_DIGEST_LENGTH]; BYTE checksum[8]; BYTE* signature; ULONG version = 1; @@ -923,10 +923,10 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, CopyMemory(data, data_buffer->pvBuffer, length); /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ - winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->SendSigningKey, 16); + winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH); winpr_HMAC_Update(&hmac, (void*) &(SeqNo), 4); winpr_HMAC_Update(&hmac, (void*) data, length); - winpr_HMAC_Final(&hmac, digest); + winpr_HMAC_Final(&hmac, digest, WINPR_MD5_DIGEST_LENGTH); /* Encrypt message using with RC4, result overwrites original buffer */ @@ -963,12 +963,12 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD int length; void* data; UINT32 SeqNo; - BYTE digest[16]; + BYTE digest[WINPR_MD5_DIGEST_LENGTH]; BYTE checksum[8]; UINT32 version = 1; WINPR_HMAC_CTX hmac; NTLM_CONTEXT* context; - BYTE expected_signature[16]; + BYTE expected_signature[WINPR_MD5_DIGEST_LENGTH]; PSecBuffer data_buffer = NULL; PSecBuffer signature_buffer = NULL; SeqNo = (UINT32) MessageSeqNo; @@ -1005,10 +1005,10 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD CopyMemory(data_buffer->pvBuffer, data, length); /* Compute the HMAC-MD5 hash of ConcatenationOf(seq_num,data) using the client signing key */ - winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->RecvSigningKey, 16); + winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH); winpr_HMAC_Update(&hmac, (void*) &(SeqNo), 4); winpr_HMAC_Update(&hmac, (void*) data_buffer->pvBuffer, data_buffer->cbBuffer); - winpr_HMAC_Final(&hmac, digest); + winpr_HMAC_Final(&hmac, digest, WINPR_MD5_DIGEST_LENGTH); #ifdef WITH_DEBUG_NTLM WLog_DBG(TAG, "Encrypted Data Buffer (length = %d)", length); winpr_HexDump(TAG, WLOG_DEBUG, data, length); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c index d3b980222..96d37384a 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c @@ -260,7 +260,7 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) UINT32 ChannelBindingTokenLength; SEC_CHANNEL_BINDINGS* ChannelBindings; - ZeroMemory(context->ChannelBindingsHash, 16); + ZeroMemory(context->ChannelBindingsHash, WINPR_MD5_DIGEST_LENGTH); ChannelBindings = context->Bindings.Bindings; if (!ChannelBindings) @@ -275,7 +275,7 @@ void ntlm_compute_channel_bindings(NTLM_CONTEXT* context) ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbAcceptorLength); ntlm_md5_update_uint32_be(&md5, ChannelBindings->cbApplicationDataLength); winpr_MD5_Update(&md5, (void*) ChannelBindingToken, ChannelBindingTokenLength); - winpr_MD5_Final(&md5, context->ChannelBindingsHash); + winpr_MD5_Final(&md5, context->ChannelBindingsHash, WINPR_MD5_DIGEST_LENGTH); } void ntlm_compute_single_host_data(NTLM_CONTEXT* context) diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index b2973c4ac..b341dbca8 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -315,7 +315,7 @@ int ntlm_compute_ntlm_v2_hash(NTLM_CONTEXT* context, BYTE* hash) int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) { BYTE* response; - BYTE value[16]; + BYTE value[WINPR_MD5_DIGEST_LENGTH]; if (context->LmCompatibilityLevel < 2) { @@ -340,7 +340,9 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) response = (BYTE*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ - winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, 16, (BYTE*) value, 16, (BYTE*) response); + winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) response, WINPR_MD5_DIGEST_LENGTH); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); return 1; @@ -356,7 +358,7 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) { BYTE* blob; - BYTE nt_proof_str[16]; + BYTE nt_proof_str[WINPR_MD5_DIGEST_LENGTH]; SecBuffer ntlm_v2_temp; SecBuffer ntlm_v2_temp_chal; PSecBuffer TargetInfo; @@ -385,7 +387,7 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) WLog_DBG(TAG, "Workstation (length = %d)", context->Workstation.Length); winpr_HexDump(TAG, WLOG_DEBUG, (BYTE*) context->Workstation.Buffer, context->Workstation.Length); WLog_DBG(TAG, "NTOWFv2, NTLMv2 Hash"); - winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, 16); + winpr_HexDump(TAG, WLOG_DEBUG, context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH); #endif /* Construct temp */ blob[0] = 1; /* RespType (1 byte) */ @@ -409,8 +411,9 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) blob = (BYTE*) ntlm_v2_temp_chal.pvBuffer; CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); - winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, 16, (BYTE*) ntlm_v2_temp_chal.pvBuffer, - ntlm_v2_temp_chal.cbBuffer, (BYTE*) nt_proof_str); + winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ @@ -421,7 +424,9 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(blob, nt_proof_str, 16); CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ - winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, 16, (BYTE*) nt_proof_str, 16, (BYTE*) context->SessionBaseKey); + winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); return 1; @@ -544,18 +549,18 @@ int ntlm_generate_signing_key(BYTE* exported_session_key, PSecBuffer sign_magic, BYTE* value; WINPR_MD5_CTX md5; - length = 16 + sign_magic->cbBuffer; + length = WINPR_MD5_DIGEST_LENGTH + sign_magic->cbBuffer; value = (BYTE*) malloc(length); if (!value) return -1; /* Concatenate ExportedSessionKey with sign magic */ - CopyMemory(value, exported_session_key, 16); - CopyMemory(&value[16], sign_magic->pvBuffer, sign_magic->cbBuffer); + CopyMemory(value, exported_session_key, WINPR_MD5_DIGEST_LENGTH); + CopyMemory(&value[WINPR_MD5_DIGEST_LENGTH], sign_magic->pvBuffer, sign_magic->cbBuffer); winpr_MD5_Init(&md5); winpr_MD5_Update(&md5, value, length); - winpr_MD5_Final(&md5, signing_key); + winpr_MD5_Final(&md5, signing_key, WINPR_MD5_DIGEST_LENGTH); free(value); return 1; } @@ -602,16 +607,16 @@ int ntlm_generate_sealing_key(BYTE* exported_session_key, PSecBuffer seal_magic, WINPR_MD5_CTX md5; SecBuffer buffer; - if (!sspi_SecBufferAlloc(&buffer, 16 + seal_magic->cbBuffer)) + if (!sspi_SecBufferAlloc(&buffer, WINPR_MD5_DIGEST_LENGTH + seal_magic->cbBuffer)) return -1; p = (BYTE*) buffer.pvBuffer; /* Concatenate ExportedSessionKey with seal magic */ - CopyMemory(p, exported_session_key, 16); - CopyMemory(&p[16], seal_magic->pvBuffer, seal_magic->cbBuffer); + CopyMemory(p, exported_session_key, WINPR_MD5_DIGEST_LENGTH); + CopyMemory(&p[WINPR_MD5_DIGEST_LENGTH], seal_magic->pvBuffer, seal_magic->cbBuffer); winpr_MD5_Init(&md5); winpr_MD5_Update(&md5, buffer.pvBuffer, buffer.cbBuffer); - winpr_MD5_Final(&md5, sealing_key); + winpr_MD5_Final(&md5, sealing_key, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&buffer); return 1; } @@ -679,9 +684,9 @@ void ntlm_compute_message_integrity_check(NTLM_CONTEXT* context) * CHALLENGE_MESSAGE, AUTHENTICATE_MESSAGE) using the ExportedSessionKey */ - winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->ExportedSessionKey, 16); + winpr_HMAC_Init(&hmac, WINPR_MD_MD5, context->ExportedSessionKey, WINPR_MD5_DIGEST_LENGTH); winpr_HMAC_Update(&hmac, (BYTE*) context->NegotiateMessage.pvBuffer, context->NegotiateMessage.cbBuffer); winpr_HMAC_Update(&hmac, (BYTE*) context->ChallengeMessage.pvBuffer, context->ChallengeMessage.cbBuffer); winpr_HMAC_Update(&hmac, (BYTE*) context->AuthenticateMessage.pvBuffer, context->AuthenticateMessage.cbBuffer); - winpr_HMAC_Final(&hmac, context->MessageIntegrityCheck); + winpr_HMAC_Final(&hmac, context->MessageIntegrityCheck, WINPR_MD5_DIGEST_LENGTH); } diff --git a/winpr/libwinpr/utils/ntlm.c b/winpr/libwinpr/utils/ntlm.c index 709d4d89c..be1deaedc 100644 --- a/winpr/libwinpr/utils/ntlm.c +++ b/winpr/libwinpr/utils/ntlm.c @@ -42,9 +42,12 @@ BYTE* NTOWFv1W(LPWSTR Password, UINT32 PasswordLength, BYTE* NtHash) if (!NtHash && !(NtHash = malloc(16))) return NULL; - winpr_MD4_Init(&md4); - winpr_MD4_Update(&md4, (BYTE*) Password, (size_t) PasswordLength); - winpr_MD4_Final(&md4, NtHash); + if (!winpr_MD4_Init(&md4)) + return NULL; + if (!winpr_MD4_Update(&md4, (BYTE*) Password, (size_t) PasswordLength)) + return NULL; + if (!winpr_MD4_Final(&md4, NtHash, WINPR_MD4_DIGEST_LENGTH)) + return NULL; return NtHash; } @@ -77,11 +80,12 @@ BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, { BYTE* buffer; BYTE NtHashV1[16]; + BYTE* result = NtHash; if ((!User) || (!Password)) return NULL; - if (!NtHash && !(NtHash = (BYTE*) malloc(16))) + if (!NtHash && !(NtHash = (BYTE*) malloc(WINPR_MD4_DIGEST_LENGTH))) return NULL; if (!NTOWFv1W(Password, PasswordLength, NtHashV1)) @@ -103,11 +107,12 @@ BYTE* NTOWFv2W(LPWSTR Password, UINT32 PasswordLength, LPWSTR User, CopyMemory(&buffer[UserLength], Domain, DomainLength); /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ - winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash); + if (!winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash, WINPR_MD4_DIGEST_LENGTH)) + result = NULL; free(buffer); - return NtHash; + return result; } BYTE* NTOWFv2A(LPSTR Password, UINT32 PasswordLength, LPSTR User, @@ -141,11 +146,12 @@ out_fail: BYTE* NTOWFv2FromHashW(BYTE* NtHashV1, LPWSTR User, UINT32 UserLength, LPWSTR Domain, UINT32 DomainLength, BYTE* NtHash) { BYTE* buffer; + BYTE* result = NtHash; if (!User) return NULL; - if (!NtHash && !(NtHash = (BYTE*) malloc(16))) + if (!NtHash && !(NtHash = (BYTE*) malloc(WINPR_MD4_DIGEST_LENGTH))) return NULL; if (!(buffer = (BYTE*) malloc(UserLength + DomainLength))) @@ -165,11 +171,12 @@ BYTE* NTOWFv2FromHashW(BYTE* NtHashV1, LPWSTR User, UINT32 UserLength, LPWSTR Do } /* Compute the HMAC-MD5 hash of the above value using the NTLMv1 hash as the key, the result is the NTLMv2 hash */ - winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash); + if (!winpr_HMAC(WINPR_MD_MD5, NtHashV1, 16, buffer, UserLength + DomainLength, NtHash, WINPR_MD4_DIGEST_LENGTH)) + result = NULL; free(buffer); - return NtHash; + return result; } BYTE* NTOWFv2FromHashA(BYTE* NtHashV1, LPSTR User, UINT32 UserLength, LPSTR Domain, UINT32 DomainLength, BYTE* NtHash) From 2b18d257317df63dcdc7d01b16fd37f8e96f6fc9 Mon Sep 17 00:00:00 2001 From: David FORT Date: Thu, 25 Feb 2016 00:41:19 +0100 Subject: [PATCH 062/128] Added some checks --- client/Wayland/wlfreerdp.c | 7 ++++++- uwac/libuwac/uwac-input.c | 2 ++ uwac/libuwac/uwac-window.c | 4 ++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c index 6c61ae4da..308147cab 100644 --- a/client/Wayland/wlfreerdp.c +++ b/client/Wayland/wlfreerdp.c @@ -92,6 +92,9 @@ static BOOL wl_end_paint(rdpContext* context) context_w = (wlfContext*) context; data = UwacWindowGetDrawingBuffer(context_w->window); + if (!data) + return FALSE; + for (i = 0; i < h; i++) { memcpy(data + ((i+y)*(gdi->width*4)) + x*4, @@ -99,7 +102,9 @@ static BOOL wl_end_paint(rdpContext* context) w*4); } - UwacWindowAddDamage(context_w->window, x, y, w, h); + if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS) + return FALSE; + context_w->haveDamage = TRUE; return wl_update_content(context_w); } diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c index 20d0ad01a..76e2f5ec4 100644 --- a/uwac/libuwac/uwac-input.c +++ b/uwac/libuwac/uwac-input.c @@ -742,6 +742,8 @@ seat_handle_name(void *data, struct wl_seat *seat, const char *name) free(input->name); input->name = strdup(name); + if (!input->name) + assert(uwacErrorHandler(input->display, UWAC_ERROR_NOMEMORY, "unable to strdup seat's name\n")); } static const struct wl_seat_listener seat_listener = { diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c index fa3b860ea..b3fd370ad 100644 --- a/uwac/libuwac/uwac-window.c +++ b/uwac/libuwac/uwac-window.c @@ -296,6 +296,10 @@ int UwacWindowShmAllocBuffers(UwacWindow *w, int nbuffers, int allocSize, uint32 } pool = wl_shm_create_pool(w->display->shm, fd, allocSize * nbuffers); + if (!pool) { + ret = UWAC_ERROR_NOMEMORY; + goto error_mmap; + } for (i = 0; i < nbuffers; i++) { UwacBuffer *buffer = &w->buffers[w->nbuffers + i]; From fd415cd10ae6829de4485d837d238aaad9b4d65f Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 25 Feb 2016 09:02:46 +0100 Subject: [PATCH 063/128] Fixed missing semicolon. --- libfreerdp/core/timezone.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/libfreerdp/core/timezone.c b/libfreerdp/core/timezone.c index 637afa64e..48374fe58 100644 --- a/libfreerdp/core/timezone.c +++ b/libfreerdp/core/timezone.c @@ -82,15 +82,15 @@ BOOL rdp_read_client_time_zone(wStream* s, rdpSettings* settings) { LPTIME_ZONE_INFORMATION tz; - if (!s || !settings) - return FALSE; + if (!s || !settings) + return FALSE; if (Stream_GetRemainingLength(s) < 172) return FALSE; tz = settings->ClientTimeZone; - if (!tz) - return FALSE; + if (!tz) + return FALSE; Stream_Read_UINT32(s, tz->Bias); /* Bias */ @@ -122,8 +122,8 @@ BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings) DWORD rc; tz = settings->ClientTimeZone; - if (!tz) - return FALSE; + if (!tz) + return FALSE; rc = GetTimeZoneInformation(tz); @@ -137,7 +137,7 @@ BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings) rdp_write_system_time(s, &tz->StandardDate); DEBUG_TIMEZONE("bias=%d stdName='%s' dlName='%s'", tz->Bias, - tz->StandardName, tz->DaylightName); + tz->StandardName, tz->DaylightName); /* Note that StandardBias is ignored if no valid standardDate is provided. */ /* StandardBias */ @@ -155,6 +155,6 @@ BOOL rdp_write_client_time_zone(wStream* s, rdpSettings* settings) Stream_Write_UINT32(s, tz->DaylightBias); DEBUG_TIMEZONE("DaylightBias=%d", tz->DaylightBias); - return TRUE + return TRUE; } From aa7fe1d3139ad2259c6b4559ec2369a19095eb2f Mon Sep 17 00:00:00 2001 From: David FORT Date: Thu, 25 Feb 2016 15:03:14 +0100 Subject: [PATCH 064/128] Fixed indentation --- include/freerdp/session.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/freerdp/session.h b/include/freerdp/session.h index 3d81f4a7c..9d7ed5198 100644 --- a/include/freerdp/session.h +++ b/include/freerdp/session.h @@ -22,7 +22,7 @@ #include /* Logon Information Types */ -#define INFO_TYPE_LOGON 0x00000000 +#define INFO_TYPE_LOGON 0x00000000 #define INFO_TYPE_LOGON_LONG 0x00000001 #define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002 #define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003 From ae6c235be71cafb31dbcfbe0179288ffb21a57b8 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 25 Feb 2016 16:31:20 +0100 Subject: [PATCH 065/128] android: disable mips build mips build causes problems when building openssl during integration builds. Disable it for now --- scripts/android-build.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/android-build.conf b/scripts/android-build.conf index 4d26f9407..fff1ab298 100644 --- a/scripts/android-build.conf +++ b/scripts/android-build.conf @@ -19,4 +19,4 @@ BUILD_SRC=$SRC_DIR/build CMAKE_BUILD_TYPE=Debug -BUILD_ARCH="armeabi armeabi-v7a x86 mips" +BUILD_ARCH="armeabi armeabi-v7a x86" From b61ab5ecb75ac910be92d515ec8006cc94da4bde Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 25 Feb 2016 19:37:20 +0100 Subject: [PATCH 066/128] Fixed stream copy in update_message_SurfaceCommand --- libfreerdp/core/message.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/libfreerdp/core/message.c b/libfreerdp/core/message.c index adc0e0f49..4692b00e5 100644 --- a/libfreerdp/core/message.c +++ b/libfreerdp/core/message.c @@ -188,19 +188,12 @@ static BOOL update_message_SurfaceCommand(rdpContext* context, wStream* s) { wStream* wParam; - wParam = (wStream*) malloc(sizeof(wStream)); + wParam = Stream_New(NULL, Stream_GetRemainingLength(s)); if (!wParam) return FALSE; - wParam->capacity = Stream_Capacity(s); - wParam->buffer = (BYTE*) malloc(wParam->capacity); - if (!wParam->buffer) - { - free(wParam); - return FALSE; - } - - wParam->pointer = wParam->buffer; + Stream_Copy(wParam, s, Stream_Capacity(s)); + Stream_SetPosition(wParam, 0); return MessageQueue_Post(context->update->queue, (void*) context, MakeMessageId(Update, SurfaceCommand), (void*) wParam, NULL); @@ -2058,7 +2051,7 @@ int update_message_free_pointer_update_class(wMessage* msg, int type) free(wParam); } break; - + case PointerUpdate_PointerNew: { POINTER_NEW_UPDATE* wParam = (POINTER_NEW_UPDATE*) msg->wParam; @@ -2091,11 +2084,11 @@ static int update_message_process_pointer_update_class(rdpUpdateProxy* proxy, wM break; case PointerUpdate_PointerColor: - IFCALL(proxy->PointerColor, msg->context, (POINTER_COLOR_UPDATE*) msg->wParam); + IFCALL(proxy->PointerColor, msg->context, (POINTER_COLOR_UPDATE*) msg->wParam); break; case PointerUpdate_PointerNew: - IFCALL(proxy->PointerNew, msg->context, (POINTER_NEW_UPDATE*) msg->wParam); + IFCALL(proxy->PointerNew, msg->context, (POINTER_NEW_UPDATE*) msg->wParam); break; case PointerUpdate_PointerCached: @@ -2220,7 +2213,7 @@ int update_message_queue_free_message(wMessage *message) int msgType; assert(message); - + if (message->id == WMQ_QUIT) return 0; From e79eee2bb1a09b103d418d37b56fba745c9bc7c1 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 25 Feb 2016 20:01:12 +0100 Subject: [PATCH 067/128] Fixed Stream API misuse. --- libfreerdp/core/capabilities.c | 8 ++++---- libfreerdp/core/gateway/http.c | 2 +- libfreerdp/core/gcc.c | 6 +++--- libfreerdp/core/mcs.c | 4 ++-- libfreerdp/core/orders.c | 4 ++-- libfreerdp/core/rdp.c | 2 +- libfreerdp/core/transport.c | 3 +-- server/Sample/sfreerdp.c | 6 +++--- 8 files changed, 17 insertions(+), 18 deletions(-) diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 114cfd2ee..d6e46e810 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -3392,10 +3392,10 @@ BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOOL recei break; } - if (s->pointer != em) + if (Stream_Pointer(s) != em) { WLog_ERR(TAG, "incorrect offset, type:0x%02X actual:%d expected:%d", - type, (int)(s->pointer - bm), (int)(em - bm)); + type, (int)(Stream_Pointer(s) - bm), (int)(em - bm)); } Stream_SetPointer(s, em); @@ -3617,10 +3617,10 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa } } - if (s->pointer != em) + if (Stream_Pointer(s) != em) { WLog_ERR(TAG, "incorrect offset, type:0x%02X actual:%d expected:%d", - type, (int)(s->pointer - bm), (int)(em - bm)); + type, (int)(Stream_Pointer(s) - bm), (int)(em - bm)); } Stream_SetPointer(s, em); diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c index f12423f93..a3d5da350 100644 --- a/libfreerdp/core/gateway/http.c +++ b/libfreerdp/core/gateway/http.c @@ -407,7 +407,7 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request) free(lines); Stream_Write(s, "\0", 1); /* append null terminator */ Stream_Rewind(s, 1); /* don't include null terminator in length */ - Stream_Length(s) = Stream_GetPosition(s); + Stream_SetLength(s, Stream_GetPosition(s)); return s; out_free: diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index c2354423e..b0a0f1b0f 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -225,7 +225,7 @@ void gcc_write_conference_create_request(wStream* s, wStream* userData) per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */ /* userData::value (OCTET_STRING) */ - per_write_octet_string(s, userData->buffer, Stream_GetPosition(userData), 0); /* array of client data blocks */ + per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData), 0); /* array of client data blocks */ } BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs) @@ -319,7 +319,7 @@ void gcc_write_conference_create_response(wStream* s, wStream* userData) per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */ /* userData (OCTET_STRING) */ - per_write_octet_string(s, userData->buffer, Stream_GetPosition(userData), 0); /* array of server data blocks */ + per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData), 0); /* array of server data blocks */ } BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length) @@ -508,7 +508,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length) break; } offset += blockLength; - Stream_Pointer(s) = holdp + blockLength; + Stream_SetPointer(s, holdp + blockLength); } return TRUE; diff --git a/libfreerdp/core/mcs.c b/libfreerdp/core/mcs.c index 8d082b155..27c9126c6 100644 --- a/libfreerdp/core/mcs.c +++ b/libfreerdp/core/mcs.c @@ -571,7 +571,7 @@ BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData) goto out; /* userData (OCTET_STRING) */ - ber_write_octet_string(tmps, userData->buffer, Stream_GetPosition(userData)); + ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData)); length = Stream_GetPosition(tmps); /* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */ @@ -608,7 +608,7 @@ BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData) if (!mcs_write_domain_parameters(tmps, &(mcs->domainParameters))) goto out; /* userData (OCTET_STRING) */ - ber_write_octet_string(tmps, userData->buffer, Stream_GetPosition(userData)); + ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData)); length = Stream_GetPosition(tmps); ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length); diff --git a/libfreerdp/core/orders.c b/libfreerdp/core/orders.c index 60aed90b8..49df89add 100644 --- a/libfreerdp/core/orders.c +++ b/libfreerdp/core/orders.c @@ -1728,7 +1728,7 @@ BOOL update_read_fast_glyph_order(wStream* s, ORDER_INFO* orderInfo, FAST_GLYPH_ } } - Stream_Pointer(s) = phold + fastGlyph->cbData; + Stream_SetPointer(s, phold + fastGlyph->cbData); } return TRUE; @@ -3546,7 +3546,7 @@ BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags) break; } - Stream_Pointer(s) = next; + Stream_SetPointer(s, next); return TRUE; } diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index dfaa02dbf..37dc8ee26 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1056,7 +1056,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags) return FALSE; /* TODO */ } - Stream_Length(s) -= pad; + Stream_SetLength(s, Stream_Length(s) - pad); return TRUE; } diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index 6f928cca1..147913f82 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -733,8 +733,7 @@ out_cleanup: transport->layer = TRANSPORT_LAYER_CLOSED; } - if (s->pool) - Stream_Release(s); + Stream_Release(s); LeaveCriticalSection(&(transport->WriteLock)); return status; diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index ba2cf9ecc..96b6c9c4b 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -449,12 +449,12 @@ BOOL tf_peer_dump_rfx(freerdp_peer* client) if (!tmp) break; - Stream_Buffer(s) = tmp; + Stream_SetBuffer(s, tmp); record.data = Stream_Buffer(s); - Stream_Capacity(s) = record.length; + Stream_SetCapacity(s, record.length); pcap_get_next_record_content(pcap_rfx, &record); - Stream_Pointer(s) = Stream_Buffer(s) + Stream_Capacity(s); + Stream_SetPointer(s, Stream_Buffer(s) + Stream_Capacity(s)); if (test_dump_rfx_realtime && test_sleep_tsdiff(&prev_seconds, &prev_useconds, record.header.ts_sec, record.header.ts_usec) == FALSE) break; From cf9543e3507ed4c4661f56add487372c8b79ce79 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 25 Feb 2016 20:13:56 +0100 Subject: [PATCH 068/128] Converted Stream defines to inline functions. Using inline functions allows compiler type checks --- winpr/include/winpr/stream.h | 343 +++++++++++++++++++++++------------ 1 file changed, 225 insertions(+), 118 deletions(-) diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index 2e9f89f27..a9abb78c5 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -50,35 +50,59 @@ WINPR_API BOOL Stream_EnsureRemainingCapacity(wStream* s, size_t size); WINPR_API wStream* Stream_New(BYTE* buffer, size_t size); WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); -#define _stream_read_n8(_t, _s, _v, _p) do { _v = \ - (_t)(*_s->pointer); \ - _s->pointer += _p; } while (0) +static INLINE void Stream_Seek(wStream* s, size_t _offset) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->pointer += (_offset); +} -#define _stream_read_n16_le(_t, _s, _v, _p) do { _v = \ +static INLINE void Stream_Rewind(wStream* s, size_t _offset) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->pointer -= (_offset); +} + +#define _stream_read_n8(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ + (_t)(*_s->pointer); \ + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) + +#define _stream_read_n16_le(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ (_t)(*_s->pointer) + \ (((_t)(*(_s->pointer + 1))) << 8); \ - if (_p) _s->pointer += 2; } while (0) + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n16_be(_t, _s, _v, _p) do { _v = \ +#define _stream_read_n16_be(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ (((_t)(*_s->pointer)) << 8) + \ (_t)(*(_s->pointer + 1)); \ - if (_p) _s->pointer += 2; } while (0) + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n32_le(_t, _s, _v, _p) do { _v = \ +#define _stream_read_n32_le(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ (_t)(*_s->pointer) + \ (((_t)(*(_s->pointer + 1))) << 8) + \ (((_t)(*(_s->pointer + 2))) << 16) + \ (((_t)(*(_s->pointer + 3))) << 24); \ - if (_p) _s->pointer += 4; } while (0) + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n32_be(_t, _s, _v, _p) do { _v = \ +#define _stream_read_n32_be(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ (((_t)(*(_s->pointer))) << 24) + \ (((_t)(*(_s->pointer + 1))) << 16) + \ (((_t)(*(_s->pointer + 2))) << 8) + \ (((_t)(*(_s->pointer + 3)))); \ - if (_p) _s->pointer += 4; } while (0) + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n64_le(_t, _s, _v, _p) do { _v = \ +#define _stream_read_n64_le(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ (_t)(*_s->pointer) + \ (((_t)(*(_s->pointer + 1))) << 8) + \ (((_t)(*(_s->pointer + 2))) << 16) + \ @@ -87,9 +111,11 @@ WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); (((_t)(*(_s->pointer + 5))) << 40) + \ (((_t)(*(_s->pointer + 6))) << 48) + \ (((_t)(*(_s->pointer + 7))) << 56); \ - if (_p) _s->pointer += 8; } while (0) + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n64_be(_t, _s, _v, _p) do { _v = \ +#define _stream_read_n64_be(_t, __s, _v, _p) do { \ + struct _wStream* _s = (struct _wStream*)__s; \ + _v = \ (((_t)(*(_s->pointer))) << 56) + \ (((_t)(*(_s->pointer + 1))) << 48) + \ (((_t)(*(_s->pointer + 2))) << 40) + \ @@ -98,102 +124,117 @@ WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); (((_t)(*(_s->pointer + 5))) << 16) + \ (((_t)(*(_s->pointer + 6))) << 8) + \ (((_t)(*(_s->pointer + 7)))); \ - if (_p) _s->pointer += 8; } while (0) + if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) +#define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, TRUE) +#define Stream_Read_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, TRUE) -#define Stream_Read_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, 1) -#define Stream_Read_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, 1) +#define Stream_Read_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, TRUE) +#define Stream_Read_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, TRUE) -#define Stream_Read_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, 1) -#define Stream_Read_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, 1) +#define Stream_Read_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, TRUE) +#define Stream_Read_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, TRUE) -#define Stream_Read_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, 1) -#define Stream_Read_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, 1) +#define Stream_Read_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, TRUE) +#define Stream_Read_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, TRUE) -#define Stream_Read_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, 1) -#define Stream_Read_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, 1) +#define Stream_Read_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, TRUE) +#define Stream_Read_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, TRUE) -#define Stream_Read_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, 1) -#define Stream_Read_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, 1) +#define Stream_Read_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, TRUE) +#define Stream_Read_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, TRUE) -#define Stream_Read_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, 1) -#define Stream_Read_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, 1) +#define Stream_Read_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, TRUE) +#define Stream_Read_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, TRUE) -#define Stream_Read_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, 1) -#define Stream_Read_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, 1) +static INLINE void Stream_Read(wStream* s, void* _b, size_t _n) +{ + struct _wStream* _s = (struct _wStream*)s; + memcpy(_b, (_s->pointer), (_n)); + Stream_Seek(_s, _n); +} -#define Stream_Read(_s, _b, _n) do { \ - memcpy(_b, (_s->pointer), (_n)); \ - _s->pointer += (_n); \ - } while (0) +#define Stream_Peek_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, FALSE) +#define Stream_Peek_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, FALSE) +#define Stream_Peek_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, FALSE) +#define Stream_Peek_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, FALSE) -#define Stream_Peek_UINT8(_s, _v) _stream_read_n8(UINT8, _s, _v, 0) -#define Stream_Peek_INT8(_s, _v) _stream_read_n8(INT8, _s, _v, 0) +#define Stream_Peek_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, FALSE) +#define Stream_Peek_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, FALSE) -#define Stream_Peek_UINT16(_s, _v) _stream_read_n16_le(UINT16, _s, _v, 0) -#define Stream_Peek_INT16(_s, _v) _stream_read_n16_le(INT16, _s, _v, 0) +#define Stream_Peek_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, FALSE) +#define Stream_Peek_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, FALSE) -#define Stream_Peek_UINT16_BE(_s, _v) _stream_read_n16_be(UINT16, _s, _v, 0) -#define Stream_Peek_INT16_BE(_s, _v) _stream_read_n16_be(INT16, _s, _v, 0) +#define Stream_Peek_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, FALSE) +#define Stream_Peek_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, FALSE) -#define Stream_Peek_UINT32(_s, _v) _stream_read_n32_le(UINT32, _s, _v, 0) -#define Stream_Peek_INT32(_s, _v) _stream_read_n32_le(INT32, _s, _v, 0) +#define Stream_Peek_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, FALSE) +#define Stream_Peek_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, FALSE) -#define Stream_Peek_UINT32_BE(_s, _v) _stream_read_n32_be(UINT32, _s, _v, 0) -#define Stream_Peek_INT32_BE(_s, _v) _stream_read_n32_be(INT32, _s, _v, 0) +#define Stream_Peek_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, FALSE) +#define Stream_Peek_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, FALSE) -#define Stream_Peek_UINT64(_s, _v) _stream_read_n64_le(UINT64, _s, _v, 0) -#define Stream_Peek_INT64(_s, _v) _stream_read_n64_le(INT64, _s, _v, 0) +static INLINE void Stream_Peek(wStream* s, void* _b, size_t _n) +{ + struct _wStream* _s = (struct _wStream*)s; + memcpy(_b, (_s->pointer), (_n)); +} -#define Stream_Peek_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, 0) -#define Stream_Peek_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, 0) +static INLINE void Stream_Write_UINT8(wStream* s, UINT8 _v) +{ + struct _wStream* _s = (struct _wStream*)s; + *_s->pointer++ = (UINT8)(_v); +} -#define Stream_Peek(_s, _b, _n) do { \ - memcpy(_b, (_s->pointer), (_n)); \ - } while (0) +static INLINE void Stream_Write_UINT16(wStream* s, UINT16 _v) +{ + struct _wStream* _s = (struct _wStream*)s; + *_s->pointer++ = (_v) & 0xFF; + *_s->pointer++ = ((_v) >> 8) & 0xFF; +} +static INLINE void Stream_Write_UINT16_BE(wStream* s, UINT16 _v) +{ + struct _wStream* _s = (struct _wStream*)s; + *_s->pointer++ = ((_v) >> 8) & 0xFF; + *_s->pointer++ = (_v) & 0xFF; +} -#define Stream_Write_UINT8(_s, _v) do { \ - *_s->pointer++ = (UINT8)(_v); } while (0) +static INLINE void Stream_Write_UINT32(wStream* s, UINT32 _v) +{ + struct _wStream* _s = (struct _wStream*)s; + *_s->pointer++ = (_v) & 0xFF; + *_s->pointer++ = ((_v) >> 8) & 0xFF; + *_s->pointer++ = ((_v) >> 16) & 0xFF; + *_s->pointer++ = ((_v) >> 24) & 0xFF; +} -#define Stream_Write_UINT16(_s, _v) do { \ - *_s->pointer++ = (_v) & 0xFF; \ - *_s->pointer++ = ((_v) >> 8) & 0xFF; } while (0) +static INLINE void Stream_Write_UINT32_BE(wStream* s, UINT32 _v) +{ + struct _wStream* _s = (struct _wStream*)s; + Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); + Stream_Write_UINT16_BE(_s, ((_v) & 0xFFFF)); +} -#define Stream_Write_UINT16_BE(_s, _v) do { \ - *_s->pointer++ = ((_v) >> 8) & 0xFF; \ - *_s->pointer++ = (_v) & 0xFF; } while (0) - -#define Stream_Write_UINT32(_s, _v) do { \ - *_s->pointer++ = (_v) & 0xFF; \ - *_s->pointer++ = ((_v) >> 8) & 0xFF; \ - *_s->pointer++ = ((_v) >> 16) & 0xFF; \ - *_s->pointer++ = ((_v) >> 24) & 0xFF; } while (0) - -#define Stream_Write_UINT32_BE(_s, _v) do { \ - Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); \ - Stream_Write_UINT16_BE(_s, ((_v) & 0xFFFF)); \ - } while (0) - -#define Stream_Write_UINT64(_s, _v) do { \ - *_s->pointer++ = (UINT64)(_v) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; \ - *_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; } while (0) - -#define Stream_Write(_s, _b, _n) do { \ - memcpy(_s->pointer, (_b), (_n)); \ - _s->pointer += (_n); \ - } while (0) - - -#define Stream_Seek(_s,_offset) _s->pointer += (_offset) -#define Stream_Rewind(_s,_offset) _s->pointer -= (_offset) +static INLINE void Stream_Write_UINT64(wStream* s, UINT64 _v) +{ + struct _wStream* _s = (struct _wStream*)s; + *_s->pointer++ = (UINT64)(_v) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 24) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 32) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 40) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; + *_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; +} +static INLINE void Stream_Write(wStream* s, void* _b, size_t _n) +{ + struct _wStream* _s = (struct _wStream*)s; + memcpy(_s->pointer, (_b), (_n)); + Stream_Seek(_s, _n); +} #define Stream_Seek_UINT8(_s) Stream_Seek(_s, 1) #define Stream_Seek_UINT16(_s) Stream_Seek(_s, 2) @@ -205,45 +246,111 @@ WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); #define Stream_Rewind_UINT32(_s) Stream_Rewind(_s, 4) #define Stream_Rewind_UINT64(_s) Stream_Rewind(_s, 8) -#define Stream_Zero(_s, _n) do { \ - memset(_s->pointer, '\0', (_n)); \ - _s->pointer += (_n); \ - } while (0) +static INLINE void Stream_Zero(wStream* s, size_t _n) +{ + struct _wStream* _s = (struct _wStream*)s; + memset(_s->pointer, '\0', (_n)); + Stream_Seek(_s, _n); +} -#define Stream_Fill(_s, _v, _n) do { \ - memset(_s->pointer, _v, (_n)); \ - _s->pointer += (_n); \ - } while (0) +static INLINE void Stream_Fill(wStream* s, int _v, size_t _n) +{ + struct _wStream* _s = (struct _wStream*)s; + memset(_s->pointer, _v, (_n)); + Stream_Seek(_s, _n); +} -#define Stream_Copy(_dst, _src, _n) do { \ - memcpy(_dst->pointer, _src->pointer, _n); \ - _dst->pointer += _n; \ - _src->pointer += _n; \ - } while (0) +static INLINE void Stream_Copy(wStream* dst, wStream* src, size_t _n) +{ + struct _wStream* _src = (struct _wStream*)src; + struct _wStream* _dst = (struct _wStream*)dst; -#define Stream_Buffer(_s) _s->buffer -#define Stream_GetBuffer(_s, _b) _b = _s->buffer -#define Stream_SetBuffer(_s, _b) _s->buffer = _b + memcpy(_dst->pointer, _src->pointer, _n); + Stream_Seek(_dst, _n); + Stream_Seek(_src, _n); +} -#define Stream_Pointer(_s) _s->pointer -#define Stream_GetPointer(_s, _p) _p = _s->pointer -#define Stream_SetPointer(_s, _p) _s->pointer = _p +static INLINE BYTE* Stream_Buffer(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + return _s->buffer; +} -#define Stream_Length(_s) _s->length -#define Stream_GetLength(_s, _l) _l = _s->length -#define Stream_SetLength(_s, _l) _s->length = _l +#define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s) +static INLINE void Stream_SetBuffer(wStream* s, BYTE* _b) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->buffer = _b; +} -#define Stream_Capacity(_s) _s->capacity -#define Stream_GetCapacity(_s, _c) _c = _s->capacity -#define Stream_SetCapacity(_s, _c) _s->capacity = _c +static INLINE BYTE* Stream_Pointer(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + return _s->pointer; +} -#define Stream_GetPosition(_s) (_s->pointer - _s->buffer) -#define Stream_SetPosition(_s, _p) _s->pointer = _s->buffer + (_p) +#define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s) +static INLINE void Stream_SetPointer(wStream* s, BYTE* _p) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->pointer = _p; +} -#define Stream_SealLength(_s) _s->length = (_s->pointer - _s->buffer) -#define Stream_GetRemainingLength(_s) (_s->length - (_s->pointer - _s->buffer)) +static INLINE size_t Stream_Length(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + return _s->length; +} -#define Stream_Clear(_s) memset(_s->buffer, 0, _s->capacity) +#define Stream_GetLength(_s, _l) _l = Stream_Length(_s) +static INLINE void Stream_SetLength(wStream* s, size_t _l) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->length = _l; +} + +static INLINE size_t Stream_Capacity(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + return _s->capacity; +} + +#define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s); +static INLINE void Stream_SetCapacity(wStream* s, size_t _c) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->capacity = _c; +} + +static INLINE size_t Stream_GetPosition(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + return (_s->pointer - _s->buffer); +} + +static INLINE void Stream_SetPosition(wStream* s, size_t _p) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->pointer = _s->buffer + (_p); +} + +static INLINE void Stream_SealLength(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + _s->length = (_s->pointer - _s->buffer); +} + +static INLINE size_t Stream_GetRemainingLength(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + return (_s->length - (_s->pointer - _s->buffer)); +} + +static INLINE void Stream_Clear(wStream* s) +{ + struct _wStream* _s = (struct _wStream*)s; + memset(_s->buffer, 0, _s->capacity); +} static INLINE BOOL Stream_SafeSeek(wStream* s, size_t size) { if (Stream_GetRemainingLength(s) < size) From 541abee4808259c871ca8706d1a2399b060e5048 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 25 Feb 2016 21:57:56 +0100 Subject: [PATCH 069/128] cmake/FindWayland: cleanup * use consistent naming * remove trailing blanks --- cmake/FindWayland.cmake | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake/FindWayland.cmake b/cmake/FindWayland.cmake index 93668d338..ee217f61d 100644 --- a/cmake/FindWayland.cmake +++ b/cmake/FindWayland.cmake @@ -1,5 +1,5 @@ # - Finds Wayland -# Find the Wayland libraries that are needed for UWAC +# Find the Wayland libraries that are needed for UWAC # # This module defines the following variables: # WAYLAND_FOUND - true if UWAC has been found @@ -28,29 +28,29 @@ include(FindPkgConfig) if(PKG_CONFIG_FOUND) - pkg_check_modules(WAYLAND_SCANNER_PKG wayland-scanner) - pkg_check_modules(WAYLAND_CLIENT_PKG wayland-client) - pkg_check_modules(XKBCOMMON_PC_PKG xkbcommon) + pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner) + pkg_check_modules(WAYLAND_CLIENT_PC wayland-client) + pkg_check_modules(XKBCOMMON_PC xkbcommon) endif() find_program(WAYLAND_SCANNER wayland-scanner - HINTS "${WAYLAND_SCANNER_PKG_PREFIX}/bin" + HINTS "${WAYLAND_SCANNER_PC_PREFIX}/bin" ) find_path(WAYLAND_INCLUDE_DIR wayland-client.h - HINTS ${WAYLAND_CLIENT_PKG_INCLUDE_DIRS} + HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS} ) -find_library(WAYLAND_LIBS +find_library(WAYLAND_LIBS NAMES "wayland-client" - HINTS "${WAYLAND_CLIENT_PKG_LIBRARY_DIRS}" + HINTS "${WAYLAND_CLIENT_PC_LIBRARY_DIRS}" ) find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h HINTS ${XKBCOMMON_PC_INCLUDE_DIRS} ) -find_library(XKBCOMMON_LIBS +find_library(XKBCOMMON_LIBS NAMES xkbcommon HINTS "${XKBCOMMON_PC_LIBRARY_DIRS}" ) From 71836f6cab6d8f436eb879068193b2082af04653 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 25 Feb 2016 23:38:53 +0100 Subject: [PATCH 070/128] build winpr: export WINPR_API_VERSION --- winpr/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 0bf1443f9..2e3b673f6 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -66,6 +66,7 @@ endif(NOT IOS) if(FREERDP_BUILD) set(WINPR_VERSION_FULL ${WINPR_VERSION_FULL} PARENT_SCOPE) set(WINPR_VERSION ${WINPR_VERSION} PARENT_SCOPE) + set(WINPR_API_VERSION ${WINPR_API_VERSION} PARENT_SCOPE) else() set(CMAKE_THREAD_PREFER_PTHREAD TRUE) From 167907ef2eac5f17865c6571c36d38f018e72cbb Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 25 Feb 2016 23:46:56 +0100 Subject: [PATCH 071/128] uwac: enable library versioning --- uwac/CMakeLists.txt | 9 ++++++++- uwac/include/CMakeLists.txt | 3 +-- uwac/libuwac/CMakeLists.txt | 6 +++--- 3 files changed, 12 insertions(+), 6 deletions(-) diff --git a/uwac/CMakeLists.txt b/uwac/CMakeLists.txt index cbfecb86a..dc8c9f00d 100644 --- a/uwac/CMakeLists.txt +++ b/uwac/CMakeLists.txt @@ -15,6 +15,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Soname versioning +set(UWAC_VERSION_MAJOR "0") +set(UWAC_VERSION_MINOR "0") +set(UWAC_VERSION_REVISION "1") +set(UWAC_VERSION "${UWAC_VERSION_MAJOR}.${UWAC_VERSION_MINOR}.${UWAC_VERSION_REVISION}") +set(UWAC_VERSION_FULL "${UWAC_VERSION}") +set(UWAC_API_VERSION "${UWAC_VERSION_MAJOR}") + add_subdirectory(include) add_subdirectory(libuwac) - diff --git a/uwac/include/CMakeLists.txt b/uwac/include/CMakeLists.txt index b6e7129b1..68587284e 100644 --- a/uwac/include/CMakeLists.txt +++ b/uwac/include/CMakeLists.txt @@ -16,5 +16,4 @@ # limitations under the License. file(GLOB UWAC_HEADERS "uwac/*.h") -install(FILES ${UWAC_HEADERS} DESTINATION include/uwac COMPONENT headers) - +install(FILES ${UWAC_HEADERS} DESTINATION include/uwac${UWAC_API_VERSION}/uwac COMPONENT headers) diff --git a/uwac/libuwac/CMakeLists.txt b/uwac/libuwac/CMakeLists.txt index 49a663407..4de932519 100644 --- a/uwac/libuwac/CMakeLists.txt +++ b/uwac/libuwac/CMakeLists.txt @@ -65,12 +65,12 @@ add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) if (WITH_LIBRARY_VERSIONING) - #set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${UWAC_VERSION} SOVERSION ${UWAC_API_VERSION}) + set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${UWAC_VERSION} SOVERSION ${UWAC_API_VERSION}) endif() -target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBS} ${XKBCOMMON_LIBS}) +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBS} ${XKBCOMMON_LIBS} freerdp) -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT Uwac) +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} EXPORT uwac) set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "uwac") From d5a43ddc6e90cd780ce98f82c13994775c876fc1 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 25 Feb 2016 23:47:32 +0100 Subject: [PATCH 072/128] uwac: generate .pc and cmake find-module --- uwac/CMakeLists.txt | 25 ++++++++++++++++++++++ uwac/uwac.pc.in | 15 +++++++++++++ uwac/uwacConfig.cmake.in | 9 ++++++++ uwac/uwacVersion.cmake | 46 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 95 insertions(+) create mode 100644 uwac/uwac.pc.in create mode 100644 uwac/uwacConfig.cmake.in create mode 100644 uwac/uwacVersion.cmake diff --git a/uwac/CMakeLists.txt b/uwac/CMakeLists.txt index dc8c9f00d..369ba2ded 100644 --- a/uwac/CMakeLists.txt +++ b/uwac/CMakeLists.txt @@ -25,3 +25,28 @@ set(UWAC_API_VERSION "${UWAC_VERSION_MAJOR}") add_subdirectory(include) add_subdirectory(libuwac) + +set(UWAC_INCLUDE_DIR "include/uwac${UWAC_VERSION_MAJOR}") +# cmake package +if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") + + export(PACKAGE uwac) + + set(UWAC_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/uwac${UWAC_VERSION_MAJOR}") + + + configure_package_config_file(uwacConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/uwacConfig.cmake + INSTALL_DESTINATION ${UWAC_CMAKE_INSTALL_DIR} + PATH_VARS UWAC_INCLUDE_DIR) + + write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/uwacConfigVersion.cmake + VERSION ${UWAC_VERSION} COMPATIBILITY SameMajorVersion) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/uwacConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/uwacConfigVersion.cmake + DESTINATION ${UWAC_CMAKE_INSTALL_DIR}) + + install(EXPORT uwac DESTINATION ${UWAC_CMAKE_INSTALL_DIR}) +endif() + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/uwac.pc.in ${CMAKE_CURRENT_BINARY_DIR}/uwac${UWAC_VERSION_MAJOR}.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/uwac${UWAC_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) diff --git a/uwac/uwac.pc.in b/uwac/uwac.pc.in new file mode 100644 index 000000000..66b477e98 --- /dev/null +++ b/uwac/uwac.pc.in @@ -0,0 +1,15 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=${prefix}/@UWAC_INCLUDE_DIR@ +libs=-luwac + +Name: uwac +Description: uwac: using wayland as a client +URL: http://www.freerdp.com/ +Version: @UWAC_VERSION@ +Requires: +Requires.private: wayland-client xkbcommon freerdp@FREERDP_VERSION_MAJOR@ +Libs: -L${libdir} ${libs} +Libs.private: +Cflags: -I${includedir} diff --git a/uwac/uwacConfig.cmake.in b/uwac/uwacConfig.cmake.in new file mode 100644 index 000000000..2433842e9 --- /dev/null +++ b/uwac/uwacConfig.cmake.in @@ -0,0 +1,9 @@ +@PACKAGE_INIT@ + +set(UWAC_VERSION_MAJOR "@UWAC_VERSION_MAJOR@") +set(UWAC_VERSION_MINOR "@UWAC_VERSION_MINOR@") +set(UWAC_VERSION_REVISION "@UWAC_VERSION_REVISION@") + +set_and_check(UWAC_INCLUDE_DIR "@PACKAGE_UWAC_INCLUDE_DIR@") + +include("${CMAKE_CURRENT_LIST_DIR}/uwac.cmake") diff --git a/uwac/uwacVersion.cmake b/uwac/uwacVersion.cmake new file mode 100644 index 000000000..2a789d7d0 --- /dev/null +++ b/uwac/uwacVersion.cmake @@ -0,0 +1,46 @@ +# This is a basic version file for the Config-mode of find_package(). +# It is used by write_basic_package_version_file() as input file for configure_file() +# to create a version-file which can be installed along a config.cmake file. +# +# The created file sets PACKAGE_VERSION_EXACT if the current version string and +# the requested version string are exactly the same and it sets +# PACKAGE_VERSION_COMPATIBLE if the current version is >= requested version, +# but only if the requested major version is the same as the current one. +# The variable CVF_VERSION must be set before calling configure_file(). + + +set(PACKAGE_VERSION "0.0.1") + +if("${PACKAGE_VERSION}" VERSION_LESS "${PACKAGE_FIND_VERSION}" ) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + + if("0.0.1" MATCHES "^([0-9]+)\\.") + set(CVF_VERSION_MAJOR "${CMAKE_MATCH_1}") + else() + set(CVF_VERSION_MAJOR "0.0.1") + endif() + + if("${PACKAGE_FIND_VERSION_MAJOR}" STREQUAL "${CVF_VERSION_MAJOR}") + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + + if( "${PACKAGE_FIND_VERSION}" STREQUAL "${PACKAGE_VERSION}") + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() + + +# if the installed or the using project don't have CMAKE_SIZEOF_VOID_P set, ignore it: +if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "" OR "8" STREQUAL "") + return() +endif() + +# check that the installed version has the same 32/64bit-ness as the one which is currently searching: +if(NOT "${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") + math(EXPR installedBits "8 * 8") + set(PACKAGE_VERSION "${PACKAGE_VERSION} (${installedBits}bit)") + set(PACKAGE_VERSION_UNSUITABLE TRUE) +endif() From 7a253bae4298ab1bf9b1ab4b60c5b2e4a31987bd Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 09:27:53 +0100 Subject: [PATCH 073/128] Replaced magic numbers with defines. --- libfreerdp/core/security.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index b63022763..5484476a2 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -203,15 +203,15 @@ BOOL security_md5_16_32_32(const BYTE* in0, const BYTE* in1, const BYTE* in2, BY WINPR_MD5_CTX md5; if (!winpr_MD5_Init(&md5)) - return FALSE; + return FALSE; if (!winpr_MD5_Update(&md5, in0, 16)) - return FALSE; + return FALSE; if (!winpr_MD5_Update(&md5, in1, 32)) - return FALSE; + return FALSE; if (!winpr_MD5_Update(&md5, in2, 32)) - return FALSE; + return FALSE; if (!winpr_MD5_Final(&md5, output, WINPR_MD5_DIGEST_LENGTH)) - return FALSE; + return FALSE; return TRUE; } @@ -459,9 +459,9 @@ BOOL security_establish_keys(const BYTE* client_random, rdpRdp* rdp) if (!winpr_SHA1_Init(&sha1)) return FALSE; - if (!winpr_SHA1_Update(&sha1, client_decrypt_key_t, 20)) + if (!winpr_SHA1_Update(&sha1, client_decrypt_key_t, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; - if (!winpr_SHA1_Update(&sha1, client_encrypt_key_t, 20)) + if (!winpr_SHA1_Update(&sha1, client_encrypt_key_t, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; if (!winpr_SHA1_Final(&sha1, rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; @@ -625,18 +625,19 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* rdp) { - BYTE buf[20]; + BYTE buf[WINPR_SHA1_DIGEST_LENGTH]; BYTE use_count_le[4]; security_UINT32_le(use_count_le, rdp->encrypt_use_count); - if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, rdp->fips_sign_key, 20)) + if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, + rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; if (!winpr_HMAC_Update(rdp->fips_hmac, data, length)) return FALSE; if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4)) return FALSE; - if (!winpr_HMAC_Final(rdp->fips_hmac, buf, 20)) + if (!winpr_HMAC_Final(rdp->fips_hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; memmove(output, buf, 8); @@ -658,18 +659,19 @@ BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp) BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp) { - BYTE buf[20]; + BYTE buf[WINPR_SHA1_DIGEST_LENGTH]; BYTE use_count_le[4]; security_UINT32_le(use_count_le, rdp->decrypt_use_count); - if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, rdp->fips_sign_key, 20)) + if (!winpr_HMAC_Init(rdp->fips_hmac, WINPR_MD_SHA1, + rdp->fips_sign_key, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; if (!winpr_HMAC_Update(rdp->fips_hmac, data, length)) return FALSE; if (!winpr_HMAC_Update(rdp->fips_hmac, use_count_le, 4)) return FALSE; - if (!winpr_HMAC_Final(rdp->fips_hmac, buf, 20)) + if (!winpr_HMAC_Final(rdp->fips_hmac, buf, WINPR_SHA1_DIGEST_LENGTH)) return FALSE; rdp->decrypt_use_count++; From fe8f5dee82bb9939acc1392efca65e34f618adf6 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 09:28:54 +0100 Subject: [PATCH 074/128] Fixed indentation. --- libfreerdp/common/assistance.c | 30 ++++----- winpr/libwinpr/crypto/hash.c | 72 ++++++++++----------- winpr/libwinpr/crypto/test/TestCryptoHash.c | 30 ++++----- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index 32b7bb534..63970de35 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -563,28 +563,28 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas cbPasswordW = (status - 1) * 2; if (!winpr_MD5_Init(&md5Ctx)) - { - free (PasswordW); - return NULL; - } + { + free (PasswordW); + return NULL; + } if (!winpr_MD5_Update(&md5Ctx, (BYTE*)PasswordW, cbPasswordW)) - { - free (PasswordW); - return NULL; - } + { + free (PasswordW); + return NULL; + } if (!winpr_MD5_Final(&md5Ctx, (BYTE*) PasswordHash, sizeof(PasswordHash))) - { - free (PasswordW); - return NULL; - } + { + free (PasswordW); + return NULL; + } status = ConvertToUnicode(CP_UTF8, 0, passStub, -1, &PassStubW, 0); if (status <= 0) - { - free (PasswordW); + { + free (PasswordW); return NULL; - } + } cbPassStubW = (status - 1) * 2; diff --git a/winpr/libwinpr/crypto/hash.c b/winpr/libwinpr/crypto/hash.c index 9761d7893..70c4392fa 100644 --- a/winpr/libwinpr/crypto/hash.c +++ b/winpr/libwinpr/crypto/hash.c @@ -47,41 +47,41 @@ BOOL winpr_MD5_Init(WINPR_MD5_CTX* ctx) { #if defined(WITH_OPENSSL) if (MD5_Init((MD5_CTX*) ctx) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_init((mbedtls_md5_context*) ctx); mbedtls_md5_starts((mbedtls_md5_context*) ctx); #endif - return TRUE; + return TRUE; } BOOL winpr_MD5_Update(WINPR_MD5_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) if (MD5_Update((MD5_CTX*) ctx, input, ilen) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_update((mbedtls_md5_context*) ctx, input, ilen); #endif - return TRUE; + return TRUE; } BOOL winpr_MD5_Final(WINPR_MD5_CTX* ctx, BYTE* output, size_t ilen) { - if (ilen < WINPR_MD5_DIGEST_LENGTH) - return FALSE; + if (ilen < WINPR_MD5_DIGEST_LENGTH) + return FALSE; #if defined(WITH_OPENSSL) if (MD5_Final(output, (MD5_CTX*) ctx) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD5_C) mbedtls_md5_finish((mbedtls_md5_context*) ctx, output); mbedtls_md5_free((mbedtls_md5_context*) ctx); #endif - return TRUE; + return TRUE; } BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen) @@ -89,9 +89,9 @@ BOOL winpr_MD5(const BYTE* input, size_t ilen, BYTE* output, size_t olen) WINPR_MD5_CTX ctx; if (!winpr_MD5_Init(&ctx)) - return FALSE; + return FALSE; if (!winpr_MD5_Update(&ctx, input, ilen)) - return FALSE; + return FALSE; return winpr_MD5_Final(&ctx, output, olen); } @@ -103,40 +103,40 @@ BOOL winpr_MD4_Init(WINPR_MD4_CTX* ctx) { #if defined(WITH_OPENSSL) if (MD4_Init((MD4_CTX*) ctx) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_init((mbedtls_md4_context*) ctx); mbedtls_md4_starts((mbedtls_md4_context*) ctx); #endif - return TRUE; + return TRUE; } BOOL winpr_MD4_Update(WINPR_MD4_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) if (MD4_Update((MD4_CTX*) ctx, input, ilen) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_update((mbedtls_md4_context*) ctx, input, ilen); #endif - return TRUE; + return TRUE; } BOOL winpr_MD4_Final(WINPR_MD4_CTX* ctx, BYTE* output, size_t olen) { - if (olen < WINPR_MD4_DIGEST_LENGTH) - return FALSE; + if (olen < WINPR_MD4_DIGEST_LENGTH) + return FALSE; #if defined(WITH_OPENSSL) if (MD4_Final(output, (MD4_CTX*) ctx) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_MD4_C) mbedtls_md4_finish((mbedtls_md4_context*) ctx, output); mbedtls_md4_free((mbedtls_md4_context*) ctx); #endif - return TRUE; + return TRUE; } BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen) @@ -144,9 +144,9 @@ BOOL winpr_MD4(const BYTE* input, size_t ilen, BYTE* output, size_t olen) WINPR_MD4_CTX ctx; if (!winpr_MD4_Init(&ctx)) - return FALSE; + return FALSE; if (!winpr_MD4_Update(&ctx, input, ilen)) - return FALSE; + return FALSE; return winpr_MD4_Final(&ctx, output, olen); } @@ -158,41 +158,41 @@ BOOL winpr_SHA1_Init(WINPR_SHA1_CTX* ctx) { #if defined(WITH_OPENSSL) if (SHA1_Init((SHA_CTX*) ctx) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_init((mbedtls_sha1_context*) ctx); mbedtls_sha1_starts((mbedtls_sha1_context*) ctx); #endif - return TRUE; + return TRUE; } BOOL winpr_SHA1_Update(WINPR_SHA1_CTX* ctx, const BYTE* input, size_t ilen) { #if defined(WITH_OPENSSL) if (SHA1_Update((SHA_CTX*) ctx, input, ilen) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_update((mbedtls_sha1_context*) ctx, input, ilen); #endif - return TRUE; + return TRUE; } BOOL winpr_SHA1_Final(WINPR_SHA1_CTX* ctx, BYTE* output, size_t olen) { - if (olen < WINPR_SHA1_DIGEST_LENGTH) - return FALSE; + if (olen < WINPR_SHA1_DIGEST_LENGTH) + return FALSE; #if defined(WITH_OPENSSL) if (SHA1_Final(output, (SHA_CTX*) ctx) != 1) - return FALSE; + return FALSE; #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_SHA1_C) mbedtls_sha1_finish((mbedtls_sha1_context*) ctx, output); mbedtls_sha1_free((mbedtls_sha1_context*) ctx); #endif - return TRUE; + return TRUE; } BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen) @@ -200,9 +200,9 @@ BOOL winpr_SHA1(const BYTE* input, size_t ilen, BYTE* output, size_t olen) WINPR_SHA1_CTX ctx; if (!winpr_SHA1_Init(&ctx)) - return FALSE; + return FALSE; if (!winpr_SHA1_Update(&ctx, input, ilen)) - return FALSE; + return FALSE; return winpr_SHA1_Final(&ctx, output, olen); } @@ -362,10 +362,10 @@ BOOL winpr_HMAC_Update(WINPR_HMAC_CTX* ctx, const BYTE* input, size_t ilen) BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen) { - /* TODO - if (olen < ctx->digestLength) - return FALSE; - */ + /* TODO + if (olen < ctx->digestLength) + return FALSE; + */ #if defined(WITH_OPENSSL) #if (OPENSSL_VERSION_NUMBER < 0x10000000L) @@ -385,7 +385,7 @@ BOOL winpr_HMAC_Final(WINPR_HMAC_CTX* ctx, BYTE* output, size_t olen) } BOOL winpr_HMAC(WINPR_MD_TYPE md, const BYTE* key, size_t keylen, - const BYTE* input, size_t ilen, BYTE* output, size_t olen) + const BYTE* input, size_t ilen, BYTE* output, size_t olen) { WINPR_HMAC_CTX ctx; @@ -450,7 +450,7 @@ BOOL winpr_Digest_Update(WINPR_DIGEST_CTX* ctx, const BYTE* input, size_t ilen) BOOL winpr_Digest_Final(WINPR_DIGEST_CTX* ctx, BYTE* output, size_t olen) { - // TODO: output length check + // TODO: output length check #if defined(WITH_OPENSSL) if (EVP_DigestFinal_ex((EVP_MD_CTX*) ctx, output, NULL) != 1) return FALSE; diff --git a/winpr/libwinpr/crypto/test/TestCryptoHash.c b/winpr/libwinpr/crypto/test/TestCryptoHash.c index ec6d5ad6d..71227ee80 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoHash.c +++ b/winpr/libwinpr/crypto/test/TestCryptoHash.c @@ -12,11 +12,11 @@ BOOL test_crypto_hash_md5() WINPR_MD5_CTX ctx; if (!winpr_MD5_Init(&ctx)) - return FALSE; + return FALSE; if (!winpr_MD5_Update(&ctx, (BYTE*) TEST_MD5_DATA, strlen(TEST_MD5_DATA))) - return FALSE; + return FALSE; if (!winpr_MD5_Final(&ctx, hash, sizeof(hash))) - return FALSE; + return FALSE; if (memcmp(hash, TEST_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { @@ -46,11 +46,11 @@ BOOL test_crypto_hash_md4() WINPR_MD4_CTX ctx; if (!winpr_MD4_Init(&ctx)) - return FALSE; + return FALSE; if (!winpr_MD4_Update(&ctx, (BYTE*) TEST_MD4_DATA, strlen(TEST_MD4_DATA))) - return FALSE; + return FALSE; if (!winpr_MD4_Final(&ctx, hash, sizeof(hash))) - return FALSE; + return FALSE; if (memcmp(hash, TEST_MD4_HASH, WINPR_MD4_DIGEST_LENGTH) != 0) { @@ -80,11 +80,11 @@ BOOL test_crypto_hash_sha1() WINPR_SHA1_CTX ctx; if (!winpr_SHA1_Init(&ctx)) - return FALSE; + return FALSE; if (!winpr_SHA1_Update(&ctx, (BYTE*) TEST_SHA1_DATA, strlen(TEST_SHA1_DATA))) - return FALSE; + return FALSE; if (!winpr_SHA1_Final(&ctx, hash, sizeof(hash))) - return FALSE; + return FALSE; if (memcmp(hash, TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { @@ -115,11 +115,11 @@ BOOL test_crypto_hash_hmac_md5() WINPR_HMAC_CTX ctx; if (!winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_SHA1_DIGEST_LENGTH)) - return FALSE; + return FALSE; if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA))) - return FALSE; + return FALSE; if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) - return FALSE; + return FALSE; if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0) { @@ -150,11 +150,11 @@ BOOL test_crypto_hash_hmac_sha1() WINPR_HMAC_CTX ctx; if (!winpr_HMAC_Init(&ctx, WINPR_MD_SHA1, TEST_HMAC_SHA1_KEY, WINPR_SHA1_DIGEST_LENGTH)) - return FALSE; + return FALSE; if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_SHA1_DATA, strlen(TEST_HMAC_SHA1_DATA))) - return FALSE; + return FALSE; if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) - return FALSE; + return FALSE; if (memcmp(hash, TEST_HMAC_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0) { From 436be2441a076e659b892b384310991d49cae2fe Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 10:48:53 +0100 Subject: [PATCH 075/128] Implemented SetFileTime --- winpr/include/winpr/file.h | 3 ++ winpr/libwinpr/file/file.c | 55 +++++++++++++++++++++++++-- winpr/libwinpr/file/generic.c | 21 ++++++++++ winpr/libwinpr/file/namedPipeClient.c | 17 +++++---- winpr/libwinpr/handle/handle.h | 3 ++ winpr/libwinpr/pipe/pipe.c | 3 +- 6 files changed, 90 insertions(+), 12 deletions(-) diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h index f0129e212..386705e2c 100644 --- a/winpr/include/winpr/file.h +++ b/winpr/include/winpr/file.h @@ -288,6 +288,9 @@ WINPR_API BOOL UnlockFile(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOffse WINPR_API BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped); +WINPR_API BOOL SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime); + WINPR_API HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData); WINPR_API HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData); diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 862703b3e..6962f4aba 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -40,6 +40,8 @@ #include #include #include +#include +#include static BOOL FileIsHandled(HANDLE handle) { @@ -346,6 +348,52 @@ static BOOL FileUnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfByte return TRUE; } +static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime) +{ + int rc; + struct timespec times[2]; /* last access, last modification */ + WINPR_FILE* pFile = (WINPR_FILE*)hFile; + const UINT64 EPOCH_DIFF = 11644473600ULL; + + if (!hFile) + return FALSE; + + memset(times, 0, sizeof(times)); + if (!lpLastAccessTime) + times[0].tv_nsec = UTIME_OMIT; + else + { + UINT64 tmp = ((UINT64)lpLastAccessTime->dwHighDateTime) << 32 + | lpLastAccessTime->dwLowDateTime; + tmp -= EPOCH_DIFF; + tmp /= 10ULL; + + times[0].tv_sec = tmp / 10000000ULL; + times[0].tv_nsec = tmp % 10000000ULL; + } + if (!lpLastWriteTime) + times[1].tv_nsec = UTIME_OMIT; + else + { + UINT64 tmp = ((UINT64)lpLastWriteTime->dwHighDateTime) << 32 + | lpLastWriteTime->dwLowDateTime; + tmp -= EPOCH_DIFF; + tmp /= 10ULL; + + times[1].tv_sec = tmp / 10000000ULL; + times[1].tv_nsec = tmp % 10000000ULL; + } + + // TODO: Creation time can not be handled! + rc = futimens(fileno(pFile->fp), times); + if (rc != 0) + return FALSE; + + return TRUE; + +} + static HANDLE_OPS fileOps = { FileIsHandled, FileCloseHandle, @@ -365,7 +413,8 @@ static HANDLE_OPS fileOps = { NULL, /* FileLockFile */ FileLockFileEx, FileUnlockFile, - FileUnlockFileEx + FileUnlockFileEx, + FileSetFileTime }; static HANDLE_OPS shmOps = { @@ -387,8 +436,8 @@ static HANDLE_OPS shmOps = { NULL, /* FileLockFile */ NULL, /* FileLockFileEx */ NULL, /* FileUnlockFile */ - NULL /* FileUnlockFileEx */ - + NULL, /* FileUnlockFileEx */ + NULL /* FileSetFileTime */ }; diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index 8719787ad..367d28292 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -623,6 +623,27 @@ BOOL UnlockFileEx(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLo return FALSE; } +BOOL WINAPI SetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime) +{ + ULONG Type; + WINPR_HANDLE *handle; + + if (hFile == INVALID_HANDLE_VALUE) + return FALSE; + + if (!winpr_Handle_GetInfo(hFile, &Type, &handle)) + return FALSE; + + handle = (WINPR_HANDLE *)hFile; + if (handle->ops->SetFileTime) + return handle->ops->SetFileTime(handle, lpCreationTime, + lpLastAccessTime, lpLastWriteTime); + + WLog_ERR(TAG, "%s operation not implemented", __FUNCTION__); + return FALSE; +} + struct _WIN32_FILE_SEARCH { DIR* pDir; diff --git a/winpr/libwinpr/file/namedPipeClient.c b/winpr/libwinpr/file/namedPipeClient.c index b78f8eb7c..a318c9482 100644 --- a/winpr/libwinpr/file/namedPipeClient.c +++ b/winpr/libwinpr/file/namedPipeClient.c @@ -51,14 +51,14 @@ static HANDLE_CREATOR _NamedPipeClientHandleCreator; static BOOL NamedPipeClientIsHandled(HANDLE handle) { - WINPR_NAMED_PIPE* pFile = (WINPR_NAMED_PIPE*) handle; + WINPR_NAMED_PIPE* pFile = (WINPR_NAMED_PIPE*) handle; - if (!pFile || (pFile->Type != HANDLE_TYPE_NAMED_PIPE) || (pFile == INVALID_HANDLE_VALUE)) - { - SetLastError(ERROR_INVALID_HANDLE); - return FALSE; - } - return TRUE; + if (!pFile || (pFile->Type != HANDLE_TYPE_NAMED_PIPE) || (pFile == INVALID_HANDLE_VALUE)) + { + SetLastError(ERROR_INVALID_HANDLE); + return FALSE; + } + return TRUE; } BOOL NamedPipeClientCloseHandle(HANDLE handle) @@ -124,7 +124,8 @@ static HANDLE_OPS ops = { NULL, /* FileLockFile */ NULL, /* FileLockFileEx */ NULL, /* FileUnlockFile */ - NULL /* FileUnlockFileEx */ + NULL, /* FileUnlockFileEx */ + NULL /* SetFileTime */ }; static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, diff --git a/winpr/libwinpr/handle/handle.h b/winpr/libwinpr/handle/handle.h index d2669baa7..fc49e6429 100644 --- a/winpr/libwinpr/handle/handle.h +++ b/winpr/libwinpr/handle/handle.h @@ -77,6 +77,8 @@ typedef BOOL (*pcUnlockFile)(HANDLE hFile, DWORD dwFileOffsetLow, DWORD dwFileOf DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh); typedef BOOL (*pcUnlockFileEx)(HANDLE hFile, DWORD dwReserved, DWORD nNumberOfBytesToUnlockLow, DWORD nNumberOfBytesToUnlockHigh, LPOVERLAPPED lpOverlapped); +typedef BOOL (*pcSetFileTime)(HANDLE hFile, const FILETIME *lpCreationTime, + const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime); typedef struct _HANDLE_OPS { @@ -99,6 +101,7 @@ typedef struct _HANDLE_OPS pcLockFileEx LockFileEx; pcUnlockFile UnlockFile; pcUnlockFileEx UnlockFileEx; + pcSetFileTime SetFileTime; } HANDLE_OPS; struct winpr_handle diff --git a/winpr/libwinpr/pipe/pipe.c b/winpr/libwinpr/pipe/pipe.c index 02beb5d5b..0d8a6b6b0 100644 --- a/winpr/libwinpr/pipe/pipe.c +++ b/winpr/libwinpr/pipe/pipe.c @@ -191,7 +191,8 @@ static HANDLE_OPS ops = { NULL, /* FileLockFile */ NULL, /* FileLockFileEx */ NULL, /* FileUnlockFile */ - NULL /* FileUnlockFileEx */ + NULL, /* FileUnlockFileEx */ + NULL /* SetFileTime */ }; From 55372302988cf98ddadf6f292100f2ae180eda11 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 11:22:56 +0100 Subject: [PATCH 076/128] Fixed missing iOS UTIME_OMIT. --- winpr/libwinpr/file/file.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 6962f4aba..7e2285259 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -352,6 +352,9 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime) { int rc; +#ifdef __APPLE__ + struct stat buf; +#endif struct timespec times[2]; /* last access, last modification */ WINPR_FILE* pFile = (WINPR_FILE*)hFile; const UINT64 EPOCH_DIFF = 11644473600ULL; @@ -359,9 +362,25 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, if (!hFile) return FALSE; +#ifdef __APPLE__ + rc = fstat(fileno(pFile->fp), &buf); + if (rc < 0) + return FALSE; +#endif memset(times, 0, sizeof(times)); if (!lpLastAccessTime) + { +#ifdef __APPLE__ +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) + times[0] = buf.st_atimespec; +#else + times[0].tv_sec = buf.st_atime; + times[0].tv_nsec = buf.st_atimensec; +#endif +#else times[0].tv_nsec = UTIME_OMIT; +#endif + } else { UINT64 tmp = ((UINT64)lpLastAccessTime->dwHighDateTime) << 32 @@ -373,7 +392,18 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, times[0].tv_nsec = tmp % 10000000ULL; } if (!lpLastWriteTime) + { +#ifdef __APPLE__ +#if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) + times[1] = buf.st_mtimespec; +#else + times[1].tv_sec = buf.st_mtime; + times[1].tv_nsec = buf.st_mtimensec; +#endif +#else times[1].tv_nsec = UTIME_OMIT; +#endif + } else { UINT64 tmp = ((UINT64)lpLastWriteTime->dwHighDateTime) << 32 @@ -386,7 +416,11 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, } // TODO: Creation time can not be handled! +#ifdef __APPLE__ + rc = futimes(fileno(pFile->fp), times); +#else rc = futimens(fileno(pFile->fp), times); +#endif if (rc != 0) return FALSE; From 98d4a9347a700d29999e5416bba9b01137b56e49 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 12:13:02 +0100 Subject: [PATCH 077/128] Added support for android SetFileTime. Deactivated libjpeg support for android. --- scripts/android-build-freerdp.sh | 1 + scripts/android-build.conf | 3 ++- winpr/libwinpr/file/file.c | 33 +++++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/scripts/android-build-freerdp.sh b/scripts/android-build-freerdp.sh index a522f868f..73ce02114 100755 --- a/scripts/android-build-freerdp.sh +++ b/scripts/android-build-freerdp.sh @@ -80,6 +80,7 @@ fi common_run mkdir -p $BUILD_SRC CMAKE_CMD_ARGS="-DANDROID_NDK=$ANDROID_NDK \ + -DANDROID_NATIVE_API_LEVEL=${ANDROID_NATIVE_API_LEVEL} \ -DCMAKE_TOOLCHAIN_FILE=$SRC_DIR/cmake/AndroidToolchain.cmake \ -DCMAKE_INSTALL_PREFIX=$BUILD_DST \ -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE \ diff --git a/scripts/android-build.conf b/scripts/android-build.conf index fff1ab298..df5191211 100644 --- a/scripts/android-build.conf +++ b/scripts/android-build.conf @@ -4,10 +4,11 @@ SCRIPT_PATH=$(dirname "${BASH_SOURCE[0]}") SCRIPT_PATH=$(realpath "$SCRIPT_PATH") -WITH_JPEG=1 +WITH_JPEG=0 WITH_OPENH264=1 WITH_OPENSSL=1 BUILD_DEPS=1 +ANDROID_NATIVE_API_LEVEL=android-12 JPEG_TAG=master OPENH264_TAG=v1.5.0 diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 7e2285259..606121f78 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -352,22 +352,25 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime) { int rc; -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(ANDROID) struct stat buf; #endif +#ifdef ANDROID + struct timeval timevals[2]; +#else struct timespec times[2]; /* last access, last modification */ +#endif WINPR_FILE* pFile = (WINPR_FILE*)hFile; const UINT64 EPOCH_DIFF = 11644473600ULL; if (!hFile) return FALSE; -#ifdef __APPLE__ +#if defined(__APPLE__) || defined(ANDROID) rc = fstat(fileno(pFile->fp), &buf); if (rc < 0) return FALSE; #endif - memset(times, 0, sizeof(times)); if (!lpLastAccessTime) { #ifdef __APPLE__ @@ -377,7 +380,11 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, times[0].tv_sec = buf.st_atime; times[0].tv_nsec = buf.st_atimensec; #endif +#elif ANDROID + timevals[0].tv_sec = buf.st_mtime; + timevals[0].tv_usec = buf.st_mtimensec / 1000UL; #else + times[0].tv_sec = UTIME_OMIT; times[0].tv_nsec = UTIME_OMIT; #endif } @@ -388,8 +395,15 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, tmp -= EPOCH_DIFF; tmp /= 10ULL; +#ifdef ANDROID + tmp /= 10000ULL; + + timevals[0].tv_sec = tmp / 10000ULL; + timevals[0].tv_usec = tmp % 10000ULL; +#else times[0].tv_sec = tmp / 10000000ULL; times[0].tv_nsec = tmp % 10000000ULL; +#endif } if (!lpLastWriteTime) { @@ -400,7 +414,11 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, times[1].tv_sec = buf.st_mtime; times[1].tv_nsec = buf.st_mtimensec; #endif +#elif ANDROID + timevals[1].tv_sec = buf.st_mtime; + timevals[1].tv_usec = buf.st_mtimensec / 1000UL; #else + times[1].tv_sec = UTIME_OMIT; times[1].tv_nsec = UTIME_OMIT; #endif } @@ -411,13 +429,22 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, tmp -= EPOCH_DIFF; tmp /= 10ULL; +#ifdef ANDROID + tmp /= 10000ULL; + + timevals[1].tv_sec = tmp / 10000ULL; + timevals[1].tv_usec = tmp % 10000ULL; +#else times[1].tv_sec = tmp / 10000000ULL; times[1].tv_nsec = tmp % 10000000ULL; +#endif } // TODO: Creation time can not be handled! #ifdef __APPLE__ rc = futimes(fileno(pFile->fp), times); +#elif ANDROID + rc = utimes(pFile->lpFileName, timevals); #else rc = futimens(fileno(pFile->fp), times); #endif From dccf40c2bc8bcf0c91be4686618a8db975067678 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 14:50:27 +0100 Subject: [PATCH 078/128] Fixed duplicate loading of smartcard and printers. --- client/common/cmdline.c | 33 ++++++++++++++++++++------------- include/freerdp/settings.h | 2 ++ libfreerdp/common/settings.c | 17 +++++++++++++++++ 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/client/common/cmdline.c b/client/common/cmdline.c index 510ef716e..76a5b8dee 100644 --- a/client/common/cmdline.c +++ b/client/common/cmdline.c @@ -4,6 +4,7 @@ * * Copyright 2012 Marc-Andre Moreau * Copyright 2014 Norbert Federa + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1311,7 +1312,7 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, } static BOOL freerdp_client_detect_command_line(int argc, char** argv, - DWORD* flags, BOOL ignoreUnknown) + DWORD* flags, BOOL ignoreUnknown) { int old_cli_status; int old_cli_count; @@ -2508,28 +2509,34 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings) { RDPDR_SMARTCARD* smartcard; - smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); + if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD)) + { + smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD)); - if (!smartcard) - return FALSE; + if (!smartcard) + return FALSE; - smartcard->Type = RDPDR_DTYP_SMARTCARD; - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard)) - return FALSE; + smartcard->Type = RDPDR_DTYP_SMARTCARD; + if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard)) + return FALSE; + } } if (settings->RedirectPrinters) { RDPDR_PRINTER* printer; - printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER)); + if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_PRINT)) + { + printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER)); - if (!printer) - return FALSE; + if (!printer) + return FALSE; - printer->Type = RDPDR_DTYP_PRINT; - if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer)) - return FALSE; + printer->Type = RDPDR_DTYP_PRINT; + if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer)) + return FALSE; + } } if (settings->RedirectClipboard) diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h index a53054fab..210e7112c 100644 --- a/include/freerdp/settings.h +++ b/include/freerdp/settings.h @@ -4,6 +4,7 @@ * * Copyright 2009-2011 Jay Sorg * Copyright 2010-2012 Marc-Andre Moreau + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -1435,6 +1436,7 @@ FREERDP_API int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, char* pre FREERDP_API BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device); FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name); +FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type); FREERDP_API RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device); FREERDP_API void freerdp_device_collection_free(rdpSettings* settings); diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c index 859357a2a..bded9d0ec 100644 --- a/libfreerdp/common/settings.c +++ b/libfreerdp/common/settings.c @@ -3,6 +3,7 @@ * Settings Management * * Copyright 2012 Marc-Andre Moreau + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -208,6 +209,22 @@ RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* return NULL; } +RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type) +{ + UINT32 index; + RDPDR_DEVICE* device; + + for (index = 0; index < settings->DeviceCount; index++) + { + device = (RDPDR_DEVICE*) settings->DeviceArray[index]; + + if (device->Type == type) + return device; + } + + return NULL; +} + RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device) { if (device->Type == RDPDR_DTYP_FILESYSTEM) From b7187d04a51a2a55b1a9bd33ef245889acc25548 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 15:21:19 +0100 Subject: [PATCH 079/128] Printer driver from command line now used. --- channels/printer/client/printer_cups.c | 26 ++++++++++++++++++------ channels/printer/client/printer_main.c | 6 ++---- channels/printer/client/printer_main.h | 3 ++- channels/printer/client/printer_win.c | 28 ++++++++++++++++++++------ 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/channels/printer/client/printer_cups.c b/channels/printer/client/printer_cups.c index d498ff6f6..9586f027f 100644 --- a/channels/printer/client/printer_cups.c +++ b/channels/printer/client/printer_cups.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -229,10 +230,12 @@ static void printer_cups_free_printer(rdpPrinter* printer) cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob); free(printer->name); + free(printer->driver); free(printer); } -static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, const char* name, BOOL is_default) +static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, + const char* name, const char* driverName, BOOL is_default) { rdpCupsPrinter* cups_printer; @@ -247,8 +250,17 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c free(cups_printer); return NULL; } - /* This is a generic PostScript printer driver developed by MS, so it should be good in most cases */ - cups_printer->printer.driver = "MS Publisher Imagesetter"; + + if (driverName) + cups_printer->printer.driver = _strdup(driverName); + else + cups_printer->printer.driver = _strdup("MS Publisher Imagesetter"); + if (!cups_printer->printer.driver) + { + free(cups_printer->printer.name); + free(cups_printer); + return NULL; + } cups_printer->printer.is_default = is_default; cups_printer->printer.CreatePrintJob = printer_cups_create_printjob; @@ -279,7 +291,7 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver) if (dest->instance == NULL) { printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver, - dest->name, dest->is_default); + dest->name, NULL, dest->is_default); } } cupsFreeDests(num_dests, dests); @@ -287,11 +299,13 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver) return printers; } -static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name) +static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, + const char* name, const char* driverName) { rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver; - return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? TRUE : FALSE); + return printer_cups_new_printer(cups_driver, name, driverName, + cups_driver->id_sequence == 1 ? TRUE : FALSE); } static rdpCupsPrinterDriver* cups_driver = NULL; diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index fce501a18..74f6d436a 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -489,7 +490,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if (name && name[0]) { - printer = driver->GetPrinter(driver, name); + printer = driver->GetPrinter(driver, name, driver_name); if (!printer) { @@ -497,9 +498,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) return CHANNEL_RC_INITIALIZATION_ERROR; } - if (driver_name && driver_name[0]) - printer->driver = driver_name; - if ((error = printer_register(pEntryPoints, printer))) { WLog_ERR(TAG, "printer_register failed with error %lu!", error); diff --git a/channels/printer/client/printer_main.h b/channels/printer/client/printer_main.h index 3faa3ae7c..3d9b75a9d 100644 --- a/channels/printer/client/printer_main.h +++ b/channels/printer/client/printer_main.h @@ -5,6 +5,7 @@ * Copyright 2010-2011 Vic Lee * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +30,7 @@ typedef struct rdp_printer rdpPrinter; typedef struct rdp_print_job rdpPrintJob; typedef rdpPrinter** (*pcEnumPrinters) (rdpPrinterDriver* driver); -typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name); +typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name, const char* driverName); struct rdp_printer_driver { diff --git a/channels/printer/client/printer_win.c b/channels/printer/client/printer_win.c index f30beebab..dc3664252 100644 --- a/channels/printer/client/printer_win.c +++ b/channels/printer/client/printer_win.c @@ -5,6 +5,7 @@ * Copyright 2012 Gerald Richter * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -175,10 +176,12 @@ static void printer_win_free_printer(rdpPrinter* printer) win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob); free(printer->name); + free(printer->driver); free(printer); } -static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const char* name, const wchar_t* drivername, BOOL is_default) +static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, + const char* name, const WCHAR* drivername, BOOL is_default) { rdpWinPrinter* win_printer; wchar_t wname[256]; @@ -216,7 +219,10 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons } GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, needed, &needed); - win_printer->printer.driver = malloc(1000); + if (drivername) + win_printer->printer.driver = _wcsdup(drivername); + else + win_printer->printer.driver = _wcsdup(prninfo->pDriverName); if (!win_printer->printer.driver) { GlobalFree(prninfo); @@ -224,7 +230,6 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons free(win_printer); return NULL; } - wcstombs_s(&charsConverted, win_printer->printer.driver, 1000, prninfo->pDriverName, _TRUNCATE); return (rdpPrinter*)win_printer; } @@ -274,13 +279,24 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) return printers; } -static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* name) +static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, + const char* name, const char* driverName) { + WCHAR* driverNameW = NULL; rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver; rdpPrinter *myPrinter = NULL; - myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? TRUE : FALSE); - + if (driverName) + { + ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0); + if (!driverNameW) + return NULL; + } + + myPrinter = printer_win_new_printer(win_driver, name, driverNameW, + win_driver->id_sequence == 1 ? TRUE : FALSE); + free(driverNameW); + return myPrinter; } From 8ebe5b99302bdf0590aa7c3facac1998a3a51cea Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 12 Feb 2016 11:32:18 -0800 Subject: [PATCH 080/128] Fix bad malloc size in statvfs --- channels/drive/client/statvfs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/channels/drive/client/statvfs.c b/channels/drive/client/statvfs.c index 60722a535..e92a97557 100644 --- a/channels/drive/client/statvfs.c +++ b/channels/drive/client/statvfs.c @@ -3,6 +3,8 @@ * statvfs emulation for Windows * * Copyright 2012 Gerald Richter + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,17 +31,18 @@ int statvfs(const char *path, struct statvfs *buf) { BOOL res; int len; - LPWSTR unicodestr; + LPWSTR unicodestr = NULL; DWORD lpSectorsPerCluster; DWORD lpBytesPerSector; DWORD lpNumberOfFreeClusters; DWORD lpTotalNumberOfClusters; - len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0); - unicodestr = (LPWSTR) malloc(len); - MultiByteToWideChar(CP_ACP, 0, path, -1, unicodestr, len); + len = ConvertToUnicode(CP_ACP, 0, path, -1, &unicodestr, 0); + if (len <= 0) + return -1; - res = GetDiskFreeSpace(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters); + res = GetDiskFreeSpaceW(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters); + free(unicodestr); buf->f_bsize = lpBytesPerSector; /* file system block size */ buf->f_frsize = 0; /* fragment size */ From 1036f1e296e574aa97cfd1ccd9e6714a91bd6e8b Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 26 Feb 2016 19:25:49 +0100 Subject: [PATCH 081/128] Fixed default visibility. When nothing is declared, only export symbols defined with WINPR_API or FREERDP_API defined. Override this setting if BUILD_TESTING to allow tests access to internal functions usually not exposed. --- CMakeLists.txt | 6 ++++-- libfreerdp/core/freerdp.c | 16 ++++++++-------- libfreerdp/crypto/crypto.c | 2 +- server/shadow/Mac/mac_shadow.c | 2 +- server/shadow/Win/win_shadow.c | 2 +- server/shadow/X11/x11_shadow.c | 2 +- winpr/include/winpr/comm.h | 12 ++++++------ winpr/include/winpr/crypto.h | 4 ++-- winpr/libwinpr/utils/wlog/BinaryAppender.h | 2 +- 9 files changed, 25 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2982da5d3..13e41e9b5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -122,8 +122,10 @@ if(NOT DEFINED BUILD_SHARED_LIBS) endif() endif() -if(NOT DEFINED EXPORT_ALL_SYMBOLS) - set(EXPORT_ALL_SYMBOLS TRUE) +if(BUILD_TESTING) + set(EXPORT_ALL_SYMBOLS TRUE) +elseif(NOT DEFINED EXPORT_ALL_SYMBOLS) + set(EXPORT_ALL_SYMBOLS FALSE) endif() # BSD diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c index 07bb43736..0f45f1284 100644 --- a/libfreerdp/core/freerdp.c +++ b/libfreerdp/core/freerdp.c @@ -398,7 +398,7 @@ BOOL freerdp_shall_disconnect(freerdp* instance) return TRUE; } -FREERDP_API BOOL freerdp_focus_required(freerdp* instance) +BOOL freerdp_focus_required(freerdp* instance) { rdpRdp* rdp; BOOL bRetCode = FALSE; @@ -778,19 +778,19 @@ void freerdp_free(freerdp* instance) free(instance); } -FREERDP_API ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount) { +ULONG freerdp_get_transport_sent(rdpContext* context, BOOL resetCount) { ULONG written = context->rdp->transport->written; if (resetCount) context->rdp->transport->written = 0; return written; } -FREERDP_API HANDLE getChannelErrorEventHandle(rdpContext* context) +HANDLE getChannelErrorEventHandle(rdpContext* context) { return context->channelErrorEvent; } -FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context) +BOOL checkChannelErrorEvent(rdpContext* context) { if (WaitForSingleObject( context->channelErrorEvent, 0) == WAIT_OBJECT_0) { @@ -805,24 +805,24 @@ FREERDP_API BOOL checkChannelErrorEvent(rdpContext* context) * * @return 0 on success, otherwise a Win32 error code */ -FREERDP_API UINT getChannelError(rdpContext* context) +UINT getChannelError(rdpContext* context) { return context->channelErrorNum; } -FREERDP_API const char* getChannelErrorDescription(rdpContext* context) +const char* getChannelErrorDescription(rdpContext* context) { return context->errorDescription; } -FREERDP_API void clearChannelError(rdpContext* context) +void clearChannelError(rdpContext* context) { context->channelErrorNum = 0; memset(context->errorDescription, 0, 500); ResetEvent(context->channelErrorEvent); } -FREERDP_API void setChannelError(rdpContext* context, UINT errorNum, char* description) +void setChannelError(rdpContext* context, UINT errorNum, char* description) { context->channelErrorNum = errorNum; strncpy(context->errorDescription, description, 499); diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index dfb1dbc8b..6a2f0db31 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -334,7 +334,7 @@ char* crypto_cert_subject_common_name(X509* xcert, int* length) return (char*) common_name; } -FREERDP_API void crypto_cert_subject_alt_name_free(int count, int *lengths, +void crypto_cert_subject_alt_name_free(int count, int *lengths, char** alt_name) { int i; diff --git a/server/shadow/Mac/mac_shadow.c b/server/shadow/Mac/mac_shadow.c index 2fd5f96d4..10508c9fe 100644 --- a/server/shadow/Mac/mac_shadow.c +++ b/server/shadow/Mac/mac_shadow.c @@ -660,7 +660,7 @@ macShadowSubsystem* mac_shadow_subsystem_new() return subsystem; } -int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) +FREERDP_API int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) mac_shadow_subsystem_new; pEntryPoints->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free; diff --git a/server/shadow/Win/win_shadow.c b/server/shadow/Win/win_shadow.c index d1dbc5888..0f23b9c05 100644 --- a/server/shadow/Win/win_shadow.c +++ b/server/shadow/Win/win_shadow.c @@ -519,7 +519,7 @@ winShadowSubsystem* win_shadow_subsystem_new() return subsystem; } -int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) +FREERDP_API int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) win_shadow_subsystem_new; pEntryPoints->Free = (pfnShadowSubsystemFree) win_shadow_subsystem_free; diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c index 9a16662a9..7abb218ec 100644 --- a/server/shadow/X11/x11_shadow.c +++ b/server/shadow/X11/x11_shadow.c @@ -1437,7 +1437,7 @@ void x11_shadow_subsystem_free(x11ShadowSubsystem* subsystem) free(subsystem); } -int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) +FREERDP_API int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints) { pEntryPoints->New = (pfnShadowSubsystemNew) x11_shadow_subsystem_new; pEntryPoints->Free = (pfnShadowSubsystemFree) x11_shadow_subsystem_free; diff --git a/winpr/include/winpr/comm.h b/winpr/include/winpr/comm.h index 6f0a23077..d4a33b3dd 100644 --- a/winpr/include/winpr/comm.h +++ b/winpr/include/winpr/comm.h @@ -523,37 +523,37 @@ static const _SERIAL_IOCTL_NAME _SERIAL_IOCTL_NAMES[] = /** * FIXME: got a proper function name and place */ -const char* _comm_serial_ioctl_name(ULONG number); +WINPR_API const char* _comm_serial_ioctl_name(ULONG number); /** * FIXME: got a proper function name and place */ -void _comm_setServerSerialDriver(HANDLE hComm, SERIAL_DRIVER_ID); +WINPR_API void _comm_setServerSerialDriver(HANDLE hComm, SERIAL_DRIVER_ID); /** * FIXME: got a proper function name and place * * permissive mode is disabled by default. */ -BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive); +WINPR_API BOOL _comm_set_permissive(HANDLE hDevice, BOOL permissive); /** * FIXME: to be moved in comm_ioctl.h */ -BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, +WINPR_API BOOL CommDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped); /** * FIXME: to be moved in comm_io.h */ -BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, +WINPR_API BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); /** * FIXME: to be moved in comm_io.h */ -BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, +WINPR_API BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); #ifdef __cplusplus diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 886a5174f..20731a3aa 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -500,9 +500,9 @@ WINPR_API PCCERT_CONTEXT CertFindCertificateInStore(HCERTSTORE hCertStore, DWORD WINPR_API PCCERT_CONTEXT CertEnumCertificatesInStore(HCERTSTORE hCertStore, PCCERT_CONTEXT pPrevCertContext); -DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, +WINPR_API DWORD CertGetNameStringW(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void* pvTypePara, LPWSTR pszNameString, DWORD cchNameString); -DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, +WINPR_API DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType, DWORD dwFlags, void* pvTypePara, LPSTR pszNameString, DWORD cchNameString); #ifdef __cplusplus diff --git a/winpr/libwinpr/utils/wlog/BinaryAppender.h b/winpr/libwinpr/utils/wlog/BinaryAppender.h index 22f1075df..31a9341f8 100644 --- a/winpr/libwinpr/utils/wlog/BinaryAppender.h +++ b/winpr/libwinpr/utils/wlog/BinaryAppender.h @@ -22,6 +22,6 @@ #include "wlog.h" -WINPR_API wLogAppender* WLog_BinaryAppender_New(wLog* log); +wLogAppender* WLog_BinaryAppender_New(wLog* log); #endif /* WINPR_WLOG_BINARY_APPENDER_PRIVATE_H */ From 11c442562aa1b3def0f52211e9348baf3e13e27e Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sat, 27 Feb 2016 11:36:34 +0100 Subject: [PATCH 082/128] Fixed dupliace FREERDP_API declarations. --- server/Windows/wf_interface.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/Windows/wf_interface.c b/server/Windows/wf_interface.c index 0dc8defd0..6a158b140 100644 --- a/server/Windows/wf_interface.c +++ b/server/Windows/wf_interface.c @@ -212,7 +212,7 @@ void wfreerdp_server_free(wfServer* server) WSACleanup(); } -FREERDP_API BOOL wfreerdp_server_is_running(wfServer* server) +BOOL wfreerdp_server_is_running(wfServer* server) { DWORD tStatus; BOOL bRet; @@ -229,7 +229,7 @@ FREERDP_API BOOL wfreerdp_server_is_running(wfServer* server) return FALSE; } -FREERDP_API UINT32 wfreerdp_server_num_peers() +UINT32 wfreerdp_server_num_peers() { wfInfo* wfi; @@ -239,7 +239,7 @@ FREERDP_API UINT32 wfreerdp_server_num_peers() return wfi->peerCount; } -FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) +UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) { wfInfo* wfi; freerdp_peer* peer; @@ -264,7 +264,7 @@ FREERDP_API UINT32 wfreerdp_server_get_peer_hostname(int pId, wchar_t * dstStr) } } -FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) +BOOL wfreerdp_server_peer_is_local(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -284,7 +284,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_local(int pId) } } -FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId) +BOOL wfreerdp_server_peer_is_connected(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -305,7 +305,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_connected(int pId) } } -FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId) +BOOL wfreerdp_server_peer_is_activated(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -325,7 +325,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_activated(int pId) } } -FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) +BOOL wfreerdp_server_peer_is_authenticated(int pId) { wfInfo* wfi; freerdp_peer* peer; @@ -345,7 +345,7 @@ FREERDP_API BOOL wfreerdp_server_peer_is_authenticated(int pId) } } -FREERDP_API void wfreerdp_server_register_callback_event(cbCallback cb) +void wfreerdp_server_register_callback_event(cbCallback cb) { cbEvent = cb; } From 86436bc4e18334d5931bc8e082191eebc26bf090 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sat, 27 Feb 2016 22:13:59 +0100 Subject: [PATCH 083/128] Added API export for uwac. --- uwac/include/uwac/uwac-tools.h | 6 ++-- uwac/include/uwac/uwac.h | 58 +++++++++++++++++++--------------- 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/uwac/include/uwac/uwac-tools.h b/uwac/include/uwac/uwac-tools.h index 600727b5a..07813fbd5 100644 --- a/uwac/include/uwac/uwac-tools.h +++ b/uwac/include/uwac/uwac-tools.h @@ -40,13 +40,13 @@ typedef struct uwac_touch_automata UwacTouchAutomata; * * @param automata */ -void UwacTouchAutomataInit(UwacTouchAutomata *automata); +UWAC_API void UwacTouchAutomataInit(UwacTouchAutomata *automata); /** * * @param automata */ -void UwacTouchAutomataReset(UwacTouchAutomata *automata); +UWAC_API void UwacTouchAutomataReset(UwacTouchAutomata *automata); /** @@ -55,6 +55,6 @@ void UwacTouchAutomataReset(UwacTouchAutomata *automata); * @param event * @return */ -bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event); +UWAC_API bool UwacTouchAutomataInjectEvent(UwacTouchAutomata *automata, UwacEvent *event); #endif /* __UWAC_TOOLS_H_ */ diff --git a/uwac/include/uwac/uwac.h b/uwac/include/uwac/uwac.h index 39fafa68e..fd422f4b5 100644 --- a/uwac/include/uwac/uwac.h +++ b/uwac/include/uwac/uwac.h @@ -26,6 +26,12 @@ #include #include +#if __GNUC__ >= 4 + #define UWAC_API __attribute__ ((visibility("default"))) +#else + #define UWAC_API +#endif + typedef struct uwac_size UwacSize; typedef struct uwac_display UwacDisplay; typedef struct uwac_output UwacOutput; @@ -238,7 +244,7 @@ extern "C" { * * @param handler */ -void UwacInstallErrorHandler(UwacErrorHandler handler); +UWAC_API void UwacInstallErrorHandler(UwacErrorHandler handler); /** @@ -248,7 +254,7 @@ void UwacInstallErrorHandler(UwacErrorHandler handler); * @param name the name of the display to open * @return the created UwacDisplay object */ -UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err); +UWAC_API UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err); /** * closes the corresponding UwacDisplay @@ -256,7 +262,7 @@ UwacDisplay *UwacOpenDisplay(const char *name, UwacReturnCode *err); * @param pdisplay a pointer on the display to close * @return UWAC_SUCCESS if the operation was successful, the corresponding error otherwise */ -UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay); +UWAC_API UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay); /** * Returns the file descriptor associated with the UwacDisplay, this is useful when @@ -265,7 +271,7 @@ UwacReturnCode UwacCloseDisplay(UwacDisplay **pdisplay); * @param display an opened UwacDisplay * @return the corresponding descriptor */ -int UwacDisplayGetFd(UwacDisplay *display); +UWAC_API int UwacDisplayGetFd(UwacDisplay *display); /** * Returns a human readable form of a Uwac error code @@ -273,7 +279,7 @@ int UwacDisplayGetFd(UwacDisplay *display); * @param error the error number * @return the associated string */ -const char *UwacErrorString(UwacReturnCode error); +UWAC_API const char *UwacErrorString(UwacReturnCode error); /** * returns the last error that occurred on a display @@ -281,7 +287,7 @@ const char *UwacErrorString(UwacReturnCode error); * @param display the display * @return the last error that have been set for this display */ -UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display); +UWAC_API UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display); /** * retrieves the version of a given interface @@ -291,7 +297,7 @@ UwacReturnCode UwacDisplayGetLastError(const UwacDisplay *display); * @param version the output variable for the version * @return UWAC_SUCCESS if the interface was found, UWAC_NOT_FOUND otherwise */ -UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version); +UWAC_API UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, const char *name, uint32_t *version); /** * returns the number SHM formats that have been reported by the compositor @@ -299,7 +305,7 @@ UwacReturnCode UwacDisplayQueryInterfaceVersion(const UwacDisplay *display, cons * @param display a connected UwacDisplay * @return the number of SHM formats supported */ -uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display); +UWAC_API uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display); /** * returns the supported ShmFormats @@ -310,7 +316,7 @@ uint32_t UwacDisplayQueryGetNbShmFormats(UwacDisplay *display); * @param filled the number of filled entries in the formats array * @return UWAC_SUCCESS on success, an error otherwise */ -UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled); +UWAC_API UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_shm_format *formats, int formats_size, int *filled); /** * returns the number of registered outputs @@ -318,7 +324,7 @@ UwacReturnCode UwacDisplayQueryShmFormats(const UwacDisplay *display, enum wl_sh * @param display the display to query * @return the number of outputs */ -uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display); +UWAC_API uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display); /** * retrieve a particular UwacOutput object @@ -327,7 +333,7 @@ uint32_t UwacDisplayGetNbOutputs(UwacDisplay *display); * @param index index of the output * @return the given UwacOutput, NULL if something failed (so you should query UwacDisplayGetLastError() to have the reason) */ -UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index); +UWAC_API UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index); /** * retrieve the resolution of a given UwacOutput @@ -336,7 +342,7 @@ UwacOutput *UwacDisplayGetOutput(UwacDisplay *display, int index); * @param resolution a pointer on the * @return UWAC_SUCCESS on success */ -UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution); +UWAC_API UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution); /** @@ -348,7 +354,7 @@ UwacReturnCode UwacOutputGetResolution(UwacOutput *output, UwacSize *resolution) * @param format format to use for the SHM surface * @return the created UwacWindow, NULL if something failed (use UwacDisplayGetLastError() to know more about this) */ -UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format); +UWAC_API UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t height, enum wl_shm_format format); /** * destroys the corresponding UwacWindow @@ -356,7 +362,7 @@ UwacWindow *UwacCreateWindowShm(UwacDisplay *display, uint32_t width, uint32_t h * @param window a pointer on the UwacWindow to destroy * @return if the operation completed successfully */ -UwacReturnCode UwacDestroyWindow(UwacWindow **window); +UWAC_API UwacReturnCode UwacDestroyWindow(UwacWindow **window); /** * Sets the region that should be considered opaque to the compositor. @@ -368,7 +374,7 @@ UwacReturnCode UwacDestroyWindow(UwacWindow **window); * @param height * @return UWAC_SUCCESS on success, an error otherwise */ -UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); +UWAC_API UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); /** * Sets the region of the window that can trigger input events @@ -380,14 +386,14 @@ UwacReturnCode UwacWindowSetOpaqueRegion(UwacWindow *window, uint32_t x, uint32_ * @param height * @return */ -UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); +UWAC_API UwacReturnCode UwacWindowSetInputRegion(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); /** * retrieves a pointer on the current window content to draw a frame * @param window the UwacWindow * @return a pointer on the current window content */ -void *UwacWindowGetDrawingBuffer(UwacWindow *window); +UWAC_API void *UwacWindowGetDrawingBuffer(UwacWindow *window); /** * sets a rectangle as dirty for the next frame of a window @@ -399,7 +405,7 @@ void *UwacWindowGetDrawingBuffer(UwacWindow *window); * @param height the height of the dirty rectangle * @return UWAC_SUCCESS on success, an Uwac error otherwise */ -UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); +UWAC_API UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, uint32_t width, uint32_t height); /** * Sends a frame to the compositor with the content of the drawing buffer @@ -408,7 +414,7 @@ UwacReturnCode UwacWindowAddDamage(UwacWindow *window, uint32_t x, uint32_t y, u * @param copyContentForNextFrame if true the content to display is copied in the next drawing buffer * @return UWAC_SUCCESS if the operation was successful */ -UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame); +UWAC_API UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNextFrame); /** * returns the geometry of the given UwacWindows @@ -417,7 +423,7 @@ UwacReturnCode UwacWindowSubmitBuffer(UwacWindow *window, bool copyContentForNex * @param geometry the geometry to fill * @return UWAC_SUCCESS on success, an Uwac error otherwise */ -UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry); +UWAC_API UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry); /** * Sets or unset the fact that the window is set fullscreen. After this call the @@ -429,7 +435,7 @@ UwacReturnCode UwacWindowGetGeometry(UwacWindow *window, UwacSize *geometry); * @param isFullscreen set or unset fullscreen * @return UWAC_SUCCESS if the operation was a success */ -UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen); +UWAC_API UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *output, bool isFullscreen); /** * When possible (depending on the shell) sets the title of the UwacWindow @@ -437,7 +443,7 @@ UwacReturnCode UwacWindowSetFullscreenState(UwacWindow *window, UwacOutput *outp * @param window the UwacWindow * @param name title */ -void UwacWindowSetTitle(UwacWindow *window, const char *name); +UWAC_API void UwacWindowSetTitle(UwacWindow *window, const char *name); /** * @@ -445,7 +451,7 @@ void UwacWindowSetTitle(UwacWindow *window, const char *name); * @param timeout * @return */ -int UwacDisplayDispatch(UwacDisplay *display, int timeout); +UWAC_API int UwacDisplayDispatch(UwacDisplay *display, int timeout); /** * Returns if you have some pending events, and you can UwacNextEvent() without blocking @@ -453,7 +459,7 @@ int UwacDisplayDispatch(UwacDisplay *display, int timeout); * @param display the UwacDisplay * @return if there's some pending events */ -bool UwacHasEvent(UwacDisplay *display); +UWAC_API bool UwacHasEvent(UwacDisplay *display); /** Waits until an event occurs, and when it's there copy the event from the queue to * event. @@ -462,7 +468,7 @@ bool UwacHasEvent(UwacDisplay *display); * @param event the event to fill * @return if the operation completed successfully */ -UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event); +UWAC_API UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event); /** @@ -471,7 +477,7 @@ UwacReturnCode UwacNextEvent(UwacDisplay *display, UwacEvent *event); * @param seat the UwacSeat * @return the name of the seat */ -const char *UwacSeatGetName(const UwacSeat *seat); +UWAC_API const char *UwacSeatGetName(const UwacSeat *seat); #ifdef __cplusplus } From 492984497147d061339727d450c68869d8e16855 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sat, 27 Feb 2016 22:16:41 +0100 Subject: [PATCH 084/128] Fixed const argument for Stream_Write. --- winpr/include/winpr/stream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index a9abb78c5..5c1cc9076 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -229,7 +229,7 @@ static INLINE void Stream_Write_UINT64(wStream* s, UINT64 _v) *_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; *_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; } -static INLINE void Stream_Write(wStream* s, void* _b, size_t _n) +static INLINE void Stream_Write(wStream* s, const void* _b, size_t _n) { struct _wStream* _s = (struct _wStream*)s; memcpy(_s->pointer, (_b), (_n)); From 5805ba8e52763b4e15ef9cb2b03b8f8a22559c47 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sat, 27 Feb 2016 22:39:45 +0100 Subject: [PATCH 085/128] Removed crypto_nonce. --- include/freerdp/crypto/crypto.h | 1 - libfreerdp/core/connection.c | 2 +- libfreerdp/core/gcc.c | 2 +- libfreerdp/core/license.c | 4 ++-- libfreerdp/crypto/crypto.c | 5 ----- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 89b3eef26..3d112d4e4 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -92,7 +92,6 @@ FREERDP_API int crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32 FREERDP_API int crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); FREERDP_API int crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output); FREERDP_API void crypto_reverse(BYTE* data, int length); -FREERDP_API void crypto_nonce(BYTE* nonce, int size); FREERDP_API char* crypto_base64_encode(const BYTE* data, int length); FREERDP_API void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length); diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 44b6deb5c..111924c7d 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -437,7 +437,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) if (!settings->ClientRandom) return FALSE; - crypto_nonce(settings->ClientRandom, settings->ClientRandomLength); + winpr_RAND(settings->ClientRandom, settings->ClientRandomLength); key_len = settings->RdpServerCertificate->cert_info.ModulusLength; mod = settings->RdpServerCertificate->cert_info.Modulus; exp = settings->RdpServerCertificate->cert_info.exponent; diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 86aff0004..2d63fa777 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -1349,7 +1349,7 @@ BOOL gcc_write_server_security_data(wStream* s, rdpMcs* mcs) settings->ServerRandomLength = serverRandomLen; settings->ServerRandom = (BYTE*) malloc(serverRandomLen); - crypto_nonce(settings->ServerRandom, serverRandomLen); + winpr_RAND(settings->ServerRandom, serverRandomLen); Stream_Write(s, settings->ServerRandom, serverRandomLen); sigData = Stream_Pointer(s); diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index bfb988192..4852f9bb5 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -329,10 +329,10 @@ void license_generate_randoms(rdpLicense* license) ZeroMemory(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */ ZeroMemory(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ #ifndef LICENSE_NULL_CLIENT_RANDOM - crypto_nonce(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */ + winpr_RAND(license->ClientRandom, CLIENT_RANDOM_LENGTH); /* ClientRandom */ #endif #ifndef LICENSE_NULL_PREMASTER_SECRET - crypto_nonce(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ + winpr_RAND(license->PremasterSecret, PREMASTER_SECRET_LENGTH); /* PremasterSecret */ #endif } diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index dfb1dbc8b..00059b75f 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -240,11 +240,6 @@ void crypto_reverse(BYTE* data, int length) } } -void crypto_nonce(BYTE* nonce, int size) -{ - winpr_RAND((void*) nonce, size); -} - char* crypto_cert_fingerprint(X509* xcert) { int i = 0; From 238ff3b315219b6b2c1c98624149531f23f41496 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sat, 27 Feb 2016 23:28:49 +0100 Subject: [PATCH 086/128] Unified encryption functions. --- include/freerdp/crypto/crypto.h | 16 +---------- libfreerdp/core/connection.c | 16 +++++------ libfreerdp/core/rdp.c | 8 +++--- libfreerdp/core/rdp.h | 4 +-- libfreerdp/core/security.c | 10 +++++-- libfreerdp/crypto/crypto.c | 48 -------------------------------- winpr/include/winpr/crypto.h | 3 +- winpr/libwinpr/crypto/cipher.c | 45 +++++++++++++++++++++++------- winpr/libwinpr/crypto/crypto.c | 49 ++++++++++++++++++++++----------- 9 files changed, 93 insertions(+), 106 deletions(-) diff --git a/include/freerdp/crypto/crypto.h b/include/freerdp/crypto/crypto.h index 3d112d4e4..bcd5ee60a 100644 --- a/include/freerdp/crypto/crypto.h +++ b/include/freerdp/crypto/crypto.h @@ -38,11 +38,7 @@ #include #include - -struct crypto_des3_struct -{ - EVP_CIPHER_CTX des3_ctx; -}; +#include struct crypto_cert_struct { @@ -54,18 +50,8 @@ struct crypto_cert_struct extern "C" { #endif -typedef struct crypto_des3_struct* CryptoDes3; - -FREERDP_API CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec); -FREERDP_API CryptoDes3 crypto_des3_decrypt_init(const BYTE* key, const BYTE* ivec); -FREERDP_API BOOL crypto_des3_encrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE *out_data); -FREERDP_API BOOL crypto_des3_decrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE* out_data); -FREERDP_API void crypto_des3_free(CryptoDes3 des3); - typedef struct crypto_cert_struct* CryptoCert; -#include - FREERDP_API CryptoCert crypto_cert_read(BYTE* data, UINT32 length); FREERDP_API char* crypto_cert_fingerprint(X509* xcert); FREERDP_API char* crypto_cert_subject(X509* xcert); diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 111924c7d..496e85822 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -490,14 +490,14 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); - if (!rdp->fips_encrypt) + if (!winpr_Cipher_New(&rdp->fips_encrypt, WINPR_CIPHER_DES_EDE3_CBC, + WINPR_ENCRYPT, rdp->fips_encrypt_key, fips_ivec)) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } - rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); - if (!rdp->fips_decrypt) + if (!winpr_Cipher_New(&rdp->fips_decrypt, WINPR_CIPHER_DES_EDE3_CBC, + WINPR_DECRYPT, rdp->fips_decrypt_key, fips_ivec)) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; @@ -597,15 +597,15 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - rdp->fips_encrypt = crypto_des3_encrypt_init(rdp->fips_encrypt_key, fips_ivec); - if (!rdp->fips_encrypt) + if (!winpr_Cipher_New(&rdp->fips_encrypt, WINPR_CIPHER_DES_EDE3_CBC, + WINPR_ENCRYPT, rdp->fips_encrypt_key, fips_ivec)) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } - rdp->fips_decrypt = crypto_des3_decrypt_init(rdp->fips_decrypt_key, fips_ivec); - if (!rdp->fips_decrypt) + if (!winpr_Cipher_New(&rdp->fips_decrypt, WINPR_CIPHER_DES_EDE3_CBC, + WINPR_DECRYPT, rdp->fips_decrypt_key, fips_ivec)) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index a8276caa6..026091aec 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1602,13 +1602,13 @@ void rdp_reset(rdpRdp* rdp) if (rdp->fips_encrypt) { - crypto_des3_free(rdp->fips_encrypt); + winpr_Cipher_Free(rdp->fips_encrypt); rdp->fips_encrypt = NULL; } if (rdp->fips_decrypt) { - crypto_des3_free(rdp->fips_decrypt); + winpr_Cipher_Free(rdp->fips_decrypt); rdp->fips_decrypt = NULL; } @@ -1663,8 +1663,8 @@ void rdp_free(rdpRdp* rdp) { winpr_RC4_Final(rdp->rc4_decrypt_key); winpr_RC4_Final(rdp->rc4_encrypt_key); - crypto_des3_free(rdp->fips_encrypt); - crypto_des3_free(rdp->fips_decrypt); + winpr_Cipher_Free(rdp->fips_encrypt); + winpr_Cipher_Free(rdp->fips_decrypt); free(rdp->fips_hmac); freerdp_settings_free(rdp->settings); freerdp_settings_free(rdp->settingsCopy); diff --git a/libfreerdp/core/rdp.h b/libfreerdp/core/rdp.h index 1fb88effc..ef8e0dc4a 100644 --- a/libfreerdp/core/rdp.h +++ b/libfreerdp/core/rdp.h @@ -154,8 +154,8 @@ struct rdp_rdp WINPR_RC4_CTX* rc4_encrypt_key; int encrypt_use_count; int encrypt_checksum_use_count; - struct crypto_des3_struct* fips_encrypt; - struct crypto_des3_struct* fips_decrypt; + WINPR_CIPHER_CTX* fips_encrypt; + WINPR_CIPHER_CTX* fips_decrypt; WINPR_HMAC_CTX* fips_hmac; UINT32 sec_flags; BOOL do_crypt; diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 5484476a2..0d67c8aac 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -646,7 +646,9 @@ BOOL security_hmac_signature(const BYTE* data, int length, BYTE* output, rdpRdp* BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp) { - if (!crypto_des3_encrypt(rdp->fips_encrypt, length, data, data)) + size_t olen; + + if (!winpr_Cipher_Update(rdp->fips_encrypt, data, length, data, &olen)) return FALSE; rdp->encrypt_use_count++; return TRUE; @@ -654,7 +656,11 @@ BOOL security_fips_encrypt(BYTE* data, int length, rdpRdp* rdp) BOOL security_fips_decrypt(BYTE* data, int length, rdpRdp* rdp) { - return crypto_des3_decrypt(rdp->fips_decrypt, length, data, data); + size_t olen; + + if (!winpr_Cipher_Update(rdp->fips_decrypt, data, length, data, &olen)) + return FALSE; + return TRUE; } BOOL security_fips_check_signature(const BYTE* data, int length, const BYTE* sig, rdpRdp* rdp) diff --git a/libfreerdp/crypto/crypto.c b/libfreerdp/crypto/crypto.c index 00059b75f..e7175ad8d 100644 --- a/libfreerdp/crypto/crypto.c +++ b/libfreerdp/crypto/crypto.c @@ -29,54 +29,6 @@ #define TAG FREERDP_TAG("crypto") -CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec) -{ - CryptoDes3 des3 = malloc(sizeof(*des3)); - if (!des3) - return NULL; - - EVP_CIPHER_CTX_init(&des3->des3_ctx); - EVP_EncryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec); - EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0); - return des3; -} - -CryptoDes3 crypto_des3_decrypt_init(const BYTE* key, const BYTE* ivec) -{ - CryptoDes3 des3 = malloc(sizeof(*des3)); - if (!des3) - return NULL; - - EVP_CIPHER_CTX_init(&des3->des3_ctx); - EVP_DecryptInit_ex(&des3->des3_ctx, EVP_des_ede3_cbc(), NULL, key, ivec); - EVP_CIPHER_CTX_set_padding(&des3->des3_ctx, 0); - return des3; -} - -BOOL crypto_des3_encrypt(CryptoDes3 des3, UINT32 length, const BYTE* in_data, BYTE* out_data) -{ - int len; - return EVP_EncryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length) == 1; -} - -BOOL crypto_des3_decrypt(CryptoDes3 des3, UINT32 length, const BYTE* in_data, BYTE* out_data) -{ - int len; - int ret = EVP_DecryptUpdate(&des3->des3_ctx, out_data, &len, in_data, length); - - if (length != len) - abort(); /* TODO */ - return ret == 1; -} - -void crypto_des3_free(CryptoDes3 des3) -{ - if (des3 == NULL) - return; - EVP_CIPHER_CTX_cleanup(&des3->des3_ctx); - free(des3); -} - CryptoCert crypto_cert_read(BYTE* data, UINT32 length) { CryptoCert cert = malloc(sizeof(*cert)); diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 886a5174f..b831da8a3 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -1016,9 +1016,10 @@ typedef union _WINPR_CIPHER_CTX WINPR_CIPHER_CTX; extern "C" { #endif -WINPR_API BOOL winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv); +WINPR_API BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** ctx, int cipher, int op, const BYTE* key, const BYTE* iv); WINPR_API BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen); WINPR_API BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen); +WINPR_API void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx); #ifdef __cplusplus } diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index 7c5461273..b8eb9d671 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -500,26 +500,39 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) } #endif -BOOL winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* key, const BYTE* iv) +BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* key, const BYTE* iv) { + WINPR_CIPHER_CTX* ctx; #if defined(WITH_OPENSSL) int operation; const EVP_CIPHER* evp; + EVP_CIPHER_CTX* octx; +#elif defined(WITH_MBEDTLS) + int key_bitlen; + mbedtls_operation_t operation; + mbedtls_cipher_type_t cipher_type; + const mbedtls_cipher_info_t* cipher_info; +#endif + + ctx = calloc(1, sizeof(WINPR_CIPHER_CTX)); + if (!ctx) + return FALSE; + +#if defined(WITH_OPENSSL) + octx = (EVP_CIPHER_CTX*)ctx; evp = winpr_openssl_get_evp_cipher(cipher); if (!evp) return FALSE; operation = (op == WINPR_ENCRYPT) ? 1 : 0; - EVP_CIPHER_CTX_init((EVP_CIPHER_CTX*) ctx); + EVP_CIPHER_CTX_init(octx); - if (EVP_CipherInit_ex((EVP_CIPHER_CTX*) ctx, evp, NULL, key, iv, operation) != 1) + if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1) return FALSE; + + EVP_CIPHER_CTX_set_padding(octx, 0); #elif defined(WITH_MBEDTLS) - int key_bitlen; - mbedtls_operation_t operation; - mbedtls_cipher_type_t cipher_type; - const mbedtls_cipher_info_t* cipher_info; cipher_type = winpr_mbedtls_get_cipher_type(cipher); cipher_info = mbedtls_cipher_info_from_type(cipher_type); @@ -537,6 +550,8 @@ BOOL winpr_Cipher_Init(WINPR_CIPHER_CTX* ctx, int cipher, int op, const BYTE* ke if (mbedtls_cipher_setkey((mbedtls_cipher_context_t*) ctx, key, key_bitlen, operation) != 0) return FALSE; #endif + + *cctx = ctx; return TRUE; } @@ -564,17 +579,27 @@ BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) if (EVP_CipherFinal_ex((EVP_CIPHER_CTX*) ctx, output, &outl) != 1) return FALSE; - EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx); *olen = (size_t) outl; #elif defined(WITH_MBEDTLS) if (mbedtls_cipher_finish((mbedtls_cipher_context_t*) ctx, output, olen) != 0) return FALSE; - - mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx); #endif return TRUE; } +void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx) +{ + if (!ctx) + return; + +#if defined(WITH_OPENSSL) + EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx); +#elif defined(WITH_MBEDTLS) + mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx); +#endif +} + + /** * Key Generation */ diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c index 9e3064e84..5b0a68a7f 100644 --- a/winpr/libwinpr/crypto/crypto.c +++ b/winpr/libwinpr/crypto/crypto.c @@ -150,7 +150,7 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { BYTE* pCipherText; size_t cbOut, cbFinal; - WINPR_CIPHER_CTX enc; + WINPR_CIPHER_CTX* enc; BYTE randomKey[256]; WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; @@ -186,27 +186,34 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) pCipherText = (BYTE*) malloc(cbOut); if (!pCipherText) - { - free(pMemBlock); - return FALSE; - } + goto out; - winpr_Cipher_Init(&enc, WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key, pMemBlock->iv); - winpr_Cipher_Update(&enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut); - winpr_Cipher_Final(&enc, pCipherText + cbOut, &cbFinal); + if (!winpr_Cipher_New(&enc, WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key, pMemBlock->iv)) + goto out; + if (!winpr_Cipher_Update(enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut)) + goto out; + if (!winpr_Cipher_Final(enc, pCipherText + cbOut, &cbFinal)) + goto out; + winpr_Cipher_Free(enc); CopyMemory(pMemBlock->pData, pCipherText, pMemBlock->cbData); free(pCipherText); return ListDictionary_Add(g_ProtectedMemoryBlocks, pData, pMemBlock); +out: + free (pMemBlock); + free (pCipherText); + winpr_Cipher_Free(enc); + + return FALSE; } BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { - BYTE* pPlainText; + BYTE* pPlainText = NULL; size_t cbOut, cbFinal; - WINPR_CIPHER_CTX dec; - WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; + WINPR_CIPHER_CTX* dec = NULL; + WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock = NULL; if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS) return FALSE; @@ -217,18 +224,22 @@ BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData); if (!pMemBlock) - return FALSE; + goto out; cbOut = pMemBlock->cbData + 16 - 1; pPlainText = (BYTE*) malloc(cbOut); if (!pPlainText) - return FALSE; + goto out; - winpr_Cipher_Init(&dec, WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key, pMemBlock->iv); - winpr_Cipher_Update(&dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut); - winpr_Cipher_Final(&dec, pPlainText + cbOut, &cbFinal); + if (!winpr_Cipher_New(&dec, WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key, pMemBlock->iv)) + goto out; + if (!winpr_Cipher_Update(dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut)) + goto out; + if (!winpr_Cipher_Final(dec, pPlainText + cbOut, &cbFinal)) + goto out; + winpr_Cipher_Free(dec); CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData); SecureZeroMemory(pPlainText, pMemBlock->cbData); @@ -239,6 +250,12 @@ BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) free(pMemBlock); return TRUE; + +out: + free(pPlainText); + free(pMemBlock); + winpr_Cipher_Free(dec); + return FALSE; } BOOL CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy, From 17139b9fe69b024a053473e43b9f5dc813edd131 Mon Sep 17 00:00:00 2001 From: "zihao.jiang" Date: Sat, 27 Feb 2016 02:20:49 +0800 Subject: [PATCH 087/128] android: Fix sound redirection. After #3097, the java side pass command line argument to JNI for freerdp settings. However there's several issues need to be fixed: 1. The argument /sound should be appended if freerdp is required to play sound at local device 2. The option value for "audio-mode" is not correct. It should match the definition in client/common/cmdline.c /* Audio Mode */ define AUDIO_MODE_REDIRECT 0 /* Bring to this computer */ define AUDIO_MODE_PLAY_ON_SERVER 1 /* Leave at remote computer */ define AUDIO_MODE_NONE 2 /* Do not play */ 3. Uncomment support for WAVE_FORMAT_PCM in audin. I tested on my android phone and Nokia N1 tablet. It works on both device --- channels/audin/client/opensles/audin_opensl_es.c | 3 --- .../com/freerdp/freerdpcore/services/LibFreeRDP.java | 9 ++++++--- .../freeRDPCore/src/main/res/values-de/strings.xml | 4 ++-- .../freeRDPCore/src/main/res/values-es/strings.xml | 4 ++-- .../freeRDPCore/src/main/res/values-fr/strings.xml | 4 ++-- .../freeRDPCore/src/main/res/values-nl/strings.xml | 4 ++-- .../freeRDPCore/src/main/res/values-zh/strings.xml | 4 ++-- .../Studio/freeRDPCore/src/main/res/values/strings.xml | 4 ++-- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 51917e4a3..a9123c537 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -218,8 +218,6 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f switch (format->wFormatTag) { - /* TODO: Deactivated, untested */ -#if 0 case WAVE_FORMAT_PCM: /* PCM */ if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && @@ -229,7 +227,6 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f return TRUE; } break; -#endif /* TODO: Deactivated format, does not work, find out why */ // case WAVE_FORMAT_ADPCM: /* IMA ADPCM */ case WAVE_FORMAT_DVI_ADPCM: diff --git a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java index 0d77c12ff..d1d337a6a 100644 --- a/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java +++ b/client/Android/Studio/freeRDPCore/src/main/java/com/freerdp/freerdpcore/services/LibFreeRDP.java @@ -257,10 +257,13 @@ public class LibFreeRDP { } } - /* 0 ... disable - 1 ... local - 2 ... remote */ + /* 0 ... local + 1 ... remote + 2 ... disable */ args.add("/audio-mode:" + String.valueOf(advanced.getRedirectSound())); + if (advanced.getRedirectSound() == 0) { + args.add("/sound"); + } if (advanced.getRedirectMicrophone()) { args.add("/microphone"); diff --git a/client/Android/Studio/freeRDPCore/src/main/res/values-de/strings.xml b/client/Android/Studio/freeRDPCore/src/main/res/values-de/strings.xml index 491f11d8a..0c724e88c 100644 --- a/client/Android/Studio/freeRDPCore/src/main/res/values-de/strings.xml +++ b/client/Android/Studio/freeRDPCore/src/main/res/values-de/strings.xml @@ -119,9 +119,9 @@ Auf Client abspielen - 0 - 1 2 + 1 + 0 Mikrophon umleiten Sicherheit diff --git a/client/Android/Studio/freeRDPCore/src/main/res/values-es/strings.xml b/client/Android/Studio/freeRDPCore/src/main/res/values-es/strings.xml index 161629954..74ef6fe4e 100644 --- a/client/Android/Studio/freeRDPCore/src/main/res/values-es/strings.xml +++ b/client/Android/Studio/freeRDPCore/src/main/res/values-es/strings.xml @@ -122,9 +122,9 @@ Play on Device - 0 - 1 2 + 1 + 0 Redirect Microphone Seguridad diff --git a/client/Android/Studio/freeRDPCore/src/main/res/values-fr/strings.xml b/client/Android/Studio/freeRDPCore/src/main/res/values-fr/strings.xml index be4be240c..abb6636f5 100644 --- a/client/Android/Studio/freeRDPCore/src/main/res/values-fr/strings.xml +++ b/client/Android/Studio/freeRDPCore/src/main/res/values-fr/strings.xml @@ -121,9 +121,9 @@ Play on Device - 0 - 1 2 + 1 + 0 Redirect Microphone "Securité" diff --git a/client/Android/Studio/freeRDPCore/src/main/res/values-nl/strings.xml b/client/Android/Studio/freeRDPCore/src/main/res/values-nl/strings.xml index 6167cb12f..3f23c0e3a 100644 --- a/client/Android/Studio/freeRDPCore/src/main/res/values-nl/strings.xml +++ b/client/Android/Studio/freeRDPCore/src/main/res/values-nl/strings.xml @@ -122,9 +122,9 @@ Play on Device - 0 - 1 2 + 1 + 0 Redirect Microphone Beveiliging diff --git a/client/Android/Studio/freeRDPCore/src/main/res/values-zh/strings.xml b/client/Android/Studio/freeRDPCore/src/main/res/values-zh/strings.xml index bb98f94c9..3b57c00d8 100644 --- a/client/Android/Studio/freeRDPCore/src/main/res/values-zh/strings.xml +++ b/client/Android/Studio/freeRDPCore/src/main/res/values-zh/strings.xml @@ -119,9 +119,9 @@ 在此设备上播放 - 0 - 1 2 + 1 + 0 麦克风重定向 连接协议 diff --git a/client/Android/Studio/freeRDPCore/src/main/res/values/strings.xml b/client/Android/Studio/freeRDPCore/src/main/res/values/strings.xml index 495c9b85c..611382f02 100644 --- a/client/Android/Studio/freeRDPCore/src/main/res/values/strings.xml +++ b/client/Android/Studio/freeRDPCore/src/main/res/values/strings.xml @@ -122,9 +122,9 @@ Play on Device - 0 - 1 2 + 1 + 0 Redirect Microphone Security From 176ad52bd59e0fe568e9d23eab292e0f7f5ff6c3 Mon Sep 17 00:00:00 2001 From: "zihao.jiang" Date: Sat, 27 Feb 2016 01:07:30 +0800 Subject: [PATCH 088/128] server/shadow: Export API to set built-in subsystem modules for freerdp-shadow-subsystem --- include/freerdp/server/shadow.h | 2 + server/shadow/CMakeLists.txt | 9 ++- server/shadow/shadow.c | 24 +----- server/shadow/shadow_subsystem_builtin.c | 96 ++++++++++++++++++++++++ 4 files changed, 105 insertions(+), 26 deletions(-) create mode 100644 server/shadow/shadow_subsystem_builtin.c diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h index 5e8c71bf6..49bd0564a 100644 --- a/include/freerdp/server/shadow.h +++ b/include/freerdp/server/shadow.h @@ -277,7 +277,9 @@ typedef struct _SHADOW_MSG_OUT_AUDIO_OUT_VOLUME SHADOW_MSG_OUT_AUDIO_OUT_VOLUME; extern "C" { #endif +FREERDP_API void shadow_subsystem_set_entry_builtin(const char* name); FREERDP_API void shadow_subsystem_set_entry(pfnShadowSubsystemEntry pEntry); + FREERDP_API int shadow_subsystem_pointer_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied, UINT32 width, UINT32 height, SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* pointerColor); diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 67c3aa2a5..13c0f480d 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -97,6 +97,9 @@ set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") set(MODULE_NAME "freerdp-shadow-subsystem") set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_SUBSYSTEM") +set(${MODULE_PREFIX}_SRCS + shadow_subsystem_builtin.c) + if(WIN32) set(WITH_SHADOW_WIN 1) elseif(X11_FOUND AND NOT APPLE) @@ -245,15 +248,15 @@ set(${MODULE_PREFIX}_MAC_SRCS if(WITH_SHADOW_WIN) add_definitions(-DWITH_SHADOW_WIN) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) + list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_WIN_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_WIN_LIBS}) elseif(WITH_SHADOW_X11) add_definitions(-DWITH_SHADOW_X11) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_X11_SRCS}) + list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_X11_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_X11_LIBS}) elseif(WITH_SHADOW_MAC) add_definitions(-DWITH_SHADOW_MAC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_MAC_SRCS}) + list(APPEND ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_MAC_SRCS}) list(APPEND ${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_MAC_LIBS}) endif() diff --git a/server/shadow/shadow.c b/server/shadow/shadow.c index 83a834bc0..bc985192e 100644 --- a/server/shadow/shadow.c +++ b/server/shadow/shadow.c @@ -37,18 +37,6 @@ static BOOL g_MessagePump = FALSE; #include -#ifdef WITH_SHADOW_X11 -extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -#endif - -#ifdef WITH_SHADOW_MAC -extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -#endif - -#ifdef WITH_SHADOW_WIN -extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); -#endif - int main(int argc, char** argv) { MSG msg; @@ -56,17 +44,7 @@ int main(int argc, char** argv) DWORD dwExitCode; rdpShadowServer* server; -#ifdef WITH_SHADOW_X11 - shadow_subsystem_set_entry(X11_ShadowSubsystemEntry); -#endif - -#ifdef WITH_SHADOW_MAC - shadow_subsystem_set_entry(Mac_ShadowSubsystemEntry); -#endif - -#ifdef WITH_SHADOW_WIN - shadow_subsystem_set_entry(Win_ShadowSubsystemEntry); -#endif + shadow_subsystem_set_entry_builtin(NULL); server = shadow_server_new(); diff --git a/server/shadow/shadow_subsystem_builtin.c b/server/shadow/shadow_subsystem_builtin.c new file mode 100644 index 000000000..be143d731 --- /dev/null +++ b/server/shadow/shadow_subsystem_builtin.c @@ -0,0 +1,96 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * + * Copyright 2016 Jiang Zihao + * + * 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 + +struct _RDP_SHADOW_SUBSYSTEM +{ + const char* name; + pfnShadowSubsystemEntry entry; +}; +typedef struct _RDP_SHADOW_SUBSYSTEM RDP_SHADOW_SUBSYSTEM; + +#ifdef WITH_SHADOW_X11 +extern int X11_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); +#endif + +#ifdef WITH_SHADOW_MAC +extern int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); +#endif + +#ifdef WITH_SHADOW_WIN +extern int Win_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints); +#endif + +static RDP_SHADOW_SUBSYSTEM g_Subsystems[] = +{ + +#ifdef WITH_SHADOW_X11 + { "X11", X11_ShadowSubsystemEntry }, +#endif + +#ifdef WITH_SHADOW_MAC + { "Mac", Mac_ShadowSubsystemEntry }, +#endif + +#ifdef WITH_SHADOW_WIN + { "Win", Win_ShadowSubsystemEntry }, +#endif + + { "", NULL } +}; + +static int g_SubsystemCount = (sizeof(g_Subsystems) / sizeof(g_Subsystems[0])); + +static pfnShadowSubsystemEntry shadow_subsystem_load_static_entry(const char* name) +{ + int index; + + if (!name) + { + for (index = 0; index < g_SubsystemCount; index++) + { + if (g_Subsystems[index].name) + return g_Subsystems[index].entry; + } + } + + for (index = 0; index < g_SubsystemCount; index++) + { + if (strcmp(name, g_Subsystems[index].name) == 0) + return g_Subsystems[index].entry; + } + + return NULL; +} + +void shadow_subsystem_set_entry_builtin(const char* name) +{ + pfnShadowSubsystemEntry entry; + + entry = shadow_subsystem_load_static_entry(name); + + if (entry) + shadow_subsystem_set_entry(entry); + + return; +} From 92c15783dc9051a072b3ce5faf9e76c9f9525727 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sun, 28 Feb 2016 11:12:17 +0100 Subject: [PATCH 089/128] Updated RC4 API, fixed crashing bug. --- libfreerdp/core/connection.c | 44 +++++++++++++++---- libfreerdp/core/license.c | 26 +++++++---- libfreerdp/core/rdp.c | 8 ++-- libfreerdp/core/security.c | 22 +++++----- winpr/include/winpr/crypto.h | 4 +- winpr/libwinpr/crypto/cipher.c | 42 ++++++++++++------ winpr/libwinpr/crypto/test/TestCryptoCipher.c | 29 +++++++----- winpr/libwinpr/sspi/NTLM/ntlm.c | 10 +++-- winpr/libwinpr/sspi/NTLM/ntlm.h | 4 +- winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 30 +++++++------ 10 files changed, 139 insertions(+), 80 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index 496e85822..c23b4217a 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -513,12 +513,27 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) goto end; } - winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); - winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); + if (!winpr_RC4_New(&rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) + goto end; + if (!winpr_RC4_New(&rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + goto end; ret = TRUE; end: free(crypt_client_random); + if (!ret) + { + winpr_Cipher_Free(rdp->fips_decrypt); + winpr_Cipher_Free(rdp->fips_encrypt); + winpr_RC4_Free(rdp->rc4_decrypt_key); + winpr_RC4_Free(rdp->rc4_encrypt_key); + + rdp->fips_decrypt = NULL; + rdp->fips_encrypt = NULL; + rdp->rc4_decrypt_key = NULL; + rdp->rc4_encrypt_key = NULL; + } + return ret; } @@ -575,12 +590,12 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) if (rand_len != key_len + 8) { WLog_ERR(TAG, "invalid encrypted client random length"); - goto end2; + goto end; } crypt_client_random = calloc(1, rand_len); if (!crypt_client_random) - goto end2; + goto end; Stream_Read(s, crypt_client_random, rand_len); mod = rdp->settings->RdpServerRsaKey->Modulus; @@ -589,9 +604,7 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) /* now calculate encrypt / decrypt and update keys */ if (!security_establish_keys(client_random, rdp)) - { goto end; - } rdp->do_crypt = TRUE; @@ -621,15 +634,28 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) goto end; } - winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len); - winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len); + if (!winpr_RC4_New(&rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) + goto end; + if (!winpr_RC4_New(&rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + goto end; ret = TRUE; end: free(crypt_client_random); -end2: free(client_random); + if (!ret) + { + winpr_Cipher_Free(rdp->fips_encrypt); + winpr_Cipher_Free(rdp->fips_decrypt); + winpr_RC4_Free(rdp->rc4_encrypt_key); + winpr_RC4_Free(rdp->rc4_decrypt_key); + + rdp->fips_encrypt = NULL; + rdp->fips_decrypt = NULL; + rdp->rc4_encrypt_key = NULL; + rdp->rc4_decrypt_key = NULL; + } return ret; } diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index 4852f9bb5..cc3e64a07 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -458,20 +458,22 @@ BOOL license_encrypt_premaster_secret(rdpLicense* license) BOOL license_decrypt_platform_challenge(rdpLicense* license) { - WINPR_RC4_CTX rc4; + BOOL rc; + WINPR_RC4_CTX* rc4; license->PlatformChallenge->data = (BYTE *)malloc(license->EncryptedPlatformChallenge->length); if (!license->PlatformChallenge->data) return FALSE; license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length; - winpr_RC4_Init(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); - winpr_RC4_Update(&rc4, license->EncryptedPlatformChallenge->length, + if (!winpr_RC4_New(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) + return FALSE; + rc = winpr_RC4_Update(rc4, license->EncryptedPlatformChallenge->length, license->EncryptedPlatformChallenge->data, license->PlatformChallenge->data); - winpr_RC4_Final(&rc4); - return TRUE; + winpr_RC4_Free(rc4); + return rc; } /** @@ -1015,7 +1017,7 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) wStream* s; int length; BYTE* buffer; - WINPR_RC4_CTX rc4; + WINPR_RC4_CTX* rc4; BYTE mac_data[16]; BOOL status; @@ -1036,14 +1038,20 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) if (!status) return FALSE; - winpr_RC4_Init(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH); + if (!winpr_RC4_New(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) + return FALSE; buffer = (BYTE*) malloc(HWID_LENGTH); if (!buffer) return FALSE; - winpr_RC4_Update(&rc4, HWID_LENGTH, license->HardwareId, buffer); - winpr_RC4_Final(&rc4); + status = winpr_RC4_Update(rc4, HWID_LENGTH, license->HardwareId, buffer); + winpr_RC4_Free(rc4); + if (!status) + { + free(buffer); + return FALSE; + } license->EncryptedHardwareId->type = BB_DATA_BLOB; license->EncryptedHardwareId->data = buffer; diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c index 026091aec..61a44dc86 100644 --- a/libfreerdp/core/rdp.c +++ b/libfreerdp/core/rdp.c @@ -1590,13 +1590,13 @@ void rdp_reset(rdpRdp* rdp) if (rdp->rc4_decrypt_key) { - winpr_RC4_Final(rdp->rc4_decrypt_key); + winpr_RC4_Free(rdp->rc4_decrypt_key); rdp->rc4_decrypt_key = NULL; } if (rdp->rc4_encrypt_key) { - winpr_RC4_Final(rdp->rc4_encrypt_key); + winpr_RC4_Free(rdp->rc4_encrypt_key); rdp->rc4_encrypt_key = NULL; } @@ -1661,8 +1661,8 @@ void rdp_free(rdpRdp* rdp) { if (rdp) { - winpr_RC4_Final(rdp->rc4_decrypt_key); - winpr_RC4_Final(rdp->rc4_encrypt_key); + winpr_RC4_Free(rdp->rc4_decrypt_key); + winpr_RC4_Free(rdp->rc4_encrypt_key); winpr_Cipher_Free(rdp->fips_encrypt); winpr_Cipher_Free(rdp->fips_decrypt); free(rdp->fips_hmac); diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 0d67c8aac..4158093de 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -538,7 +538,8 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) BYTE sha1h[WINPR_SHA1_DIGEST_LENGTH]; WINPR_MD5_CTX md5; WINPR_SHA1_CTX sha1; - WINPR_RC4_CTX rc4; + WINPR_RC4_CTX* rc4; + BOOL rc; BYTE salt[] = { 0xD1, 0x26, 0x9E }; /* 40 bits: 3 bytes, 56 bits: 1 byte */ if (!winpr_SHA1_Init(&sha1)) @@ -563,11 +564,12 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) if (!winpr_MD5_Final(&md5, key, WINPR_MD5_DIGEST_LENGTH)) return FALSE; - if (!winpr_RC4_Init(&rc4, key, key_len)) + if (!winpr_RC4_New(&rc4, key, key_len)) return FALSE; - if (!winpr_RC4_Update(&rc4, key_len, key, key)) - return FALSE; - if (!winpr_RC4_Final(&rc4)) + rc = winpr_RC4_Update(rc4, key_len, key, key); + winpr_RC4_Free(rc4); + + if (!rc) return FALSE; if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_40BIT) @@ -585,9 +587,8 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp) if (!security_key_update(rdp->encrypt_key, rdp->encrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - if (!winpr_RC4_Final(rdp->rc4_encrypt_key)) - return FALSE; - if (!winpr_RC4_Init(rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + winpr_RC4_Free(rdp->rc4_encrypt_key); + if (!winpr_RC4_New(&rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) return FALSE; rdp->encrypt_use_count = 0; @@ -609,9 +610,8 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) { if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; - if (!winpr_RC4_Final(rdp->rc4_decrypt_key)) - return FALSE; - if (!winpr_RC4_Init(rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) + winpr_RC4_Free(rdp->rc4_decrypt_key); + if (!winpr_RC4_New(&rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) return FALSE; rdp->decrypt_use_count = 0; diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index b831da8a3..0808582b3 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -901,9 +901,9 @@ typedef union _WINPR_RC4_CTX WINPR_RC4_CTX; extern "C" { #endif -WINPR_API BOOL winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen); +WINPR_API BOOL winpr_RC4_New(WINPR_RC4_CTX** ctx, const BYTE* key, size_t keylen); WINPR_API BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); -WINPR_API BOOL winpr_RC4_Final(WINPR_RC4_CTX* ctx); +WINPR_API void winpr_RC4_Free(WINPR_RC4_CTX* ctx); #ifdef __cplusplus } diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index b8eb9d671..5c571b147 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -43,15 +43,26 @@ * RC4 */ -BOOL winpr_RC4_Init(WINPR_RC4_CTX* ctx, const BYTE* key, size_t keylen) +BOOL winpr_RC4_New(WINPR_RC4_CTX** octx, const BYTE* key, size_t keylen) { + WINPR_RC4_CTX* ctx = NULL; + + if (!octx || !key || (keylen == 0)) + return FALSE; + + ctx = calloc(1, sizeof(WINPR_RC4_CTX)); + if (!ctx) + return FALSE; + #if defined(WITH_OPENSSL) RC4_set_key((RC4_KEY*) ctx, keylen, key); #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) mbedtls_arc4_init((mbedtls_arc4_context*) ctx); mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, keylen); #endif - return TRUE; + *octx = ctx; + + return TRUE; } BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) @@ -60,20 +71,23 @@ BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE RC4((RC4_KEY*) ctx, length, input, output); #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) if (mbedtls_arc4_crypt((mbedtls_arc4_context*) ctx, length, input, output) != 0) - return FALSE; + return FALSE; #endif - return TRUE; + return TRUE; } -BOOL winpr_RC4_Final(WINPR_RC4_CTX* ctx) +void winpr_RC4_Free(WINPR_RC4_CTX* ctx) { + if (!ctx) + return; + #if defined(WITH_OPENSSL) #elif defined(WITH_MBEDTLS) && defined(MBEDTLS_ARC4_C) mbedtls_arc4_free((mbedtls_arc4_context*) ctx); #endif - return TRUE; + free(ctx); } /** @@ -502,7 +516,7 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* key, const BYTE* iv) { - WINPR_CIPHER_CTX* ctx; + WINPR_CIPHER_CTX* ctx; #if defined(WITH_OPENSSL) int operation; const EVP_CIPHER* evp; @@ -514,10 +528,10 @@ BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* k const mbedtls_cipher_info_t* cipher_info; #endif - ctx = calloc(1, sizeof(WINPR_CIPHER_CTX)); - if (!ctx) - return FALSE; - + ctx = calloc(1, sizeof(WINPR_CIPHER_CTX)); + if (!ctx) + return FALSE; + #if defined(WITH_OPENSSL) octx = (EVP_CIPHER_CTX*)ctx; evp = winpr_openssl_get_evp_cipher(cipher); @@ -551,7 +565,7 @@ BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* k return FALSE; #endif - *cctx = ctx; + *cctx = ctx; return TRUE; } @@ -589,8 +603,8 @@ BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen) void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx) { - if (!ctx) - return; + if (!ctx) + return; #if defined(WITH_OPENSSL) EVP_CIPHER_CTX_cleanup((EVP_CIPHER_CTX*) ctx); diff --git a/winpr/libwinpr/crypto/test/TestCryptoCipher.c b/winpr/libwinpr/crypto/test/TestCryptoCipher.c index 29aa925a8..98ceb8fc5 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoCipher.c +++ b/winpr/libwinpr/crypto/test/TestCryptoCipher.c @@ -7,22 +7,26 @@ static const BYTE* TEST_RC4_KEY = (BYTE*) "Key"; static const char* TEST_RC4_PLAINTEXT = "Plaintext"; static const BYTE* TEST_RC4_CIPHERTEXT = (BYTE*) "\xBB\xF3\x16\xE8\xD9\x40\xAF\x0A\xD3"; -BOOL test_crypto_cipher_rc4() +static BOOL test_crypto_cipher_rc4() { size_t len; - BYTE* text; - WINPR_RC4_CTX ctx; + BOOL rc = FALSE; + BYTE* text = NULL; + WINPR_RC4_CTX* ctx; len = strlen(TEST_RC4_PLAINTEXT); text = (BYTE*) calloc(1, len); if (!text) - return FALSE; + goto out; - winpr_RC4_Init(&ctx, TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY)); - winpr_RC4_Update(&ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text); - winpr_RC4_Final(&ctx); + if (!winpr_RC4_New(&ctx, TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY))) + goto out; + rc = winpr_RC4_Update(ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text); + winpr_RC4_Free(ctx); + if (!rc) + goto out; if (memcmp(text, TEST_RC4_CIPHERTEXT, len) != 0) { @@ -36,11 +40,14 @@ BOOL test_crypto_cipher_rc4() free(actual); free(expected); - - return FALSE; + goto out; } - return TRUE; + rc = TRUE; + +out: + free(text); + return rc; } static const BYTE* TEST_RAND_DATA = (BYTE*) @@ -56,7 +63,7 @@ static const BYTE* TEST_CIPHER_KEY = (BYTE*) static const BYTE* TEST_CIPHER_IV = (BYTE*) "\xFE\xE3\x9F\xF0\xD1\x5E\x37\x0C\xAB\xAB\x9B\x04\xF3\xDB\x99\x15"; -BOOL test_crypto_cipher_key() +static BOOL test_crypto_cipher_key() { int status; BYTE key[32]; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 99d63dd2e..060246658 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -239,6 +239,8 @@ void ntlm_ContextFree(NTLM_CONTEXT* context) if (!context) return; + winpr_RC4_Free(context->SendRc4Seal); + winpr_RC4_Free(context->RecvRc4Seal); sspi_SecBufferFree(&context->NegotiateMessage); sspi_SecBufferFree(&context->ChallengeMessage); sspi_SecBufferFree(&context->AuthenticateMessage); @@ -931,7 +933,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, /* Encrypt message using with RC4, result overwrites original buffer */ if (context->confidentiality) - winpr_RC4_Update(&context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); + winpr_RC4_Update(context->SendRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); else CopyMemory(data_buffer->pvBuffer, data, length); @@ -943,7 +945,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, #endif free(data); /* RC4-encrypt first 8 bytes of digest */ - winpr_RC4_Update(&context->SendRc4Seal, 8, digest, checksum); + winpr_RC4_Update(context->SendRc4Seal, 8, digest, checksum); signature = (BYTE*) signature_buffer->pvBuffer; /* Concatenate version, ciphertext and sequence number to build signature */ CopyMemory(signature, (void*) &version, 4); @@ -1000,7 +1002,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD /* Decrypt message using with RC4, result overwrites original buffer */ if (context->confidentiality) - winpr_RC4_Update(&context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); + winpr_RC4_Update(context->RecvRc4Seal, length, (BYTE*) data, (BYTE*) data_buffer->pvBuffer); else CopyMemory(data_buffer->pvBuffer, data, length); @@ -1017,7 +1019,7 @@ SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle phContext, PSecBufferD #endif free(data); /* RC4-encrypt first 8 bytes of digest */ - winpr_RC4_Update(&context->RecvRc4Seal, 8, digest, checksum); + winpr_RC4_Update(context->RecvRc4Seal, 8, digest, checksum); /* Concatenate version, ciphertext and sequence number to build signature */ CopyMemory(expected_signature, (void*) &version, 4); CopyMemory(&expected_signature[4], (void*) checksum, 8); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.h b/winpr/libwinpr/sspi/NTLM/ntlm.h index bdccecdb3..8253f3d9b 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.h +++ b/winpr/libwinpr/sspi/NTLM/ntlm.h @@ -225,8 +225,8 @@ struct _NTLM_CONTEXT BYTE MachineID[32]; BOOL SendVersionInfo; BOOL confidentiality; - WINPR_RC4_CTX SendRc4Seal; - WINPR_RC4_CTX RecvRc4Seal; + WINPR_RC4_CTX* SendRc4Seal; + WINPR_RC4_CTX* RecvRc4Seal; BYTE* SendSigningKey; BYTE* RecvSigningKey; BYTE* SendSealingKey; diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index b341dbca8..092f250e3 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -341,8 +341,8 @@ int ntlm_compute_lm_v2_response(NTLM_CONTEXT* context) response = (BYTE*) context->LmChallengeResponse.pvBuffer; /* Compute the HMAC-MD5 hash of the resulting value using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (void*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) response, WINPR_MD5_DIGEST_LENGTH); + (BYTE*) value, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) response, WINPR_MD5_DIGEST_LENGTH); /* Concatenate the resulting HMAC-MD5 hash and the client challenge, giving us the LMv2 response (24 bytes) */ CopyMemory(&response[16], context->ClientChallenge, 8); return 1; @@ -412,8 +412,8 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(blob, context->ServerChallenge, 8); CopyMemory(&blob[8], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, - (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); + (BYTE*) ntlm_v2_temp_chal.pvBuffer, ntlm_v2_temp_chal.cbBuffer, + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH); /* NtChallengeResponse, Concatenate NTProofStr with temp */ @@ -425,8 +425,8 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) CopyMemory(&blob[16], ntlm_v2_temp.pvBuffer, ntlm_v2_temp.cbBuffer); /* Compute SessionBaseKey, the HMAC-MD5 hash of NTProofStr using the NTLMv2 hash as the key */ winpr_HMAC(WINPR_MD_MD5, (BYTE*) context->NtlmV2Hash, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, - (BYTE*) context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); + (BYTE*) nt_proof_str, WINPR_MD5_DIGEST_LENGTH, + (BYTE*) context->SessionBaseKey, WINPR_MD5_DIGEST_LENGTH); sspi_SecBufferFree(&ntlm_v2_temp); sspi_SecBufferFree(&ntlm_v2_temp_chal); return 1; @@ -442,10 +442,12 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext) { - WINPR_RC4_CTX rc4; - winpr_RC4_Init(&rc4, (void*) key, 16); - winpr_RC4_Update(&rc4, length, (void*) plaintext, (void*) ciphertext); - winpr_RC4_Final(&rc4); + WINPR_RC4_CTX* rc4; + if (winpr_RC4_New(&rc4, (void*) key, 16)) + { + winpr_RC4_Update(rc4, length, (void*) plaintext, (void*) ciphertext); + winpr_RC4_Free(rc4); + } } /** @@ -662,8 +664,8 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) context->RecvSigningKey = context->ClientSigningKey; context->SendSealingKey = context->ClientSealingKey; context->RecvSealingKey = context->ServerSealingKey; - winpr_RC4_Init(&context->SendRc4Seal, context->ServerSealingKey, 16); - winpr_RC4_Init(&context->RecvRc4Seal, context->ClientSealingKey, 16); + winpr_RC4_New(&context->SendRc4Seal, context->ServerSealingKey, 16); + winpr_RC4_New(&context->RecvRc4Seal, context->ClientSealingKey, 16); } else { @@ -671,8 +673,8 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) context->RecvSigningKey = context->ServerSigningKey; context->SendSealingKey = context->ServerSealingKey; context->RecvSealingKey = context->ClientSealingKey; - winpr_RC4_Init(&context->SendRc4Seal, context->ClientSealingKey, 16); - winpr_RC4_Init(&context->RecvRc4Seal, context->ServerSealingKey, 16); + winpr_RC4_New(&context->SendRc4Seal, context->ClientSealingKey, 16); + winpr_RC4_New(&context->RecvRc4Seal, context->ServerSealingKey, 16); } } From 71bea3e1d0998ce26ee757aa63bb200181f69b33 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Sun, 28 Feb 2016 19:56:57 +0100 Subject: [PATCH 090/128] Fixed argument parsing for audin. --- channels/audin/client/audin_main.c | 84 ++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 27 deletions(-) diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 373ae86dc..d72e15524 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -38,13 +38,13 @@ #include #include "audin_main.h" -#define MSG_SNDIN_VERSION 0x01 -#define MSG_SNDIN_FORMATS 0x02 -#define MSG_SNDIN_OPEN 0x03 -#define MSG_SNDIN_OPEN_REPLY 0x04 -#define MSG_SNDIN_DATA_INCOMING 0x05 -#define MSG_SNDIN_DATA 0x06 -#define MSG_SNDIN_FORMATCHANGE 0x07 +#define MSG_SNDIN_VERSION 0x01 +#define MSG_SNDIN_FORMATS 0x02 +#define MSG_SNDIN_OPEN 0x03 +#define MSG_SNDIN_OPEN_REPLY 0x04 +#define MSG_SNDIN_DATA_INCOMING 0x05 +#define MSG_SNDIN_DATA 0x06 +#define MSG_SNDIN_FORMATCHANGE 0x07 typedef struct _AUDIN_LISTENER_CALLBACK AUDIN_LISTENER_CALLBACK; struct _AUDIN_LISTENER_CALLBACK @@ -93,6 +93,8 @@ struct _AUDIN_PLUGIN rdpContext* rdpcontext; }; +static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args); + /** * Function description * @@ -639,8 +641,12 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI { PFREERDP_AUDIN_DEVICE_ENTRY entry; FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; UINT error; + if (!audin_process_addin_args(audin, args)) + return CHANNEL_RC_INITIALIZATION_ERROR; + entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0); if (entry == NULL) @@ -660,6 +666,7 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI return error; } + WLog_INFO(TAG, "Loaded %s backend for audin", name); return CHANNEL_RC_OK; } @@ -707,18 +714,19 @@ static COMMAND_LINE_ARGUMENT_A audin_args[] = { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; -static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) +BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) { int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; UINT error; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON; + flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, audin_args, flags, audin, NULL, NULL); + if (status != 0) + return FALSE; arg = audin_args; @@ -786,7 +794,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) char *device; }; - UINT error = CHANNEL_RC_OK; + UINT error = CHANNEL_RC_INITIALIZATION_ERROR; ADDIN_ARGV* args; AUDIN_PLUGIN* audin; struct SubsystemEntry entries[] = @@ -837,31 +845,53 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) args = pEntryPoints->GetPluginData(pEntryPoints); audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; - while (entry && entry->subsystem && !audin->device) + if (args) { - if ((error = audin_set_subsystem(audin, entry->subsystem))) - { - WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %lu!", - entry->subsystem, error); - } - else if ((error = audin_set_device_name(audin, entry->device))) - { - WLog_ERR(TAG, "audin_set_device_name for %s failed with error %lu!", - entry->subsystem, error); - } - else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) + if (!audin_process_addin_args(audin, args)) + goto out; + } + + if (audin->subsystem) + { + if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) { WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!", - entry->subsystem, error); + audin->subsystem, error); + goto out; } + } + else + { + while (entry && entry->subsystem && !audin->device) + { + if ((error = audin_set_subsystem(audin, entry->subsystem))) + { + WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %lu!", + entry->subsystem, error); + } + else if ((error = audin_set_device_name(audin, entry->device))) + { + WLog_ERR(TAG, "audin_set_device_name for %s failed with error %lu!", + entry->subsystem, error); + } + else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args))) + { + WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!", + entry->subsystem, error); + } - entry++; + entry++; + } } if (audin->device == NULL) - { WLog_ERR(TAG, "no sound device."); - } + + error = CHANNEL_RC_OK; + +out: + if (error != CHANNEL_RC_OK) + audin_plugin_terminated((IWTSPlugin*)audin); return error; } From b429d230cbc4a4d301847bfb041d6b5d5c55c9b1 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 09:00:02 +0100 Subject: [PATCH 091/128] Refactored crypto *_New functions. --- libfreerdp/core/connection.c | 40 ++++++++++++------- libfreerdp/core/license.c | 7 +++- libfreerdp/core/security.c | 9 +++-- winpr/include/winpr/crypto.h | 4 +- winpr/libwinpr/crypto/cipher.c | 32 +++++++-------- winpr/libwinpr/crypto/crypto.c | 8 ++-- winpr/libwinpr/crypto/test/TestCryptoCipher.c | 2 +- winpr/libwinpr/sspi/NTLM/ntlm_compute.c | 14 +++---- 8 files changed, 66 insertions(+), 50 deletions(-) diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c index c23b4217a..99b2e59f3 100644 --- a/libfreerdp/core/connection.c +++ b/libfreerdp/core/connection.c @@ -490,14 +490,20 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) if (settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - if (!winpr_Cipher_New(&rdp->fips_encrypt, WINPR_CIPHER_DES_EDE3_CBC, - WINPR_ENCRYPT, rdp->fips_encrypt_key, fips_ivec)) + rdp->fips_encrypt = winpr_Cipher_New( WINPR_CIPHER_DES_EDE3_CBC, + WINPR_ENCRYPT, + rdp->fips_encrypt_key, + fips_ivec); + if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } - if (!winpr_Cipher_New(&rdp->fips_decrypt, WINPR_CIPHER_DES_EDE3_CBC, - WINPR_DECRYPT, rdp->fips_decrypt_key, fips_ivec)) + rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, + WINPR_DECRYPT, + rdp->fips_decrypt_key, + fips_ivec); + if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; @@ -513,9 +519,9 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp) goto end; } - if (!winpr_RC4_New(&rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) - goto end; - if (!winpr_RC4_New(&rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len); + rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); + if (!rdp->rc4_decrypt_key || !rdp->rc4_encrypt_key) goto end; ret = TRUE; @@ -610,15 +616,21 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) if (rdp->settings->EncryptionMethods == ENCRYPTION_METHOD_FIPS) { - if (!winpr_Cipher_New(&rdp->fips_encrypt, WINPR_CIPHER_DES_EDE3_CBC, - WINPR_ENCRYPT, rdp->fips_encrypt_key, fips_ivec)) + rdp->fips_encrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, + WINPR_ENCRYPT, + rdp->fips_encrypt_key, + fips_ivec); + if (!rdp->fips_encrypt) { WLog_ERR(TAG, "unable to allocate des3 encrypt key"); goto end; } - if (!winpr_Cipher_New(&rdp->fips_decrypt, WINPR_CIPHER_DES_EDE3_CBC, - WINPR_DECRYPT, rdp->fips_decrypt_key, fips_ivec)) + rdp->fips_decrypt = winpr_Cipher_New(WINPR_CIPHER_DES_EDE3_CBC, + WINPR_DECRYPT, + rdp->fips_decrypt_key, + fips_ivec); + if (!rdp->fips_decrypt) { WLog_ERR(TAG, "unable to allocate des3 decrypt key"); goto end; @@ -634,9 +646,9 @@ BOOL rdp_server_establish_keys(rdpRdp* rdp, wStream* s) goto end; } - if (!winpr_RC4_New(&rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) - goto end; - if (!winpr_RC4_New(&rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, rdp->rc4_key_len); + rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); + if (!rdp->rc4_decrypt_key || rdp->rc4_encrypt_key) goto end; ret = TRUE; diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c index cc3e64a07..055a2dc3e 100644 --- a/libfreerdp/core/license.c +++ b/libfreerdp/core/license.c @@ -466,7 +466,8 @@ BOOL license_decrypt_platform_challenge(rdpLicense* license) return FALSE; license->PlatformChallenge->length = license->EncryptedPlatformChallenge->length; - if (!winpr_RC4_New(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) + if ((rc4 = winpr_RC4_New(license->LicensingEncryptionKey, + LICENSING_ENCRYPTION_KEY_LENGTH)) == NULL) return FALSE; rc = winpr_RC4_Update(rc4, license->EncryptedPlatformChallenge->length, license->EncryptedPlatformChallenge->data, @@ -1038,7 +1039,9 @@ BOOL license_send_platform_challenge_response_packet(rdpLicense* license) if (!status) return FALSE; - if (!winpr_RC4_New(&rc4, license->LicensingEncryptionKey, LICENSING_ENCRYPTION_KEY_LENGTH)) + rc4 = winpr_RC4_New(license->LicensingEncryptionKey, + LICENSING_ENCRYPTION_KEY_LENGTH); + if (!rc4) return FALSE; buffer = (BYTE*) malloc(HWID_LENGTH); diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c index 4158093de..e41578687 100644 --- a/libfreerdp/core/security.c +++ b/libfreerdp/core/security.c @@ -564,7 +564,7 @@ BOOL security_key_update(BYTE* key, BYTE* update_key, int key_len, rdpRdp* rdp) if (!winpr_MD5_Final(&md5, key, WINPR_MD5_DIGEST_LENGTH)) return FALSE; - if (!winpr_RC4_New(&rc4, key, key_len)) + if ((rc4 = winpr_RC4_New(key, key_len)) == NULL) return FALSE; rc = winpr_RC4_Update(rc4, key_len, key, key); winpr_RC4_Free(rc4); @@ -588,7 +588,8 @@ BOOL security_encrypt(BYTE* data, int length, rdpRdp* rdp) return FALSE; winpr_RC4_Free(rdp->rc4_encrypt_key); - if (!winpr_RC4_New(&rdp->rc4_encrypt_key, rdp->encrypt_key, rdp->rc4_key_len)) + rdp->rc4_encrypt_key = winpr_RC4_New(rdp->encrypt_key, rdp->rc4_key_len); + if (!rdp->rc4_encrypt_key) return FALSE; rdp->encrypt_use_count = 0; @@ -611,7 +612,9 @@ BOOL security_decrypt(BYTE* data, int length, rdpRdp* rdp) if (!security_key_update(rdp->decrypt_key, rdp->decrypt_update_key, rdp->rc4_key_len, rdp)) return FALSE; winpr_RC4_Free(rdp->rc4_decrypt_key); - if (!winpr_RC4_New(&rdp->rc4_decrypt_key, rdp->decrypt_key, rdp->rc4_key_len)) + rdp->rc4_decrypt_key = winpr_RC4_New(rdp->decrypt_key, + rdp->rc4_key_len); + if (!rdp->rc4_decrypt_key) return FALSE; rdp->decrypt_use_count = 0; diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 0808582b3..c4dcb31bf 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -901,7 +901,7 @@ typedef union _WINPR_RC4_CTX WINPR_RC4_CTX; extern "C" { #endif -WINPR_API BOOL winpr_RC4_New(WINPR_RC4_CTX** ctx, const BYTE* key, size_t keylen); +WINPR_API WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen); WINPR_API BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output); WINPR_API void winpr_RC4_Free(WINPR_RC4_CTX* ctx); @@ -1016,7 +1016,7 @@ typedef union _WINPR_CIPHER_CTX WINPR_CIPHER_CTX; extern "C" { #endif -WINPR_API BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** ctx, int cipher, int op, const BYTE* key, const BYTE* iv); +WINPR_API WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv); WINPR_API BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen); WINPR_API BOOL winpr_Cipher_Final(WINPR_CIPHER_CTX* ctx, BYTE* output, size_t* olen); WINPR_API void winpr_Cipher_Free(WINPR_CIPHER_CTX* ctx); diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index 5c571b147..eff9c3c85 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -43,16 +43,16 @@ * RC4 */ -BOOL winpr_RC4_New(WINPR_RC4_CTX** octx, const BYTE* key, size_t keylen) +WINPR_RC4_CTX* winpr_RC4_New(const BYTE* key, size_t keylen) { WINPR_RC4_CTX* ctx = NULL; - if (!octx || !key || (keylen == 0)) - return FALSE; + if (!key || (keylen == 0)) + return NULL; ctx = calloc(1, sizeof(WINPR_RC4_CTX)); if (!ctx) - return FALSE; + return NULL; #if defined(WITH_OPENSSL) RC4_set_key((RC4_KEY*) ctx, keylen, key); @@ -60,9 +60,7 @@ BOOL winpr_RC4_New(WINPR_RC4_CTX** octx, const BYTE* key, size_t keylen) mbedtls_arc4_init((mbedtls_arc4_context*) ctx); mbedtls_arc4_setup((mbedtls_arc4_context*) ctx, key, keylen); #endif - *octx = ctx; - - return TRUE; + return ctx; } BOOL winpr_RC4_Update(WINPR_RC4_CTX* ctx, size_t length, const BYTE* input, BYTE* output) @@ -514,7 +512,7 @@ mbedtls_cipher_type_t winpr_mbedtls_get_cipher_type(int cipher) } #endif -BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* key, const BYTE* iv) +WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BYTE* iv) { WINPR_CIPHER_CTX* ctx; #if defined(WITH_OPENSSL) @@ -530,20 +528,20 @@ BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* k ctx = calloc(1, sizeof(WINPR_CIPHER_CTX)); if (!ctx) - return FALSE; - + return NULL; + #if defined(WITH_OPENSSL) octx = (EVP_CIPHER_CTX*)ctx; evp = winpr_openssl_get_evp_cipher(cipher); if (!evp) - return FALSE; + return NULL; operation = (op == WINPR_ENCRYPT) ? 1 : 0; EVP_CIPHER_CTX_init(octx); if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1) - return FALSE; + return NULL; EVP_CIPHER_CTX_set_padding(octx, 0); #elif defined(WITH_MBEDTLS) @@ -551,22 +549,20 @@ BOOL winpr_Cipher_New(WINPR_CIPHER_CTX** cctx, int cipher, int op, const BYTE* k cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (!cipher_info) - return FALSE; + return NULL; operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; mbedtls_cipher_init((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setup((mbedtls_cipher_context_t*) ctx, cipher_info) != 0) - return FALSE; + return NULL; key_bitlen = mbedtls_cipher_get_key_bitlen((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setkey((mbedtls_cipher_context_t*) ctx, key, key_bitlen, operation) != 0) - return FALSE; + return NULL; #endif - - *cctx = ctx; - return TRUE; + return ctx; } BOOL winpr_Cipher_Update(WINPR_CIPHER_CTX* ctx, const BYTE* input, size_t ilen, BYTE* output, size_t* olen) diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c index 5b0a68a7f..a651a2fe7 100644 --- a/winpr/libwinpr/crypto/crypto.c +++ b/winpr/libwinpr/crypto/crypto.c @@ -186,9 +186,10 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) pCipherText = (BYTE*) malloc(cbOut); if (!pCipherText) - goto out; + goto out; - if (!winpr_Cipher_New(&enc, WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key, pMemBlock->iv)) + if ((enc = winpr_Cipher_New(WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, + pMemBlock->key, pMemBlock->iv)) == NULL) goto out; if (!winpr_Cipher_Update(enc, pMemBlock->pData, pMemBlock->cbData, pCipherText, &cbOut)) goto out; @@ -233,7 +234,8 @@ BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) if (!pPlainText) goto out; - if (!winpr_Cipher_New(&dec, WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, pMemBlock->key, pMemBlock->iv)) + if ((dec = winpr_Cipher_New(WINPR_CIPHER_AES_256_CBC, WINPR_DECRYPT, + pMemBlock->key, pMemBlock->iv)) == NULL) goto out; if (!winpr_Cipher_Update(dec, pMemBlock->pData, pMemBlock->cbData, pPlainText, &cbOut)) goto out; diff --git a/winpr/libwinpr/crypto/test/TestCryptoCipher.c b/winpr/libwinpr/crypto/test/TestCryptoCipher.c index 98ceb8fc5..cbf940d9a 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoCipher.c +++ b/winpr/libwinpr/crypto/test/TestCryptoCipher.c @@ -21,7 +21,7 @@ static BOOL test_crypto_cipher_rc4() if (!text) goto out; - if (!winpr_RC4_New(&ctx, TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY))) + if ((ctx = winpr_RC4_New(TEST_RC4_KEY, strlen((char*) TEST_RC4_KEY))) == NULL) goto out; rc = winpr_RC4_Update(ctx, len, (BYTE*) TEST_RC4_PLAINTEXT, text); winpr_RC4_Free(ctx); diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c index 092f250e3..8c18466f7 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c @@ -442,10 +442,10 @@ int ntlm_compute_ntlm_v2_response(NTLM_CONTEXT* context) void ntlm_rc4k(BYTE* key, int length, BYTE* plaintext, BYTE* ciphertext) { - WINPR_RC4_CTX* rc4; - if (winpr_RC4_New(&rc4, (void*) key, 16)) + WINPR_RC4_CTX* rc4 = winpr_RC4_New(key, 16); + if (rc4) { - winpr_RC4_Update(rc4, length, (void*) plaintext, (void*) ciphertext); + winpr_RC4_Update(rc4, length, plaintext, ciphertext); winpr_RC4_Free(rc4); } } @@ -664,8 +664,8 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) context->RecvSigningKey = context->ClientSigningKey; context->SendSealingKey = context->ClientSealingKey; context->RecvSealingKey = context->ServerSealingKey; - winpr_RC4_New(&context->SendRc4Seal, context->ServerSealingKey, 16); - winpr_RC4_New(&context->RecvRc4Seal, context->ClientSealingKey, 16); + context->SendRc4Seal = winpr_RC4_New(context->ServerSealingKey, 16); + context->RecvRc4Seal = winpr_RC4_New(context->ClientSealingKey, 16); } else { @@ -673,8 +673,8 @@ void ntlm_init_rc4_seal_states(NTLM_CONTEXT* context) context->RecvSigningKey = context->ServerSigningKey; context->SendSealingKey = context->ServerSealingKey; context->RecvSealingKey = context->ClientSealingKey; - winpr_RC4_New(&context->SendRc4Seal, context->ClientSealingKey, 16); - winpr_RC4_New(&context->RecvRc4Seal, context->ServerSealingKey, 16); + context->SendRc4Seal = winpr_RC4_New(context->ClientSealingKey, 16); + context->RecvRc4Seal = winpr_RC4_New(context->ServerSealingKey, 16); } } From 7e6501374dabe2b0be9b3514aac0e744442e36ef Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 11:10:15 +0100 Subject: [PATCH 092/128] Fixed memory leak. --- winpr/libwinpr/crypto/cipher.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/winpr/libwinpr/crypto/cipher.c b/winpr/libwinpr/crypto/cipher.c index eff9c3c85..f7dd8354e 100644 --- a/winpr/libwinpr/crypto/cipher.c +++ b/winpr/libwinpr/crypto/cipher.c @@ -535,13 +535,20 @@ WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BY evp = winpr_openssl_get_evp_cipher(cipher); if (!evp) + { + free (ctx); return NULL; + } operation = (op == WINPR_ENCRYPT) ? 1 : 0; EVP_CIPHER_CTX_init(octx); if (EVP_CipherInit_ex(octx, evp, NULL, key, iv, operation) != 1) + { + EVP_CIPHER_CTX_cleanup(octx); + free (octx); return NULL; + } EVP_CIPHER_CTX_set_padding(octx, 0); #elif defined(WITH_MBEDTLS) @@ -549,18 +556,28 @@ WINPR_CIPHER_CTX* winpr_Cipher_New(int cipher, int op, const BYTE* key, const BY cipher_info = mbedtls_cipher_info_from_type(cipher_type); if (!cipher_info) + { + free (ctx); return NULL; + } operation = (op == WINPR_ENCRYPT) ? MBEDTLS_ENCRYPT : MBEDTLS_DECRYPT; mbedtls_cipher_init((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setup((mbedtls_cipher_context_t*) ctx, cipher_info) != 0) + { + free (ctx); return NULL; + } key_bitlen = mbedtls_cipher_get_key_bitlen((mbedtls_cipher_context_t*) ctx); if (mbedtls_cipher_setkey((mbedtls_cipher_context_t*) ctx, key, key_bitlen, operation) != 0) + { + mbedtls_cipher_free((mbedtls_cipher_context_t*) ctx); + free (ctx); return NULL; + } #endif return ctx; } From 19568c6e9b426658e72ca8821b41782cf23c89d9 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 11:12:32 +0100 Subject: [PATCH 093/128] Fixed indentation. --- winpr/libwinpr/crypto/crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c index a651a2fe7..4729a769b 100644 --- a/winpr/libwinpr/crypto/crypto.c +++ b/winpr/libwinpr/crypto/crypto.c @@ -186,7 +186,7 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) pCipherText = (BYTE*) malloc(cbOut); if (!pCipherText) - goto out; + goto out; if ((enc = winpr_Cipher_New(WINPR_CIPHER_AES_256_CBC, WINPR_ENCRYPT, pMemBlock->key, pMemBlock->iv)) == NULL) From 8482fbf85445e0c1a6e0817c4d7cd58e209c1aa4 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 12:34:53 +0100 Subject: [PATCH 094/128] Fixed formatting. --- channels/audin/client/audin_main.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index d72e15524..223b338b2 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -38,13 +38,13 @@ #include #include "audin_main.h" -#define MSG_SNDIN_VERSION 0x01 -#define MSG_SNDIN_FORMATS 0x02 -#define MSG_SNDIN_OPEN 0x03 -#define MSG_SNDIN_OPEN_REPLY 0x04 -#define MSG_SNDIN_DATA_INCOMING 0x05 -#define MSG_SNDIN_DATA 0x06 -#define MSG_SNDIN_FORMATCHANGE 0x07 +#define MSG_SNDIN_VERSION 0x01 +#define MSG_SNDIN_FORMATS 0x02 +#define MSG_SNDIN_OPEN 0x03 +#define MSG_SNDIN_OPEN_REPLY 0x04 +#define MSG_SNDIN_DATA_INCOMING 0x05 +#define MSG_SNDIN_DATA 0x06 +#define MSG_SNDIN_FORMATCHANGE 0x07 typedef struct _AUDIN_LISTENER_CALLBACK AUDIN_LISTENER_CALLBACK; struct _AUDIN_LISTENER_CALLBACK @@ -82,7 +82,7 @@ struct _AUDIN_PLUGIN /* Parsed plugin data */ UINT16 fixed_format; - UINT16 fixed_channel; + UINT16 fixed_channel; UINT32 fixed_rate; char* subsystem; char* device_name; @@ -860,7 +860,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) goto out; } } - else + else { while (entry && entry->subsystem && !audin->device) { From 46fa7ec481e0dc8668fe99b2d2c0806e7480ba6c Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 12:51:54 +0100 Subject: [PATCH 095/128] Fixed invalid stream copy length. --- libfreerdp/core/message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libfreerdp/core/message.c b/libfreerdp/core/message.c index 4692b00e5..76e0a69a9 100644 --- a/libfreerdp/core/message.c +++ b/libfreerdp/core/message.c @@ -192,7 +192,7 @@ static BOOL update_message_SurfaceCommand(rdpContext* context, wStream* s) if (!wParam) return FALSE; - Stream_Copy(wParam, s, Stream_Capacity(s)); + Stream_Copy(wParam, s, Stream_GetRemainingLength(s)); Stream_SetPosition(wParam, 0); return MessageQueue_Post(context->update->queue, (void*) context, From b69047064ad9134977c234da163c0a14dc45aa35 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 12:54:31 +0100 Subject: [PATCH 096/128] Replaced stream manipulation with EnsureCapacity. --- server/Sample/sfreerdp.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c index 96b6c9c4b..9095f4aa0 100644 --- a/server/Sample/sfreerdp.c +++ b/server/Sample/sfreerdp.c @@ -441,17 +441,13 @@ BOOL tf_peer_dump_rfx(freerdp_peer* client) while (pcap_has_next_record(pcap_rfx)) { - BYTE* tmp = NULL; if (!pcap_get_next_record_header(pcap_rfx, &record)) break; - tmp = realloc(Stream_Buffer(s), record.length); - if (!tmp) + if (!Stream_EnsureCapacity(s, record.length)) break; - Stream_SetBuffer(s, tmp); record.data = Stream_Buffer(s); - Stream_SetCapacity(s, record.length); pcap_get_next_record_content(pcap_rfx, &record); Stream_SetPointer(s, Stream_Buffer(s) + Stream_Capacity(s)); From 4e4d2e11d43e8ac9e3eea65f23121300bb0cfb36 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 14:43:33 +0100 Subject: [PATCH 097/128] Fixed crypto tests. --- winpr/libwinpr/crypto/test/TestCryptoHash.c | 32 ++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/winpr/libwinpr/crypto/test/TestCryptoHash.c b/winpr/libwinpr/crypto/test/TestCryptoHash.c index 71227ee80..ffdf3dba9 100644 --- a/winpr/libwinpr/crypto/test/TestCryptoHash.c +++ b/winpr/libwinpr/crypto/test/TestCryptoHash.c @@ -6,7 +6,7 @@ static const char* TEST_MD5_DATA = "test"; static const BYTE* TEST_MD5_HASH = (BYTE*) "\x09\x8f\x6b\xcd\x46\x21\xd3\x73\xca\xde\x4e\x83\x26\x27\xb4\xf6"; -BOOL test_crypto_hash_md5() +static BOOL test_crypto_hash_md5(void) { BYTE hash[WINPR_MD5_DIGEST_LENGTH]; WINPR_MD5_CTX ctx; @@ -31,7 +31,7 @@ BOOL test_crypto_hash_md5() free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -40,7 +40,7 @@ BOOL test_crypto_hash_md5() static const char* TEST_MD4_DATA = "test"; static const BYTE* TEST_MD4_HASH = (BYTE*) "\xdb\x34\x6d\x69\x1d\x7a\xcc\x4d\xc2\x62\x5d\xb1\x9f\x9e\x3f\x52"; -BOOL test_crypto_hash_md4() +static BOOL test_crypto_hash_md4(void) { BYTE hash[WINPR_MD4_DIGEST_LENGTH]; WINPR_MD4_CTX ctx; @@ -65,7 +65,7 @@ BOOL test_crypto_hash_md4() free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -74,7 +74,7 @@ BOOL test_crypto_hash_md4() static const char* TEST_SHA1_DATA = "test"; static const BYTE* TEST_SHA1_HASH = (BYTE*) "\xa9\x4a\x8f\xe5\xcc\xb1\x9b\xa6\x1c\x4c\x08\x73\xd3\x91\xe9\x87\x98\x2f\xbb\xd3"; -BOOL test_crypto_hash_sha1() +static BOOL test_crypto_hash_sha1(void) { BYTE hash[WINPR_SHA1_DIGEST_LENGTH]; WINPR_SHA1_CTX ctx; @@ -91,15 +91,15 @@ BOOL test_crypto_hash_sha1() char* actual; char* expected; - actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE); - expected = winpr_BinToHexString(TEST_SHA1_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE); + actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_SHA1_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected SHA1 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -109,32 +109,32 @@ static const char* TEST_HMAC_MD5_DATA = "Hi There"; static const BYTE* TEST_HMAC_MD5_KEY = (BYTE*) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; static const BYTE* TEST_HMAC_MD5_HASH = (BYTE*) "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d"; -BOOL test_crypto_hash_hmac_md5() +static BOOL test_crypto_hash_hmac_md5(void) { BYTE hash[WINPR_MD5_DIGEST_LENGTH]; WINPR_HMAC_CTX ctx; - if (!winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_SHA1_DIGEST_LENGTH)) + if (!winpr_HMAC_Init(&ctx, WINPR_MD_MD5, TEST_HMAC_MD5_KEY, WINPR_MD5_DIGEST_LENGTH)) return FALSE; if (!winpr_HMAC_Update(&ctx, (BYTE*) TEST_HMAC_MD5_DATA, strlen(TEST_HMAC_MD5_DATA))) return FALSE; if (!winpr_HMAC_Final(&ctx, hash, sizeof(hash))) return FALSE; - if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_SHA1_DIGEST_LENGTH) != 0) + if (memcmp(hash, TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH) != 0) { char* actual; char* expected; - actual = winpr_BinToHexString(hash, WINPR_SHA1_DIGEST_LENGTH, FALSE); - expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, WINPR_SHA1_DIGEST_LENGTH, FALSE); + actual = winpr_BinToHexString(hash, WINPR_MD5_DIGEST_LENGTH, FALSE); + expected = winpr_BinToHexString(TEST_HMAC_MD5_HASH, WINPR_MD5_DIGEST_LENGTH, FALSE); fprintf(stderr, "unexpected HMAC-MD5 hash: Actual: %s Expected: %s\n", actual, expected); free(actual); free(expected); - return -1; + return FALSE; } return TRUE; @@ -144,7 +144,7 @@ static const char* TEST_HMAC_SHA1_DATA = "Hi There"; static const BYTE* TEST_HMAC_SHA1_KEY = (BYTE*) "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; static const BYTE* TEST_HMAC_SHA1_HASH = (BYTE*) "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00"; -BOOL test_crypto_hash_hmac_sha1() +static BOOL test_crypto_hash_hmac_sha1(void) { BYTE hash[WINPR_SHA1_DIGEST_LENGTH]; WINPR_HMAC_CTX ctx; @@ -169,7 +169,7 @@ BOOL test_crypto_hash_hmac_sha1() free(actual); free(expected); - return -1; + return FALSE; } return TRUE; From 5acd80dd5b12f7086220cc93893dcccb13ee3945 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 15:18:19 +0100 Subject: [PATCH 098/128] Exporting channel entry points. --- channels/audin/client/audin_main.c | 2 ++ channels/disp/client/disp_main.c | 2 ++ channels/drive/client/drive_main.c | 2 ++ channels/echo/client/echo_main.c | 2 ++ channels/parallel/client/parallel_main.c | 2 ++ channels/printer/client/printer_main.c | 2 ++ channels/rdpei/client/rdpei_main.c | 2 ++ channels/rdpgfx/client/rdpgfx_main.c | 2 ++ channels/serial/client/serial_main.c | 2 ++ channels/tsmf/client/tsmf_main.c | 2 ++ channels/urbdrc/client/urbdrc_main.c | 2 ++ 11 files changed, 22 insertions(+) diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index 373ae86dc..b03643785 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -771,6 +771,8 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args) #ifdef STATIC_CHANNELS #define DVCPluginEntry audin_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index d70f61964..fb23d8b5e 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -340,6 +340,8 @@ UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DI #ifdef STATIC_CHANNELS #define DVCPluginEntry disp_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index e2a5a39ab..39ed054b9 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -859,6 +859,8 @@ out_error: #ifdef STATIC_CHANNELS #define DeviceServiceEntry drive_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif UINT sys_code_page = 0; diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index fe2d3631c..ba50aaaad 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -162,6 +162,8 @@ static UINT echo_plugin_terminated(IWTSPlugin* pPlugin) #ifdef STATIC_CHANNELS #define DVCPluginEntry echo_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index 2bd90f242..58bc9c2b1 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -394,6 +394,8 @@ static UINT parallel_free(DEVICE* device) #ifdef STATIC_CHANNELS #define DeviceServiceEntry parallel_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index fce501a18..02f72e190 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -451,6 +451,8 @@ error_out: #ifdef STATIC_CHANNELS #define DeviceServiceEntry printer_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index d1cbb7c07..6acfcc739 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -957,6 +957,8 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpei_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 7da8c9fd2..07ec66cc5 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -1515,6 +1515,8 @@ void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot) #ifdef STATIC_CHANNELS #define DVCPluginEntry rdpgfx_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/serial/client/serial_main.c b/channels/serial/client/serial_main.c index 548fa5675..b9650a9e5 100644 --- a/channels/serial/client/serial_main.c +++ b/channels/serial/client/serial_main.c @@ -813,6 +813,8 @@ static UINT serial_free(DEVICE* device) #ifdef STATIC_CHANNELS #define DeviceServiceEntry serial_DeviceServiceEntry +#else +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** diff --git a/channels/tsmf/client/tsmf_main.c b/channels/tsmf/client/tsmf_main.c index 6e373ecb9..bc202ead9 100644 --- a/channels/tsmf/client/tsmf_main.c +++ b/channels/tsmf/client/tsmf_main.c @@ -527,6 +527,8 @@ static UINT tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args) #ifdef STATIC_CHANNELS #define DVCPluginEntry tsmf_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** diff --git a/channels/urbdrc/client/urbdrc_main.c b/channels/urbdrc/client/urbdrc_main.c index 1e4c0a771..cbb937996 100644 --- a/channels/urbdrc/client/urbdrc_main.c +++ b/channels/urbdrc/client/urbdrc_main.c @@ -1541,6 +1541,8 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args) #ifdef STATIC_CHANNELS #define DVCPluginEntry urbdrc_DVCPluginEntry +#else +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** From 68c402ac58339e9f75f8dc0dd93ac435bac6a74d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 15:18:47 +0100 Subject: [PATCH 099/128] Removed windows module.def files. All symbols exported from libraries are declared using *_API defines. --- channels/cliprdr/client/module.def | 3 -- channels/drive/client/module.def | 3 -- client/common/module.def | 3 -- server/common/module.def | 3 -- winpr/libwinpr/asn1/module.def | 3 -- winpr/libwinpr/com/module.def | 2 -- winpr/libwinpr/comm/module.def | 3 -- winpr/libwinpr/credentials/module.def | 2 -- winpr/libwinpr/credui/module.def | 2 -- winpr/libwinpr/crt/module.def | 2 -- winpr/libwinpr/crypto/module.def | 3 -- winpr/libwinpr/dsparse/module.def | 3 -- winpr/libwinpr/environment/module.def | 2 -- winpr/libwinpr/error/module.def | 3 -- winpr/libwinpr/handle/module.def | 3 -- winpr/libwinpr/heap/module.def | 2 -- winpr/libwinpr/interlocked/module.def | 14 -------- winpr/libwinpr/io/module.def | 2 -- winpr/libwinpr/library/module.def | 3 -- .../library/test/TestLibraryA/module.def | 4 --- .../library/test/TestLibraryB/module.def | 4 --- winpr/libwinpr/locale/module.def | 2 -- winpr/libwinpr/memory/module.def | 3 -- winpr/libwinpr/nt/module.def | 3 -- winpr/libwinpr/pipe/module.def | 3 -- winpr/libwinpr/pool/module.def | 3 -- winpr/libwinpr/registry/module.def | 2 -- winpr/libwinpr/rpc/module.def | 3 -- winpr/libwinpr/security/module.def | 2 -- winpr/libwinpr/smartcard/module.def | 3 -- winpr/libwinpr/sspi/module.def | 34 ------------------- winpr/libwinpr/sysinfo/module.def | 3 -- winpr/libwinpr/thread/module.def | 3 -- winpr/libwinpr/winsock/module.def | 3 -- winpr/libwinpr/wnd/module.def | 3 -- 35 files changed, 139 deletions(-) delete mode 100644 channels/cliprdr/client/module.def delete mode 100644 channels/drive/client/module.def delete mode 100644 client/common/module.def delete mode 100644 server/common/module.def delete mode 100644 winpr/libwinpr/asn1/module.def delete mode 100644 winpr/libwinpr/com/module.def delete mode 100644 winpr/libwinpr/comm/module.def delete mode 100644 winpr/libwinpr/credentials/module.def delete mode 100644 winpr/libwinpr/credui/module.def delete mode 100644 winpr/libwinpr/crt/module.def delete mode 100644 winpr/libwinpr/crypto/module.def delete mode 100644 winpr/libwinpr/dsparse/module.def delete mode 100644 winpr/libwinpr/environment/module.def delete mode 100644 winpr/libwinpr/error/module.def delete mode 100644 winpr/libwinpr/handle/module.def delete mode 100644 winpr/libwinpr/heap/module.def delete mode 100644 winpr/libwinpr/interlocked/module.def delete mode 100644 winpr/libwinpr/io/module.def delete mode 100644 winpr/libwinpr/library/module.def delete mode 100644 winpr/libwinpr/library/test/TestLibraryA/module.def delete mode 100644 winpr/libwinpr/library/test/TestLibraryB/module.def delete mode 100644 winpr/libwinpr/locale/module.def delete mode 100644 winpr/libwinpr/memory/module.def delete mode 100644 winpr/libwinpr/nt/module.def delete mode 100644 winpr/libwinpr/pipe/module.def delete mode 100644 winpr/libwinpr/pool/module.def delete mode 100644 winpr/libwinpr/registry/module.def delete mode 100644 winpr/libwinpr/rpc/module.def delete mode 100644 winpr/libwinpr/security/module.def delete mode 100644 winpr/libwinpr/smartcard/module.def delete mode 100644 winpr/libwinpr/sspi/module.def delete mode 100644 winpr/libwinpr/sysinfo/module.def delete mode 100644 winpr/libwinpr/thread/module.def delete mode 100644 winpr/libwinpr/winsock/module.def delete mode 100644 winpr/libwinpr/wnd/module.def diff --git a/channels/cliprdr/client/module.def b/channels/cliprdr/client/module.def deleted file mode 100644 index 7336368ec..000000000 --- a/channels/cliprdr/client/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "cliprdr" -EXPORTS - VirtualChannelEntry @1 diff --git a/channels/drive/client/module.def b/channels/drive/client/module.def deleted file mode 100644 index 82b96df27..000000000 --- a/channels/drive/client/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "drive" -EXPORTS - DeviceServiceEntry @1 diff --git a/client/common/module.def b/client/common/module.def deleted file mode 100644 index f54443e02..000000000 --- a/client/common/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "freerdp-client" -EXPORTS - diff --git a/server/common/module.def b/server/common/module.def deleted file mode 100644 index 17f147374..000000000 --- a/server/common/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "freerdp-server" -EXPORTS - diff --git a/winpr/libwinpr/asn1/module.def b/winpr/libwinpr/asn1/module.def deleted file mode 100644 index eba1a913a..000000000 --- a/winpr/libwinpr/asn1/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-asn1" -EXPORTS - diff --git a/winpr/libwinpr/com/module.def b/winpr/libwinpr/com/module.def deleted file mode 100644 index 4467b6c7b..000000000 --- a/winpr/libwinpr/com/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-com" -EXPORTS diff --git a/winpr/libwinpr/comm/module.def b/winpr/libwinpr/comm/module.def deleted file mode 100644 index 44feb6f4e..000000000 --- a/winpr/libwinpr/comm/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr" -EXPORTS - diff --git a/winpr/libwinpr/credentials/module.def b/winpr/libwinpr/credentials/module.def deleted file mode 100644 index 1d5bc0e56..000000000 --- a/winpr/libwinpr/credentials/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-credentials" -EXPORTS diff --git a/winpr/libwinpr/credui/module.def b/winpr/libwinpr/credui/module.def deleted file mode 100644 index 70ec4964d..000000000 --- a/winpr/libwinpr/credui/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-credui" -EXPORTS diff --git a/winpr/libwinpr/crt/module.def b/winpr/libwinpr/crt/module.def deleted file mode 100644 index 3c3c4ffb4..000000000 --- a/winpr/libwinpr/crt/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-crt" -EXPORTS diff --git a/winpr/libwinpr/crypto/module.def b/winpr/libwinpr/crypto/module.def deleted file mode 100644 index d21b12685..000000000 --- a/winpr/libwinpr/crypto/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-crypto" -EXPORTS - diff --git a/winpr/libwinpr/dsparse/module.def b/winpr/libwinpr/dsparse/module.def deleted file mode 100644 index 683aae863..000000000 --- a/winpr/libwinpr/dsparse/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-dsparse" -EXPORTS - diff --git a/winpr/libwinpr/environment/module.def b/winpr/libwinpr/environment/module.def deleted file mode 100644 index e46493ad3..000000000 --- a/winpr/libwinpr/environment/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-environment" -EXPORTS diff --git a/winpr/libwinpr/error/module.def b/winpr/libwinpr/error/module.def deleted file mode 100644 index be897a9a8..000000000 --- a/winpr/libwinpr/error/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-error" -EXPORTS - diff --git a/winpr/libwinpr/handle/module.def b/winpr/libwinpr/handle/module.def deleted file mode 100644 index 5e4d32f95..000000000 --- a/winpr/libwinpr/handle/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-handle" -EXPORTS - diff --git a/winpr/libwinpr/heap/module.def b/winpr/libwinpr/heap/module.def deleted file mode 100644 index 7b6e836dd..000000000 --- a/winpr/libwinpr/heap/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-heap" -EXPORTS diff --git a/winpr/libwinpr/interlocked/module.def b/winpr/libwinpr/interlocked/module.def deleted file mode 100644 index 39f295109..000000000 --- a/winpr/libwinpr/interlocked/module.def +++ /dev/null @@ -1,14 +0,0 @@ -LIBRARY "libwinpr-interlocked" -EXPORTS - ; Not required on windows > 5.1 - ; InterlockedCompareExchange64 @1 - InitializeListHead @2 - IsListEmpty @3 - RemoveEntryList @4 - InsertHeadList @5 - RemoveHeadList @6 - InsertTailList @7 - RemoveTailList @8 - AppendTailList @9 - PushEntryList @10 - PopEntryList @11 diff --git a/winpr/libwinpr/io/module.def b/winpr/libwinpr/io/module.def deleted file mode 100644 index 1f984b577..000000000 --- a/winpr/libwinpr/io/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-io" -EXPORTS diff --git a/winpr/libwinpr/library/module.def b/winpr/libwinpr/library/module.def deleted file mode 100644 index c4a5071c4..000000000 --- a/winpr/libwinpr/library/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-library" -EXPORTS - diff --git a/winpr/libwinpr/library/test/TestLibraryA/module.def b/winpr/libwinpr/library/test/TestLibraryA/module.def deleted file mode 100644 index d49a3e406..000000000 --- a/winpr/libwinpr/library/test/TestLibraryA/module.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY "TestLibraryA" -EXPORTS - FunctionA @1 - FunctionB @2 diff --git a/winpr/libwinpr/library/test/TestLibraryB/module.def b/winpr/libwinpr/library/test/TestLibraryB/module.def deleted file mode 100644 index 19ab14dd0..000000000 --- a/winpr/libwinpr/library/test/TestLibraryB/module.def +++ /dev/null @@ -1,4 +0,0 @@ -LIBRARY "TestLibraryB" -EXPORTS - FunctionA @1 - FunctionB @2 diff --git a/winpr/libwinpr/locale/module.def b/winpr/libwinpr/locale/module.def deleted file mode 100644 index 593aba52f..000000000 --- a/winpr/libwinpr/locale/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-locale" -EXPORTS diff --git a/winpr/libwinpr/memory/module.def b/winpr/libwinpr/memory/module.def deleted file mode 100644 index 14a9402ee..000000000 --- a/winpr/libwinpr/memory/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-memory" -EXPORTS - diff --git a/winpr/libwinpr/nt/module.def b/winpr/libwinpr/nt/module.def deleted file mode 100644 index b45c622b5..000000000 --- a/winpr/libwinpr/nt/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-nt" -EXPORTS - diff --git a/winpr/libwinpr/pipe/module.def b/winpr/libwinpr/pipe/module.def deleted file mode 100644 index 8c4cc1eac..000000000 --- a/winpr/libwinpr/pipe/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-pipe" -EXPORTS - diff --git a/winpr/libwinpr/pool/module.def b/winpr/libwinpr/pool/module.def deleted file mode 100644 index 1651b3c99..000000000 --- a/winpr/libwinpr/pool/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-pool" -EXPORTS - diff --git a/winpr/libwinpr/registry/module.def b/winpr/libwinpr/registry/module.def deleted file mode 100644 index d65f4556c..000000000 --- a/winpr/libwinpr/registry/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-registry" -EXPORTS diff --git a/winpr/libwinpr/rpc/module.def b/winpr/libwinpr/rpc/module.def deleted file mode 100644 index 63efed138..000000000 --- a/winpr/libwinpr/rpc/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-rpc" -EXPORTS - diff --git a/winpr/libwinpr/security/module.def b/winpr/libwinpr/security/module.def deleted file mode 100644 index 9857be66b..000000000 --- a/winpr/libwinpr/security/module.def +++ /dev/null @@ -1,2 +0,0 @@ -LIBRARY "libwinpr-security" -EXPORTS diff --git a/winpr/libwinpr/smartcard/module.def b/winpr/libwinpr/smartcard/module.def deleted file mode 100644 index 3691a2338..000000000 --- a/winpr/libwinpr/smartcard/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-smartcard" -EXPORTS - diff --git a/winpr/libwinpr/sspi/module.def b/winpr/libwinpr/sspi/module.def deleted file mode 100644 index b08f89731..000000000 --- a/winpr/libwinpr/sspi/module.def +++ /dev/null @@ -1,34 +0,0 @@ -LIBRARY "libwinpr-sspi" -EXPORTS - AcceptSecurityContext - AcquireCredentialsHandleA - AcquireCredentialsHandleW - ApplyControlToken - CompleteAuthToken - DecryptMessage - DeleteSecurityContext - EncryptMessage - EnumerateSecurityPackagesA - EnumerateSecurityPackagesW - ExportSecurityContext - FreeContextBuffer - FreeCredentialsHandle - ImpersonateSecurityContext - ImportSecurityContextA - ImportSecurityContextW - InitSecurityInterfaceA - InitSecurityInterfaceW - InitializeSecurityContextA - InitializeSecurityContextW - MakeSignature - QueryContextAttributesA - QueryContextAttributesW - QueryCredentialsAttributesA - QueryCredentialsAttributesW - QuerySecurityContextToken - QuerySecurityPackageInfoA - QuerySecurityPackageInfoW - RevertSecurityContext - VerifySignature - InitSecurityInterfaceExA - InitSecurityInterfaceExW diff --git a/winpr/libwinpr/sysinfo/module.def b/winpr/libwinpr/sysinfo/module.def deleted file mode 100644 index 50f4066fc..000000000 --- a/winpr/libwinpr/sysinfo/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-sysinfo" -EXPORTS - diff --git a/winpr/libwinpr/thread/module.def b/winpr/libwinpr/thread/module.def deleted file mode 100644 index 688109ba6..000000000 --- a/winpr/libwinpr/thread/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-thread" -EXPORTS - diff --git a/winpr/libwinpr/winsock/module.def b/winpr/libwinpr/winsock/module.def deleted file mode 100644 index e4d0419ce..000000000 --- a/winpr/libwinpr/winsock/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-winsock" -EXPORTS - diff --git a/winpr/libwinpr/wnd/module.def b/winpr/libwinpr/wnd/module.def deleted file mode 100644 index de91bf1fa..000000000 --- a/winpr/libwinpr/wnd/module.def +++ /dev/null @@ -1,3 +0,0 @@ -LIBRARY "libwinpr-wnd" -EXPORTS - From c182be093dd909da953e87b3cdeb188e71e7bb73 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 29 Feb 2016 15:24:07 +0100 Subject: [PATCH 100/128] Removed module.def from build config. --- client/common/CMakeLists.txt | 2 +- server/common/CMakeLists.txt | 2 +- winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt | 2 +- winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt index 5502696d9..95c8e98e0 100644 --- a/client/common/CMakeLists.txt +++ b/client/common/CMakeLists.txt @@ -39,7 +39,7 @@ foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS}) endforeach() if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() # On windows create dll version information. diff --git a/server/common/CMakeLists.txt b/server/common/CMakeLists.txt index d5b990610..009d5662a 100644 --- a/server/common/CMakeLists.txt +++ b/server/common/CMakeLists.txt @@ -33,7 +33,7 @@ foreach(FREERDP_CHANNELS_SERVER_SRC ${FREERDP_CHANNELS_SERVER_SRCS}) endforeach() if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() diff --git a/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt b/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt index 3241f0939..b7c0649e2 100644 --- a/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt +++ b/winpr/libwinpr/library/test/TestLibraryA/CMakeLists.txt @@ -21,7 +21,7 @@ set(MODULE_PREFIX "TEST_LIBRARY_A") set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} TestLibraryA.c) if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) diff --git a/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt b/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt index ec4e85c63..c1cc32a2f 100644 --- a/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt +++ b/winpr/libwinpr/library/test/TestLibraryB/CMakeLists.txt @@ -21,7 +21,7 @@ set(MODULE_PREFIX "TEST_LIBRARY_B") set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} TestLibraryB.c) if(MSVC) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def) + set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS}) endif() add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS}) From 5a7ac964c3de43ada7676b419a876b41adbaf2af Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 29 Feb 2016 16:00:35 +0100 Subject: [PATCH 101/128] build/win32: fix DLL version information Swap build and patch. Now uses the format major.minor.patch.build --- cmake/WindowsDLLVersion.rc.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/WindowsDLLVersion.rc.in b/cmake/WindowsDLLVersion.rc.in index cebd5f22a..5a0da5eae 100644 --- a/cmake/WindowsDLLVersion.rc.in +++ b/cmake/WindowsDLLVersion.rc.in @@ -19,7 +19,7 @@ BEGIN BEGIN VALUE "CompanyName", "@RC_VERSION_VENDOR@" VALUE "FileDescription", "@RC_VERSION_DESCRIPTION@" - VALUE "FileVersion", "@RC_VERSION_MAJOR@,@RC_VERSION_MINOR@,@RC_VERSION_BUILD@,@RC_VERSION_PATCH@" + VALUE "FileVersion", "@RC_VERSION_MAJOR@,@RC_VERSION_MINOR@,@RC_VERSION_PATCH@,@RC_VERSION_BUILD@" VALUE "InternalName", "@RC_VERSION_FILE@" VALUE "LegalCopyright", "Copyright (C) 2011-@RC_VERSION_YEAR@" VALUE "OriginalFilename", "@RC_VERSION_FILE@" From f15c050d1fb3769b92e69872f5be84375f7d6d2b Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 29 Feb 2016 16:02:13 +0100 Subject: [PATCH 102/128] shadow/subsystem: fix windows build * add dependency to freerdp-client * add version information to freerdp-shadow-cli --- server/shadow/CMakeLists.txt | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index 13c0f480d..aa1431a8e 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -15,11 +15,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +# freerdp-shadow library + set(MODULE_NAME "freerdp-shadow") set(MODULE_PREFIX "FREERDP_SERVER_SHADOW") -include_directories(${OPENSSL_INCLUDE_DIR}) - set(${MODULE_PREFIX}_SRCS shadow_client.c shadow_client.h @@ -75,7 +75,6 @@ list(APPEND ${MODULE_PREFIX}_LIBS freerdp) list(APPEND ${MODULE_PREFIX}_LIBS freerdp-server) list(APPEND ${MODULE_PREFIX}_LIBS winpr) list(APPEND ${MODULE_PREFIX}_LIBS winpr-makecert-tool) - list(APPEND ${MODULE_PREFIX}_LIBS rdtk) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) @@ -108,6 +107,20 @@ elseif(APPLE AND NOT IOS) set(WITH_SHADOW_MAC 1) endif() +if (WIN32) + set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}) + set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR}) + set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION}) + set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" ) + + configure_file( + ${CMAKE_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in + ${CMAKE_CURRENT_BINARY_DIR}/version.rc + @ONLY) + + set ( ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) +endif() + # Authentication if(WITH_SHADOW_X11 OR WITH_SHADOW_MAC) @@ -219,13 +232,13 @@ if(WITH_SHADOW_X11) include_directories(${XRANDR_INCLUDE_DIRS}) list(APPEND ${MODULE_PREFIX}_X11_LIBS ${XRANDR_LIBRARIES}) endif() -endif() - -if(WITH_SHADOW_MAC) +elseif(WITH_SHADOW_MAC) find_library(IOKIT IOKit) find_library(IOSURFACE IOSurface) find_library(CARBON Carbon) list(APPEND ${MODULE_PREFIX}_MAC_LIBS ${IOKIT} ${IOSURFACE} ${CARBON}) +elseif(WITH_SHADOW_WIN) + list(APPEND ${MODULE_PREFIX}_WIN_LIBS freerdp-client) endif() set(${MODULE_PREFIX}_WIN_SRCS @@ -273,6 +286,7 @@ if (WITH_LIBRARY_VERSIONING) endif() install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server) + if (WITH_DEBUG_SYMBOLS AND MSVC) install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols) @@ -288,7 +302,7 @@ set(MODULE_PREFIX "FREERDP_SERVER_SHADOW_CLI") set(${MODULE_PREFIX}_SRCS shadow.c) - # On windows create dll version information. +# On windows create dll version information. # Vendor, product and year are already set in top level CMakeLists.txt if (WIN32) set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR}) From 1b926f87401de32190f3ef8712f673ca4bd4ce7a Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 29 Feb 2016 16:22:24 +0100 Subject: [PATCH 103/128] build: export freerdp-shadow pkg-config and cmake find package --- server/shadow/CMakeLists.txt | 26 +++++++++++++++++++-- server/shadow/FreeRDP-ShadowConfig.cmake.in | 10 ++++++++ server/shadow/freerdp-shadow.pc.in | 15 ++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 server/shadow/FreeRDP-ShadowConfig.cmake.in create mode 100644 server/shadow/freerdp-shadow.pc.in diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt index aa1431a8e..3eb741d6a 100644 --- a/server/shadow/CMakeLists.txt +++ b/server/shadow/CMakeLists.txt @@ -83,7 +83,7 @@ if (WITH_LIBRARY_VERSIONING) set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION}) endif() -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server) +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server EXPORT FreeRDP-ShadowTargets) if (WITH_DEBUG_SYMBOLS AND MSVC) install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols) @@ -285,7 +285,7 @@ if (WITH_LIBRARY_VERSIONING) set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION}) endif() -install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server) +install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT server EXPORT FreeRDP-ShadowTargets) if (WITH_DEBUG_SYMBOLS AND MSVC) install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} @@ -331,3 +331,25 @@ if (WITH_DEBUG_SYMBOLS AND MSVC) endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow") + +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp-shadow.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp-shadow${FREERDP_VERSION_MAJOR}.pc @ONLY) +install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp-shadow${FREERDP_VERSION_MAJOR}.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + +if(${CMAKE_VERSION} VERSION_GREATER "2.8.10") + + export(PACKAGE freerdp-shadow) + + set(FREERDP_SERVER_CMAKE_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}/cmake/FreeRDP-Shadow${FREERDP_VERSION_MAJOR}") + + configure_package_config_file(FreeRDP-ShadowConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfig.cmake + INSTALL_DESTINATION ${FREERDP_SERVER_CMAKE_INSTALL_DIR} + PATH_VARS FREERDP_INCLUDE_DIR) + + write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfigVersion.cmake + VERSION ${FREERDP_VERSION} COMPATIBILITY SameMajorVersion) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/FreeRDP-ShadowConfigVersion.cmake + DESTINATION ${FREERDP_SERVER_CMAKE_INSTALL_DIR}) + + install(EXPORT FreeRDP-ShadowTargets DESTINATION ${FREERDP_SERVER_CMAKE_INSTALL_DIR}) +endif() diff --git a/server/shadow/FreeRDP-ShadowConfig.cmake.in b/server/shadow/FreeRDP-ShadowConfig.cmake.in new file mode 100644 index 000000000..1eb11e0f5 --- /dev/null +++ b/server/shadow/FreeRDP-ShadowConfig.cmake.in @@ -0,0 +1,10 @@ + +@PACKAGE_INIT@ + +set(FreeRDP-Shadow_VERSION_MAJOR "@FREERDP_VERSION_MAJOR@") +set(FreeRDP-Shadow_VERSION_MINOR "@FREERDP_VERSION_MINOR@") +set(FreeRDP-Shadow_VERSION_REVISION "@FREERDP_VERSION_REVISION@") + +set_and_check(FreeRDP-Shadow_INCLUDE_DIR "@PACKAGE_FREERDP_INCLUDE_DIR@") + +include("${CMAKE_CURRENT_LIST_DIR}/FreeRDP-ShadowTargets.cmake") diff --git a/server/shadow/freerdp-shadow.pc.in b/server/shadow/freerdp-shadow.pc.in new file mode 100644 index 000000000..49449e816 --- /dev/null +++ b/server/shadow/freerdp-shadow.pc.in @@ -0,0 +1,15 @@ +prefix=@CMAKE_INSTALL_PREFIX@ +exec_prefix=@CMAKE_INSTALL_PREFIX@ +libdir=@CMAKE_INSTALL_FULL_LIBDIR@ +includedir=${prefix}/@FREERDP_INCLUDE_DIR@ +libs=-lfreerdp-shadow + +Name: FreeRDP shadow +Description: FreeRDP: A Remote Desktop Protocol Implementation +URL: http://www.freerdp.com/ +Version: @FREERDP_VERSION@ +Requires: +Requires.private: @WINPR_PKG_CONFIG_FILENAME@ freerdp@FREERDP_VERSION_MAJOR@ freerdp-shadow@FREERDP_VERSION_MAJOR@ +Libs: -L${libdir} ${libs} +Libs.private: -ldl -lpthread +Cflags: -I${includedir} From 16887384526f2985c0ff900b870e23c97d5f1317 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Mon, 29 Feb 2016 16:25:04 +0100 Subject: [PATCH 104/128] ci: build server side on windows --- ci/cmake-preloads/config-windows.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/cmake-preloads/config-windows.txt b/ci/cmake-preloads/config-windows.txt index 980bcb2cb..0a84d883d 100644 --- a/ci/cmake-preloads/config-windows.txt +++ b/ci/cmake-preloads/config-windows.txt @@ -1,3 +1,4 @@ message("PRELOADING windows cache") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") +set(WITH_SERVER "ON" CACHE BOOL "Build server binaries") #set (BUILD_TESTING ON CACHE BOOL "build testing") From a98e0f9ebbcce74129a552ae555ed8fdd4144b56 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 1 Mar 2016 10:29:51 +0100 Subject: [PATCH 105/128] Reverted opaque structures. --- winpr/include/winpr/stream.h | 104 ++++++++++++----------------------- 1 file changed, 34 insertions(+), 70 deletions(-) diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index 5c1cc9076..50f1aa904 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -52,38 +52,32 @@ WINPR_API void Stream_Free(wStream* s, BOOL bFreeBuffer); static INLINE void Stream_Seek(wStream* s, size_t _offset) { - struct _wStream* _s = (struct _wStream*)s; - _s->pointer += (_offset); + s->pointer += (_offset); } static INLINE void Stream_Rewind(wStream* s, size_t _offset) { - struct _wStream* _s = (struct _wStream*)s; - _s->pointer -= (_offset); + s->pointer -= (_offset); } -#define _stream_read_n8(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n8(_t, _s, _v, _p) do { \ _v = \ (_t)(*_s->pointer); \ if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n16_le(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n16_le(_t, _s, _v, _p) do { \ _v = \ (_t)(*_s->pointer) + \ (((_t)(*(_s->pointer + 1))) << 8); \ if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n16_be(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n16_be(_t, _s, _v, _p) do { \ _v = \ (((_t)(*_s->pointer)) << 8) + \ (_t)(*(_s->pointer + 1)); \ if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n32_le(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n32_le(_t, _s, _v, _p) do { \ _v = \ (_t)(*_s->pointer) + \ (((_t)(*(_s->pointer + 1))) << 8) + \ @@ -91,8 +85,7 @@ static INLINE void Stream_Rewind(wStream* s, size_t _offset) (((_t)(*(_s->pointer + 3))) << 24); \ if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n32_be(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n32_be(_t, _s, _v, _p) do { \ _v = \ (((_t)(*(_s->pointer))) << 24) + \ (((_t)(*(_s->pointer + 1))) << 16) + \ @@ -100,8 +93,7 @@ static INLINE void Stream_Rewind(wStream* s, size_t _offset) (((_t)(*(_s->pointer + 3)))); \ if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n64_le(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n64_le(_t, _s, _v, _p) do { \ _v = \ (_t)(*_s->pointer) + \ (((_t)(*(_s->pointer + 1))) << 8) + \ @@ -113,8 +105,7 @@ static INLINE void Stream_Rewind(wStream* s, size_t _offset) (((_t)(*(_s->pointer + 7))) << 56); \ if (_p) Stream_Seek(_s, sizeof(_t)); } while (0) -#define _stream_read_n64_be(_t, __s, _v, _p) do { \ - struct _wStream* _s = (struct _wStream*)__s; \ +#define _stream_read_n64_be(_t, _s, _v, _p) do { \ _v = \ (((_t)(*(_s->pointer))) << 56) + \ (((_t)(*(_s->pointer + 1))) << 48) + \ @@ -147,9 +138,8 @@ static INLINE void Stream_Rewind(wStream* s, size_t _offset) #define Stream_Read_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, TRUE) #define Stream_Read_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, TRUE) -static INLINE void Stream_Read(wStream* s, void* _b, size_t _n) +static INLINE void Stream_Read(wStream* _s, void* _b, size_t _n) { - struct _wStream* _s = (struct _wStream*)s; memcpy(_b, (_s->pointer), (_n)); Stream_Seek(_s, _n); } @@ -175,51 +165,44 @@ static INLINE void Stream_Read(wStream* s, void* _b, size_t _n) #define Stream_Peek_UINT64_BE(_s, _v) _stream_read_n64_be(UINT64, _s, _v, FALSE) #define Stream_Peek_INT64_BE(_s, _v) _stream_read_n64_be(INT64, _s, _v, FALSE) -static INLINE void Stream_Peek(wStream* s, void* _b, size_t _n) +static INLINE void Stream_Peek(wStream* _s, void* _b, size_t _n) { - struct _wStream* _s = (struct _wStream*)s; memcpy(_b, (_s->pointer), (_n)); } -static INLINE void Stream_Write_UINT8(wStream* s, UINT8 _v) +static INLINE void Stream_Write_UINT8(wStream* _s, UINT8 _v) { - struct _wStream* _s = (struct _wStream*)s; *_s->pointer++ = (UINT8)(_v); } -static INLINE void Stream_Write_UINT16(wStream* s, UINT16 _v) +static INLINE void Stream_Write_UINT16(wStream* _s, UINT16 _v) { - struct _wStream* _s = (struct _wStream*)s; *_s->pointer++ = (_v) & 0xFF; *_s->pointer++ = ((_v) >> 8) & 0xFF; } -static INLINE void Stream_Write_UINT16_BE(wStream* s, UINT16 _v) +static INLINE void Stream_Write_UINT16_BE(wStream* _s, UINT16 _v) { - struct _wStream* _s = (struct _wStream*)s; *_s->pointer++ = ((_v) >> 8) & 0xFF; *_s->pointer++ = (_v) & 0xFF; } -static INLINE void Stream_Write_UINT32(wStream* s, UINT32 _v) +static INLINE void Stream_Write_UINT32(wStream* _s, UINT32 _v) { - struct _wStream* _s = (struct _wStream*)s; *_s->pointer++ = (_v) & 0xFF; *_s->pointer++ = ((_v) >> 8) & 0xFF; *_s->pointer++ = ((_v) >> 16) & 0xFF; *_s->pointer++ = ((_v) >> 24) & 0xFF; } -static INLINE void Stream_Write_UINT32_BE(wStream* s, UINT32 _v) +static INLINE void Stream_Write_UINT32_BE(wStream* _s, UINT32 _v) { - struct _wStream* _s = (struct _wStream*)s; Stream_Write_UINT16_BE(_s, ((_v) >> 16 & 0xFFFF)); Stream_Write_UINT16_BE(_s, ((_v) & 0xFFFF)); } -static INLINE void Stream_Write_UINT64(wStream* s, UINT64 _v) +static INLINE void Stream_Write_UINT64(wStream* _s, UINT64 _v) { - struct _wStream* _s = (struct _wStream*)s; *_s->pointer++ = (UINT64)(_v) & 0xFF; *_s->pointer++ = ((UINT64)(_v) >> 8) & 0xFF; *_s->pointer++ = ((UINT64)(_v) >> 16) & 0xFF; @@ -229,9 +212,8 @@ static INLINE void Stream_Write_UINT64(wStream* s, UINT64 _v) *_s->pointer++ = ((UINT64)(_v) >> 48) & 0xFF; *_s->pointer++ = ((UINT64)(_v) >> 56) & 0xFF; } -static INLINE void Stream_Write(wStream* s, const void* _b, size_t _n) +static INLINE void Stream_Write(wStream* _s, const void* _b, size_t _n) { - struct _wStream* _s = (struct _wStream*)s; memcpy(_s->pointer, (_b), (_n)); Stream_Seek(_s, _n); } @@ -246,109 +228,91 @@ static INLINE void Stream_Write(wStream* s, const void* _b, size_t _n) #define Stream_Rewind_UINT32(_s) Stream_Rewind(_s, 4) #define Stream_Rewind_UINT64(_s) Stream_Rewind(_s, 8) -static INLINE void Stream_Zero(wStream* s, size_t _n) +static INLINE void Stream_Zero(wStream* _s, size_t _n) { - struct _wStream* _s = (struct _wStream*)s; memset(_s->pointer, '\0', (_n)); Stream_Seek(_s, _n); } -static INLINE void Stream_Fill(wStream* s, int _v, size_t _n) +static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n) { - struct _wStream* _s = (struct _wStream*)s; memset(_s->pointer, _v, (_n)); Stream_Seek(_s, _n); } -static INLINE void Stream_Copy(wStream* dst, wStream* src, size_t _n) +static INLINE void Stream_Copy(wStream* _dst, wStream* _src, size_t _n) { - struct _wStream* _src = (struct _wStream*)src; - struct _wStream* _dst = (struct _wStream*)dst; - memcpy(_dst->pointer, _src->pointer, _n); Stream_Seek(_dst, _n); Stream_Seek(_src, _n); } -static INLINE BYTE* Stream_Buffer(wStream* s) +static INLINE BYTE* Stream_Buffer(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; return _s->buffer; } #define Stream_GetBuffer(_s, _b) _b = Stream_Buffer(_s) -static INLINE void Stream_SetBuffer(wStream* s, BYTE* _b) +static INLINE void Stream_SetBuffer(wStream* _s, BYTE* _b) { - struct _wStream* _s = (struct _wStream*)s; _s->buffer = _b; } -static INLINE BYTE* Stream_Pointer(wStream* s) +static INLINE BYTE* Stream_Pointer(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; return _s->pointer; } #define Stream_GetPointer(_s, _p) _p = Stream_Pointer(_s) -static INLINE void Stream_SetPointer(wStream* s, BYTE* _p) +static INLINE void Stream_SetPointer(wStream* _s, BYTE* _p) { - struct _wStream* _s = (struct _wStream*)s; _s->pointer = _p; } -static INLINE size_t Stream_Length(wStream* s) +static INLINE size_t Stream_Length(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; return _s->length; } #define Stream_GetLength(_s, _l) _l = Stream_Length(_s) -static INLINE void Stream_SetLength(wStream* s, size_t _l) +static INLINE void Stream_SetLength(wStream* _s, size_t _l) { - struct _wStream* _s = (struct _wStream*)s; _s->length = _l; } -static INLINE size_t Stream_Capacity(wStream* s) +static INLINE size_t Stream_Capacity(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; return _s->capacity; } #define Stream_GetCapacity(_s, _c) _c = Stream_Capacity(_s); -static INLINE void Stream_SetCapacity(wStream* s, size_t _c) +static INLINE void Stream_SetCapacity(wStream* _s, size_t _c) { - struct _wStream* _s = (struct _wStream*)s; _s->capacity = _c; } -static INLINE size_t Stream_GetPosition(wStream* s) +static INLINE size_t Stream_GetPosition(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; return (_s->pointer - _s->buffer); } -static INLINE void Stream_SetPosition(wStream* s, size_t _p) +static INLINE void Stream_SetPosition(wStream* _s, size_t _p) { - struct _wStream* _s = (struct _wStream*)s; _s->pointer = _s->buffer + (_p); } -static INLINE void Stream_SealLength(wStream* s) +static INLINE void Stream_SealLength(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; _s->length = (_s->pointer - _s->buffer); } -static INLINE size_t Stream_GetRemainingLength(wStream* s) +static INLINE size_t Stream_GetRemainingLength(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; return (_s->length - (_s->pointer - _s->buffer)); } -static INLINE void Stream_Clear(wStream* s) +static INLINE void Stream_Clear(wStream* _s) { - struct _wStream* _s = (struct _wStream*)s; memset(_s->buffer, 0, _s->capacity); } From e7814d58554d5859b59221b3f6af00fbddaa9c8d Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 1 Mar 2016 11:39:21 +0100 Subject: [PATCH 106/128] Fixed stream API for Stream_Copy. --- channels/drdynvc/client/drdynvc_main.c | 4 ++-- channels/tsmf/client/tsmf_ifman.c | 2 +- libfreerdp/core/fastpath.c | 12 ++++++------ libfreerdp/core/message.c | 2 +- winpr/include/winpr/stream.h | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index 29111fde8..676dfb960 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -958,8 +958,8 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c Stream_Write_UINT8(data_out, 0x10 | cbChId); Stream_SetPosition(s, 1); - Stream_Copy(data_out, s, pos - 1); - + Stream_Copy(s, data_out, pos - 1); + if (channel_status == CHANNEL_RC_OK) { WLog_DBG(TAG, "channel created"); diff --git a/channels/tsmf/client/tsmf_ifman.c b/channels/tsmf/client/tsmf_ifman.c index b4a84dfdb..4c9da7421 100644 --- a/channels/tsmf/client/tsmf_ifman.c +++ b/channels/tsmf/client/tsmf_ifman.c @@ -79,7 +79,7 @@ UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman) if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4)) return ERROR_OUTOFMEMORY; pos = Stream_GetPosition(ifman->output); - Stream_Copy(ifman->output, ifman->input, ifman->input_size); + Stream_Copy(ifman->input, ifman->output, ifman->input_size); Stream_SetPosition(ifman->output, pos); if (Stream_GetRemainingLength(ifman->output) < 4) diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index 79fa00d6e..411d0e960 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -45,7 +45,7 @@ * Fast-Path packet format is defined in [MS-RDPBCGR] 2.2.9.1.2, which revises * server output packets from the first byte with the goal of improving * bandwidth. - * + * * Slow-Path packet always starts with TPKT header, which has the first * byte 0x03, while Fast-Path packet starts with 2 zero bits in the first * two less significant bits of the first byte. @@ -282,7 +282,7 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s if (!fastpath_recv_update_synchronize(fastpath, s)) WLog_ERR(TAG, "fastpath_recv_update_synchronize failure but we continue"); else - IFCALL(update->Synchronize, context); + IFCALL(update->Synchronize, context); break; case FASTPATH_UPDATETYPE_SURFCMDS: @@ -463,7 +463,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) Stream_SetPosition(fastpath->updateData, 0); - Stream_Copy(fastpath->updateData, cs, size); + Stream_Copy(cs, fastpath->updateData, size); } else if (fragmentation == FASTPATH_FRAGMENT_NEXT) { @@ -491,7 +491,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) goto out_fail; } - Stream_Copy(fastpath->updateData, cs, size); + Stream_Copy(cs, fastpath->updateData, size); } else if (fragmentation == FASTPATH_FRAGMENT_LAST) { @@ -519,7 +519,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) goto out_fail; } - Stream_Copy(fastpath->updateData, cs, size); + Stream_Copy(cs, fastpath->updateData, size); Stream_SealLength(fastpath->updateData); Stream_SetPosition(fastpath->updateData, 0); @@ -546,7 +546,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s) out_fail: if (cs != s) { - Stream_Release(cs); + Stream_Release(cs); } return -1; diff --git a/libfreerdp/core/message.c b/libfreerdp/core/message.c index 76e0a69a9..a56d1b58d 100644 --- a/libfreerdp/core/message.c +++ b/libfreerdp/core/message.c @@ -192,7 +192,7 @@ static BOOL update_message_SurfaceCommand(rdpContext* context, wStream* s) if (!wParam) return FALSE; - Stream_Copy(wParam, s, Stream_GetRemainingLength(s)); + Stream_Copy(s, wParam, Stream_GetRemainingLength(s)); Stream_SetPosition(wParam, 0); return MessageQueue_Post(context->update->queue, (void*) context, diff --git a/winpr/include/winpr/stream.h b/winpr/include/winpr/stream.h index 50f1aa904..7571a1380 100644 --- a/winpr/include/winpr/stream.h +++ b/winpr/include/winpr/stream.h @@ -240,7 +240,7 @@ static INLINE void Stream_Fill(wStream* _s, int _v, size_t _n) Stream_Seek(_s, _n); } -static INLINE void Stream_Copy(wStream* _dst, wStream* _src, size_t _n) +static INLINE void Stream_Copy(wStream* _src, wStream* _dst, size_t _n) { memcpy(_dst->pointer, _src->pointer, _n); Stream_Seek(_dst, _n); From a79072a87cae22379fefe2f912d48e08acb1b248 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Tue, 1 Mar 2016 11:40:11 +0100 Subject: [PATCH 107/128] Added tests for remaining stream functions. --- winpr/libwinpr/utils/test/TestStream.c | 273 ++++++++++++++++++++++++- 1 file changed, 264 insertions(+), 9 deletions(-) diff --git a/winpr/libwinpr/utils/test/TestStream.c b/winpr/libwinpr/utils/test/TestStream.c index 005dcef1b..7b0a75142 100644 --- a/winpr/libwinpr/utils/test/TestStream.c +++ b/winpr/libwinpr/utils/test/TestStream.c @@ -261,6 +261,252 @@ static BOOL TestStream_Reading(void) return result; } +static BOOL TestStream_Write(void) +{ + BOOL rc = FALSE; + UINT8 u8; + UINT16 u16; + UINT32 u32; + UINT64 u64; + const BYTE data[] = "someteststreamdata"; + wStream* s = Stream_New(NULL, 100); + if (!s) + goto out; + if (s->pointer != s->buffer) + goto out; + + Stream_Write(s, data, sizeof(data)); + if (memcmp(Stream_Buffer(s), data, sizeof(data)) == 0) + rc = TRUE; + if (s->pointer != s->buffer + sizeof(data)) + goto out; + + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Write_UINT8(s, 42); + if (s->pointer != s->buffer + 1) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Peek_UINT8(s, u8); + if (u8 != 42) + goto out; + + Stream_Write_UINT16(s, 0x1234); + if (s->pointer != s->buffer + 2) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Peek_UINT16(s, u16); + if (u16 != 0x1234) + goto out; + + Stream_Write_UINT32(s, 0x12345678UL); + if (s->pointer != s->buffer + 4) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Peek_UINT32(s, u32); + if (u32 != 0x12345678UL) + goto out; + + Stream_Write_UINT64(s, 0x1234567890ABCDEFULL); + if (s->pointer != s->buffer + 8) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Peek_UINT64(s, u64); + if (u64 != 0x1234567890ABCDEFULL) + goto out; +out: + Stream_Free(s, TRUE); + return rc; +} + +static BOOL TestStream_Seek(void) +{ + BOOL rc = FALSE; + wStream* s = Stream_New(NULL, 100); + if (!s) + goto out; + + if (s->pointer != s->buffer) + goto out; + + Stream_Seek(s, 5); + if (s->pointer != s->buffer + 5) + goto out; + Stream_Seek_UINT8(s); + if (s->pointer != s->buffer + 6) + goto out; + + Stream_Seek_UINT16(s); + if (s->pointer != s->buffer + 8) + goto out; + + Stream_Seek_UINT32(s); + if (s->pointer != s->buffer + 12) + goto out; + Stream_Seek_UINT64(s); + if (s->pointer != s->buffer + 20) + goto out; + + rc = TRUE; +out: + Stream_Free(s, TRUE); + return rc; +} + +static BOOL TestStream_Rewind(void) +{ + BOOL rc = FALSE; + wStream* s = Stream_New(NULL, 100); + if (!s) + goto out; + if (s->pointer != s->buffer) + goto out; + + Stream_Seek(s, 100); + if (s->pointer != s->buffer + 100) + goto out; + + Stream_Rewind(s, 10); + if (s->pointer != s->buffer + 90) + goto out; + Stream_Rewind_UINT8(s); + if (s->pointer != s->buffer + 89) + goto out; + Stream_Rewind_UINT16(s); + if (s->pointer != s->buffer + 87) + goto out; + + Stream_Rewind_UINT32(s); + if (s->pointer != s->buffer + 83) + goto out; + Stream_Rewind_UINT64(s); + if (s->pointer != s->buffer + 75) + goto out; + + rc = TRUE; +out: + Stream_Free(s, TRUE); + return rc; +} + +static BOOL TestStream_Zero(void) +{ + UINT32 x; + BOOL rc = FALSE; + const BYTE data[] = "someteststreamdata"; + wStream* s = Stream_New(NULL, sizeof(data)); + if (!s) + goto out; + + Stream_Write(s, data, sizeof(data)); + if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Zero(s, 5); + if (s->pointer != s->buffer + 5) + goto out; + if (memcmp(Stream_Pointer(s), data+5, sizeof(data)-5) != 0) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + for (x=0; x<5; x++) + { + UINT8 val; + Stream_Read_UINT8(s, val); + if (val != 0) + goto out; + } + + rc = TRUE; +out: + Stream_Free(s, TRUE); + return rc; +} + +static BOOL TestStream_Fill(void) +{ + BOOL rc = FALSE; + const BYTE fill[7] = "XXXXXXX"; + const BYTE data[] = "someteststreamdata"; + wStream* s = Stream_New(NULL, sizeof(data)); + if (!s) + goto out; + + Stream_Write(s, data, sizeof(data)); + if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + Stream_Fill(s, fill[0], sizeof(fill)); + if (s->pointer != s->buffer + sizeof(fill)) + goto out; + if (memcmp(Stream_Pointer(s), data+sizeof(fill), sizeof(data)-sizeof(fill)) != 0) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + if (memcmp(Stream_Pointer(s), fill, sizeof(fill)) != 0) + goto out; + + rc = TRUE; +out: + Stream_Free(s, TRUE); + return rc; +} + +static BOOL TestStream_Copy(void) +{ + BOOL rc = FALSE; + const BYTE data[] = "someteststreamdata"; + wStream* s = Stream_New(NULL, sizeof(data)); + wStream* d = Stream_New(NULL, sizeof(data)); + if (!s || !d) + goto out; + if (s->pointer != s->buffer) + goto out; + + Stream_Write(s, data, sizeof(data)); + if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0) + goto out; + if (s->pointer != s->buffer + sizeof(data)) + goto out; + Stream_SetPosition(s, 0); + if (s->pointer != s->buffer) + goto out; + + Stream_Copy(s, d, sizeof(data)); + if (s->pointer != s->buffer + sizeof(data)) + goto out; + if (d->pointer != d->buffer + sizeof(data)) + goto out; + if (Stream_GetPosition(s) != Stream_GetPosition(d)) + goto out; + + if (memcmp(Stream_Buffer(s), data, sizeof(data)) != 0) + goto out; + if (memcmp(Stream_Buffer(d), data, sizeof(data)) != 0) + goto out; + + rc = TRUE; +out: + Stream_Free(s, TRUE); + Stream_Free(d, TRUE); + return rc; +} + int TestStream(int argc, char* argv[]) { @@ -278,15 +524,24 @@ int TestStream(int argc, char* argv[]) if (!TestStream_New()) return 5; - /** - * FIXME: Add tests for - * Stream_Write_* - * Stream_Seek_* - * Stream_Rewind_* - * Stream_Zero - * Stream_Fill - * Stream_Copy - */ + + if (!TestStream_Write()) + return 6; + + if (!TestStream_Seek()) + return 7; + + if (!TestStream_Rewind()) + return 8; + + if (!TestStream_Zero()) + return 9; + + if (!TestStream_Fill()) + return 10; + + if (!TestStream_Copy()) + return 11; return 0; } From a5bb05bf44f3538e8dfabdc181b174d3e7f82efc Mon Sep 17 00:00:00 2001 From: Hendrik Woltersdorf Date: Tue, 1 Mar 2016 21:49:21 +0100 Subject: [PATCH 108/128] fix wayland-client.h not found --- client/Wayland/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt index 315be7dc2..25c69a281 100644 --- a/client/Wayland/CMakeLists.txt +++ b/client/Wayland/CMakeLists.txt @@ -19,6 +19,7 @@ set(MODULE_NAME "wlfreerdp") set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND") +include_directories(${WAYLAND_INCLUDE_DIR}) include_directories(${CMAKE_SOURCE_DIR}/uwac/include) set(${MODULE_PREFIX}_SRCS From 227ecc4bd5b16adf7c379fd1b36096b568e18cda Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 2 Mar 2016 09:16:49 +0100 Subject: [PATCH 109/128] Fixed uninitialized variable. --- winpr/libwinpr/crypto/crypto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/libwinpr/crypto/crypto.c b/winpr/libwinpr/crypto/crypto.c index 4729a769b..144222af3 100644 --- a/winpr/libwinpr/crypto/crypto.c +++ b/winpr/libwinpr/crypto/crypto.c @@ -150,7 +150,7 @@ BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags) { BYTE* pCipherText; size_t cbOut, cbFinal; - WINPR_CIPHER_CTX* enc; + WINPR_CIPHER_CTX* enc = NULL; BYTE randomKey[256]; WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock; From 65cddbc3fbd9a899669358f6e61e3d2433a933ba Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Wed, 2 Mar 2016 09:16:59 +0100 Subject: [PATCH 110/128] Removed obsolete log message. --- winpr/libwinpr/timezone/timezone.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index 79cb6f36b..abda1e699 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -1711,8 +1711,6 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) #else tz->Bias = 0; #endif - WLog_DBG(TAG, "tzname[std]: %s, tzname[dst]: %s, timezone: %ld, Daylight: %d", - tzname[0], tzname[1], timezone, daylight); dtz = winpr_detect_windows_time_zone(tz->Bias); From 9f0b14f8bd200837a91515508d77cddf2aa9faf4 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Wed, 2 Mar 2016 10:20:12 +0100 Subject: [PATCH 111/128] shadow/subsystem: fix pkgconfig file Add freerdp-shadow-subsystem to 'libs' in order to avoid undefined reference to shadow_subsystem_set_entry_builtin at runtime. Remove cyclic dependency on itself. --- server/shadow/freerdp-shadow.pc.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/shadow/freerdp-shadow.pc.in b/server/shadow/freerdp-shadow.pc.in index 49449e816..5c8c4629c 100644 --- a/server/shadow/freerdp-shadow.pc.in +++ b/server/shadow/freerdp-shadow.pc.in @@ -2,14 +2,14 @@ prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@ libdir=@CMAKE_INSTALL_FULL_LIBDIR@ includedir=${prefix}/@FREERDP_INCLUDE_DIR@ -libs=-lfreerdp-shadow +libs=-lfreerdp-shadow -lfreerdp-shadow-subsystem Name: FreeRDP shadow Description: FreeRDP: A Remote Desktop Protocol Implementation URL: http://www.freerdp.com/ Version: @FREERDP_VERSION@ Requires: -Requires.private: @WINPR_PKG_CONFIG_FILENAME@ freerdp@FREERDP_VERSION_MAJOR@ freerdp-shadow@FREERDP_VERSION_MAJOR@ +Requires.private: @WINPR_PKG_CONFIG_FILENAME@ freerdp@FREERDP_VERSION_MAJOR@ Libs: -L${libdir} ${libs} Libs.private: -ldl -lpthread Cflags: -I${includedir} From 7075353417ae32e1afc0f32e7256639c5670aa03 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Wed, 2 Mar 2016 12:37:48 -0500 Subject: [PATCH 112/128] winpr: fix regression in timezone detection ConvertToUnicode can't be used if the destination is a static buffer. StandardName and DaylightName were invalid and timezone redirection didn't work. This regression was introduced with PR #3151 --- winpr/libwinpr/timezone/timezone.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c index abda1e699..f277d4abd 100644 --- a/winpr/libwinpr/timezone/timezone.c +++ b/winpr/libwinpr/timezone/timezone.c @@ -1716,6 +1716,7 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) if (dtz!= NULL) { + int status; WLog_DBG(TAG, "tz: Bias=%d sn='%s' dln='%s'", dtz->Bias, dtz->StandardName, dtz->DaylightName); @@ -1723,10 +1724,23 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) tz->StandardBias = dtz->Bias; tz->DaylightBias = dtz->Bias; - ConvertToUnicode(CP_UTF8, 0, dtz->StandardName, sizeof(dtz->StandardName), - (WCHAR**)&tz->StandardName, sizeof(tz->StandardName)/sizeof(WCHAR)); - ConvertToUnicode(CP_UTF8, 0, dtz->DaylightName, sizeof(dtz->DaylightName), - (WCHAR**)&tz->DaylightName, sizeof(tz->DaylightName)/sizeof(WCHAR)); + ZeroMemory(tz->StandardName, sizeof(tz->StandardName)); + ZeroMemory(tz->DaylightName, sizeof(tz->DaylightName)); + status = MultiByteToWideChar(CP_UTF8, 0, dtz->StandardName, -1, tz->StandardName, + sizeof(tz->StandardName)/sizeof(WCHAR)-1); + if (status < 1) + { + WLog_ERR(TAG, "StandardName convertion failed - using default"); + goto out_error; + } + + status = MultiByteToWideChar(CP_UTF8, 0, dtz->DaylightName, -1, tz->DaylightName, + sizeof(tz->DaylightName)/sizeof(WCHAR)-1); + if (status < 1) + { + WLog_ERR(TAG, "DaylightName convertion failed - using default"); + goto out_error; + } if ((dtz->SupportsDST) && (dtz->RuleTableCount > 0)) { @@ -1751,6 +1765,7 @@ DWORD GetTimeZoneInformation(LPTIME_ZONE_INFORMATION lpTimeZoneInformation) { /* could not detect timezone, fallback to using GMT */ WLog_DBG(TAG, "tz not found, using GMT."); +out_error: memcpy(tz->StandardName, L"GMT Standard Time", sizeof(tz->StandardName)); memcpy(tz->DaylightName, L"GMT Daylight Time", sizeof(tz->DaylightName)); return 0; /* TIME_ZONE_ID_UNKNOWN */ From a20950faa0d11d060576c7ea91f867ed5fc2564c Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Thu, 7 Jan 2016 11:04:10 -0800 Subject: [PATCH 113/128] Implement FileAllocationInformation --- channels/drive/client/drive_file.c | 31 +++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 7aec1c280..4b0a3e3c3 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -7,6 +7,8 @@ * Copyright 2012 Gerald Richter * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -507,7 +509,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN { char* s = NULL; mode_t m; - UINT64 size; + INT64 size; int status; char* fullpath; struct STAT st; @@ -516,9 +518,14 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN #else struct timeval tv[2]; #endif + UINT64 CreationTime; + UINT64 LastAccessTime; UINT64 LastWriteTime; + UINT64 ChangeTime; UINT32 FileAttributes; UINT32 FileNameLength; + int fd; + LARGE_INTEGER liSize; m = 0; @@ -526,10 +533,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ - Stream_Seek_UINT64(input); /* CreationTime */ - Stream_Seek_UINT64(input); /* LastAccessTime */ + Stream_Read_UINT64(input, CreationTime); + Stream_Read_UINT64(input, LastAccessTime); Stream_Read_UINT64(input, LastWriteTime); - Stream_Seek_UINT64(input); /* ChangeTime */ + Stream_Read_UINT64(input, ChangeTime); Stream_Read_UINT32(input, FileAttributes); if (FSTAT(file->fd, &st) != 0) @@ -538,7 +545,6 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN tv[0].tv_sec = st.st_atime; tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); #ifndef WIN32 - /* TODO on win32 */ #ifdef ANDROID tv[0].tv_usec = 0; tv[1].tv_usec = 0; @@ -563,6 +569,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN if (m != st.st_mode) fchmod(file->fd, st.st_mode); } +#else /* WIN32 */ + SetFileTime(file->fd, &CreationTime, &LastAccessTime, &LastWriteTime); #endif break; @@ -570,10 +578,19 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN /* http://msdn.microsoft.com/en-us/library/cc232067.aspx */ case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ - Stream_Read_UINT64(input, size); + Stream_Read_INT64(input, size); #ifndef _WIN32 - if (ftruncate(file->fd, size) != 0) + fd = OPEN(file->fullpath, O_RDWR); + if (ftruncate(fd, size) != 0) + { + WLog_ERR(TAG, "Unable to truncate %s to %d: %s (%d)", file->fullpath, size, strerror(errno), errno); return FALSE; + } + close(fd); +#else + liSize.QuadPart = size; + SetFilePointerEx(file->fd, liSize, NULL, FILE_BEGIN); + SetEndOfFile(file->fd); #endif break; From 2e1e6a4ff0041efc36bc179be9201016d1809c9e Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Mon, 7 Sep 2015 12:16:03 +0200 Subject: [PATCH 114/128] Add hotplug support for MacOS --- channels/rdpdr/client/CMakeLists.txt | 6 + channels/rdpdr/client/rdpdr_main.c | 276 ++++++++++++++++++++++++++- channels/rdpdr/client/rdpdr_main.h | 8 + 3 files changed, 289 insertions(+), 1 deletion(-) diff --git a/channels/rdpdr/client/CMakeLists.txt b/channels/rdpdr/client/CMakeLists.txt index 488c174c2..4074eb6f4 100644 --- a/channels/rdpdr/client/CMakeLists.txt +++ b/channels/rdpdr/client/CMakeLists.txt @@ -2,6 +2,8 @@ # FreeRDP cmake build script # # Copyright 2012 Marc-Andre Moreau +# Copyright 2016 Inuvika Inc. +# Copyright 2016 David PHAM-VAN # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -32,6 +34,10 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE target_link_libraries(${MODULE_NAME} winpr freerdp) +if(APPLE AND (NOT IOS)) + find_library(CORESERVICES_LIBRARY CoreServices) + target_link_libraries(${MODULE_NAME} ${CORESERVICES_LIBRARY}) +endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 87ee6fbdb..eed6f78b8 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -46,6 +46,15 @@ #include #endif +#ifdef __MACOSX__ +#include +#include +#include +#include +#include +#include +#endif + #ifdef HAVE_UNISTD_H #include #endif @@ -103,6 +112,34 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou #ifdef _WIN32 +void first_hotplug(rdpdrPlugin *rdpdr) +{ + int i; + char drive_path[5] = { 'c', ':', '\\', '\0' }; + + DWORD unitmask = GetLogicalDrives(); + + for (i = 0; i < 26; i++) + { + if (unitmask & 0x01) + { + RDPDR_DRIVE* drive; + + drive_path[0] = 'A' + i; + drive_path[1] = ':'; + + 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->rdpcontext); + } + unitmask = unitmask >> 1; + } +} + LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { rdpdrPlugin *rdpdr; @@ -131,6 +168,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) RDPDR_DRIVE* drive; drive_path[0] = 'A' + i; + drive_path[1] = ':'; drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); ZeroMemory(drive, sizeof(RDPDR_DRIVE)); @@ -212,6 +250,7 @@ static void* drive_hotplug_thread_func(void* arg) HDEVNOTIFY hDevNotify; rdpdr = (rdpdrPlugin *)arg; + first_hotplug(rdpdr); /* init windows class */ wnd_cls.cbSize = sizeof(WNDCLASSEX); @@ -275,6 +314,239 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) return error; } +#elif __MACOSX__ + +#define MAX_USB_DEVICES 100 + +typedef struct _hotplug_dev +{ + char* path; + BOOL to_add; +} hotplug_dev; + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT handle_hotplug(rdpdrPlugin* rdpdr) +{ + struct dirent *pDirent; + DIR *pDir; + char fullpath[PATH_MAX]; + char* szdir = (char*)"/Volumes"; + struct stat buf; + hotplug_dev dev_array[MAX_USB_DEVICES]; + int count; + DEVICE_DRIVE_EXT *device_ext; + ULONG_PTR *keys; + int i, j; + int size = 0; + UINT error; + UINT32 ids[1]; + + pDir = opendir (szdir); + if (pDir == NULL) + { + printf ("Cannot open directory\n"); + return ERROR_OPEN_FAILED; + } + + while ((pDirent = readdir(pDir)) != NULL) + { + if (pDirent->d_name[0] != '.') + { + sprintf(fullpath, "%s/%s", szdir, pDirent->d_name); + lstat(fullpath, &buf); + if(S_ISDIR(buf.st_mode)) + { + dev_array[size].path = _strdup(fullpath); + if (!dev_array[size].path) + { + closedir (pDir); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + dev_array[size++].to_add = TRUE; + } + } + } + closedir (pDir); + + /* 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]); + if (!device_ext) + continue; + + if (device_ext->path == NULL) + continue; + + /* not plugable device */ + if (strstr(device_ext->path, "/Volumes/") == 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]; + if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) + { + WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!", error); + goto cleanup; + } + } + } + + /* add new devices */ + for (i = 0; i < size; i++) + { + RDPDR_DRIVE* drive; + + if (dev_array[i].to_add) + { + char* name; + + drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE)); + if (!drive) + { + WLog_ERR(TAG, "calloc failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + + drive->Type = RDPDR_DTYP_FILESYSTEM; + + drive->Path = dev_array[i].path; + dev_array[i].path = NULL; + + name = strrchr(drive->Path, '/') + 1; + drive->Name = _strdup(name); + if (!drive->Name) + { + WLog_ERR(TAG, "_strdup failed!"); + free(drive->Path); + free(drive); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext))) + { + WLog_ERR(TAG, "devman_load_device_service failed!"); + free(drive->Path); + free(drive->Name); + free(drive); + error = CHANNEL_RC_NO_MEMORY; + goto cleanup; + } + } + } + +cleanup: + for (i = 0; i < size; i++) + free (dev_array[i].path); + + return error; + } + + +static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo, + size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) +{ + rdpdrPlugin* rdpdr; + int i; + UINT error; + char **paths = (char**)eventPaths; + + rdpdr = (rdpdrPlugin*) clientCallBackInfo; + + for (i=0; irunLoop = CFRunLoopGetCurrent(); + FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode); + FSEventStreamStart(fsev); + CFRunLoopRun(); + FSEventStreamStop(fsev); + FSEventStreamRelease(fsev); + + ExitThread(CHANNEL_RC_OK); + return NULL; +} + + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) +{ + UINT error; + if (rdpdr->hotplugThread) + { + CFRunLoopStop(rdpdr->runLoop); + + if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error); + return error; + } + rdpdr->hotplugThread = NULL; + } + return CHANNEL_RC_OK; +} + #else #define MAX_USB_DEVICES 100 @@ -506,7 +778,7 @@ cleanup: for (i = 0; i < size; i++) free (dev_array[i].path); - return error ? error : rdpdr_send_device_list_announce_request(rdpdr, TRUE); + return error; } static void* drive_hotplug_thread_func(void* arg) @@ -568,6 +840,8 @@ static void* drive_hotplug_thread_func(void* arg) WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); goto out; } + else + rdpdr_send_device_list_announce_request(rdpdr, TRUE); } FD_ZERO(&rfds); diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index 7f93acbd3..6ecb945cd 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -6,6 +6,8 @@ * Copyright 2010-2012 Marc-Andre Moreau * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +38,10 @@ #include #include +#ifdef __MACOSX__ +#include +#endif + #define TAG CHANNELS_TAG("rdpdr.client") typedef struct rdpdr_plugin rdpdrPlugin; @@ -64,6 +70,8 @@ struct rdpdr_plugin HANDLE hotplugThread; #ifdef _WIN32 HWND hotplug_wnd; +#elif __MACOSX__ + CFRunLoopRef runLoop; #else HANDLE stopEvent; #endif From 2f28b6c38b8567beb3333b3e898f024e676bbc74 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 26 Feb 2016 10:19:21 -0800 Subject: [PATCH 115/128] Improve code using more winpr functions --- channels/drive/client/drive_file.c | 118 ++++++++++++++++------------- channels/drive/client/drive_file.h | 4 +- 2 files changed, 66 insertions(+), 56 deletions(-) diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index 4b0a3e3c3..f1ad8bfc6 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -61,6 +61,8 @@ #ifdef _WIN32 #pragma comment(lib, "Shlwapi.lib") #include +#else +#include #endif #include "drive_file.h" @@ -512,19 +514,19 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN INT64 size; int status; char* fullpath; - struct STAT st; -#if defined(__linux__) && !defined(ANDROID) || defined(sun) - struct timespec tv[2]; -#else - struct timeval tv[2]; -#endif - UINT64 CreationTime; - UINT64 LastAccessTime; - UINT64 LastWriteTime; - UINT64 ChangeTime; + ULARGE_INTEGER liCreationTime; + ULARGE_INTEGER liLastAccessTime; + ULARGE_INTEGER liLastWriteTime; + ULARGE_INTEGER liChangeTime; + FILETIME ftCreationTime; + FILETIME ftLastAccessTime; + FILETIME ftLastWriteTime; + FILETIME* pftCreationTime = NULL; + FILETIME* pftLastAccessTime = NULL; + FILETIME* pftLastWriteTime = NULL; UINT32 FileAttributes; UINT32 FileNameLength; - int fd; + HANDLE hFd; LARGE_INTEGER liSize; m = 0; @@ -533,45 +535,51 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN { case FileBasicInformation: /* http://msdn.microsoft.com/en-us/library/cc232094.aspx */ - Stream_Read_UINT64(input, CreationTime); - Stream_Read_UINT64(input, LastAccessTime); - Stream_Read_UINT64(input, LastWriteTime); - Stream_Read_UINT64(input, ChangeTime); + Stream_Read_UINT64(input, liCreationTime.QuadPart); + Stream_Read_UINT64(input, liLastAccessTime.QuadPart); + Stream_Read_UINT64(input, liLastWriteTime.QuadPart); + Stream_Read_UINT64(input, liChangeTime.QuadPart); Stream_Read_UINT32(input, FileAttributes); - if (FSTAT(file->fd, &st) != 0) + if (!PathFileExistsA(file->fullpath)) return FALSE; - - tv[0].tv_sec = st.st_atime; - tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime); -#ifndef WIN32 -#ifdef ANDROID - tv[0].tv_usec = 0; - tv[1].tv_usec = 0; - utimes(file->fullpath, tv); -#elif defined (__linux__) || defined (sun) - tv[0].tv_nsec = 0; - tv[1].tv_nsec = 0; - futimens(file->fd, tv); -#else - tv[0].tv_usec = 0; - tv[1].tv_usec = 0; - futimes(file->fd, tv); -#endif - - if (FileAttributes > 0) + hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFd == INVALID_HANDLE_VALUE) { - m = st.st_mode; - if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0) - m |= S_IWUSR; - else - m &= ~S_IWUSR; - if (m != st.st_mode) - fchmod(file->fd, st.st_mode); + WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath); + return FALSE; } -#else /* WIN32 */ - SetFileTime(file->fd, &CreationTime, &LastAccessTime, &LastWriteTime); -#endif + if (liCreationTime.QuadPart != 0) + { + ftCreationTime.dwHighDateTime = liCreationTime.HighPart; + ftCreationTime.dwLowDateTime = liCreationTime.LowPart; + pftCreationTime = &ftCreationTime; + } + if (liLastAccessTime.QuadPart != 0) + { + ftLastAccessTime.dwHighDateTime = liLastAccessTime.HighPart; + ftLastAccessTime.dwLowDateTime = liLastAccessTime.LowPart; + pftLastAccessTime = &ftLastAccessTime; + } + if (liLastWriteTime.QuadPart != 0) + { + ftLastWriteTime.dwHighDateTime = liLastWriteTime.HighPart; + ftLastWriteTime.dwLowDateTime = liLastWriteTime.LowPart; + pftLastWriteTime = &ftLastWriteTime; + } + if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart) + { + ftLastWriteTime.dwHighDateTime = liChangeTime.HighPart; + ftLastWriteTime.dwLowDateTime = liChangeTime.LowPart; + pftLastWriteTime = &ftLastWriteTime; + } + if (!SetFileTime(hFd, pftCreationTime, pftLastAccessTime, pftLastWriteTime)) + { + WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath); + CloseHandle(hFd); + return FALSE; + } + CloseHandle(hFd); break; case FileEndOfFileInformation: @@ -579,19 +587,21 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN case FileAllocationInformation: /* http://msdn.microsoft.com/en-us/library/cc232076.aspx */ Stream_Read_INT64(input, size); -#ifndef _WIN32 - fd = OPEN(file->fullpath, O_RDWR); - if (ftruncate(fd, size) != 0) + + hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFd == INVALID_HANDLE_VALUE) { - WLog_ERR(TAG, "Unable to truncate %s to %d: %s (%d)", file->fullpath, size, strerror(errno), errno); + WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size); return FALSE; } - close(fd); -#else liSize.QuadPart = size; - SetFilePointerEx(file->fd, liSize, NULL, FILE_BEGIN); - SetEndOfFile(file->fd); -#endif + if (SetFilePointerEx(hFd, liSize, NULL, FILE_BEGIN) == 0) + { + WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size); + CloseHandle(hFd); + return FALSE; + } + CloseHandle(hFd); break; case FileDispositionInformation: diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h index b5bd14118..d287eb4ee 100644 --- a/channels/drive/client/drive_file.h +++ b/channels/drive/client/drive_file.h @@ -7,6 +7,8 @@ * Copyright 2012 Gerald Richter * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Inuvika Inc. + * Copyright 2016 David PHAM-VAN * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -84,8 +86,6 @@ typedef UINT32 mode_t; #define FILE_TIME_SYSTEM_TO_RDP(_t) \ (((UINT64)(_t) + EPOCH_DIFF) * 10000000LL) -#define FILE_TIME_RDP_TO_SYSTEM(_t) \ - (((_t) == 0LL || (_t) == (UINT64)(-1LL)) ? 0 : (time_t)((_t) / 10000000LL - EPOCH_DIFF)) #define FILE_ATTR_SYSTEM_TO_RDP(_f, _st) ( \ (S_ISDIR(_st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : 0) | \ From 31d9599d0964f2031c31c667705a33a411071d91 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 26 Feb 2016 10:31:14 -0800 Subject: [PATCH 116/128] Move first_hotplug call to parent thread to avoid parallel access to devman dictionary --- channels/rdpdr/client/rdpdr_main.c | 32 ++++++++++++++++++------------ 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index eed6f78b8..7104b8eae 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -250,7 +250,6 @@ static void* drive_hotplug_thread_func(void* arg) HDEVNOTIFY hDevNotify; rdpdr = (rdpdrPlugin *)arg; - first_hotplug(rdpdr); /* init windows class */ wnd_cls.cbSize = sizeof(WNDCLASSEX); @@ -492,6 +491,15 @@ static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, void } } +void first_hotplug(rdpdrPlugin *rdpdr) +{ + UINT error; + if ((error = handle_hotplug(rdpdr))) + { + WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); + } +} + static void* drive_hotplug_thread_func(void* arg) { rdpdrPlugin* rdpdr; @@ -506,12 +514,6 @@ static void* drive_hotplug_thread_func(void* arg) ctx.info = arg; fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone); - if ((error = handle_hotplug(rdpdr))) - { - WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - return NULL; - } - rdpdr->runLoop = CFRunLoopGetCurrent(); FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode); FSEventStreamStart(fsev); @@ -781,6 +783,15 @@ cleanup: return error; } +void first_hotplug(rdpdrPlugin *rdpdr) +{ + UINT error; + if ((error = handle_hotplug(rdpdr))) + { + WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); + } +} + static void* drive_hotplug_thread_func(void* arg) { rdpdrPlugin* rdpdr; @@ -814,12 +825,6 @@ static void* drive_hotplug_thread_func(void* arg) tv.tv_sec = 1; tv.tv_usec = 0; - if ((error = handle_hotplug(rdpdr))) - { - WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error); - goto out; - } - while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0) { status = WaitForSingleObject(rdpdr->stopEvent, 0); @@ -917,6 +922,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) if (device->Name && (strcmp(device->Name, "*") == 0)) { + first_hotplug(rdpdr); if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL))) { From f4eb2789359c8e207c225217e42d0b4833fbdf5e Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Fri, 26 Feb 2016 10:32:54 -0800 Subject: [PATCH 117/128] Mount only removable devices and network drives in Windows; Adds consistency with Linux and Mac --- channels/rdpdr/client/rdpdr_main.c | 44 ++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 15 deletions(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 7104b8eae..c6a81f094 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -112,6 +112,14 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou #ifdef _WIN32 +BOOL check_path(char* path) +{ + UINT type = GetDriveTypeA(path); + if (!(type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE)) + return FALSE; + return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0); +} + void first_hotplug(rdpdrPlugin *rdpdr) { int i; @@ -128,13 +136,16 @@ void first_hotplug(rdpdrPlugin *rdpdr) drive_path[0] = 'A' + i; drive_path[1] = ':'; - 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->rdpcontext); + if (check_path(drive_path)) + { + 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->rdpcontext); + } } unitmask = unitmask >> 1; } @@ -170,16 +181,19 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) drive_path[0] = 'A' + i; drive_path[1] = ':'; - drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); - ZeroMemory(drive, sizeof(RDPDR_DRIVE)); + if (check_path(drive_path)) + { + drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); + ZeroMemory(drive, sizeof(RDPDR_DRIVE)); - drive->Type = RDPDR_DTYP_FILESYSTEM; + 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->rdpcontext); - rdpdr_send_device_list_announce_request(rdpdr, TRUE); + drive->Path = _strdup(drive_path); + drive_path[1] = '\0'; + drive->Name = _strdup(drive_path); + devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext); + rdpdr_send_device_list_announce_request(rdpdr, TRUE); + } } unitmask = unitmask >> 1; } From 40504c546019eb476f2b7732030485c8a056c839 Mon Sep 17 00:00:00 2001 From: David PHAM-VAN Date: Tue, 1 Mar 2016 17:10:22 -0800 Subject: [PATCH 118/128] Fix Uninitialized Variable --- channels/rdpdr/client/rdpdr_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index c6a81f094..d18cc5b1b 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -813,7 +813,7 @@ static void* drive_hotplug_thread_func(void* arg) fd_set rfds; struct timeval tv; int rv; - UINT error; + UINT error = 0; DWORD status; rdpdr = (rdpdrPlugin*) arg; From bc750e98308ee217ec00b2e3429c196b873f8b60 Mon Sep 17 00:00:00 2001 From: Jakub Adam Date: Tue, 23 Feb 2016 15:27:33 +0100 Subject: [PATCH 119/128] Fix build on older 32-bit Ubuntu releases Some older 32-bit versions of gcc fail on '#elif __x86_64__'. This applies at least to what Ubuntu 14.04 and 15.04 have as the default compiler. --- winpr/include/winpr/wtypes.h.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/winpr/include/winpr/wtypes.h.in b/winpr/include/winpr/wtypes.h.in index 1bfa553a8..93543f9af 100644 --- a/winpr/include/winpr/wtypes.h.in +++ b/winpr/include/winpr/wtypes.h.in @@ -285,7 +285,7 @@ typedef void *PVOID64, *LPVOID64; #if WINPR_HAVE_STDINT_H typedef intptr_t INT_PTR; typedef uintptr_t UINT_PTR; -#elif __x86_64__ +#elif defined (__x86_64__) typedef __int64 INT_PTR; typedef unsigned __int64 UINT_PTR; #else From 7dcba9a663854b74930ad20bc3828bd6c79126c4 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 3 Mar 2016 09:08:30 +0100 Subject: [PATCH 120/128] Removed additional '\0' from TUNNEL_AUTH message. --- libfreerdp/core/gateway/rdg.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c index 3f3bab8ec..474ed85ad 100644 --- a/libfreerdp/core/gateway/rdg.c +++ b/libfreerdp/core/gateway/rdg.c @@ -206,7 +206,7 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) if (!clientName) return FALSE; - packetSize = 12 + clientNameLen * 2 + sizeof(WCHAR); + packetSize = 12 + clientNameLen * sizeof(WCHAR); s = Stream_New(NULL, packetSize); if (!s) @@ -225,8 +225,6 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg) for (i = 0; i < clientNameLen; i++) Stream_Write_UINT16(s, clientName[i]); - Stream_Write_UINT16(s, 0); - Stream_SealLength(s); status = rdg_write_packet(rdg, s); From 767e6bbb658870067567536fc7794810c51b5383 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 3 Mar 2016 11:36:26 +0100 Subject: [PATCH 121/128] Updated freerdp plugin path to use major version. --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 13e41e9b5..a1113150f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -700,17 +700,17 @@ if (TARGET_ARCH MATCHES "sparc") endif() # Path to put FreeRDP data -set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp") +set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}") # Path to put plugins set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}") -set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp") +set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}") set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}") # Path to put extensions -set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions") +set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}/extensions") # Include directories include_directories(${CMAKE_CURRENT_BINARY_DIR}) From f5ce5e72dd40f7efed4a8021a8888459afb93138 Mon Sep 17 00:00:00 2001 From: David FORT Date: Thu, 3 Mar 2016 11:45:12 +0100 Subject: [PATCH 122/128] Fix parsing of saveSessionInfo PDU This should fix the case when no username is sent (issue #3186). --- libfreerdp/core/info.c | 51 ++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index e7b2d46ec..25fe94098 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -665,23 +665,32 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) UINT32 cbDomain; UINT32 cbUserName; + ZeroMemory(info, sizeof(*info)); + if (Stream_GetRemainingLength(s) < 576) return FALSE; Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ if (cbDomain > 52) return FALSE; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); - if (!info->domain) - return FALSE; + if (cbDomain) + { + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); + if (!info->domain) + return FALSE; + } + Stream_Seek(s, 52); /* domain (52 bytes) */ Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ if (cbUserName > 512) goto error_username; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); - if (!info->username) - goto error_username; + if (cbUserName) + { + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); + if (!info->username) + goto error_username; + } Stream_Seek(s, 512); /* userName (512 bytes) */ Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */ @@ -703,6 +712,8 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) UINT32 cbDomain; UINT32 cbUserName; + ZeroMemory(info, sizeof(*info)); + if (Stream_GetRemainingLength(s) < 576) return FALSE; @@ -716,19 +727,25 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) if (Stream_GetRemainingLength(s) < (cbDomain + cbUserName)) return FALSE; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); - if (!info->domain) - return FALSE; - Stream_Seek(s, cbDomain); /* domain */ - - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); - if (!info->username) + if (cbDomain) { - free(info->domain); - info->domain = NULL; - return FALSE; + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); + if (!info->domain) + return FALSE; + Stream_Seek(s, cbDomain); /* domain */ + } + + if (cbUserName) + { + ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); + if (!info->username) + { + free(info->domain); + info->domain = NULL; + return FALSE; + } + Stream_Seek(s, cbUserName); /* userName */ } - Stream_Seek(s, cbUserName); /* userName */ WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", info->sessionId); From ef4b29e5b3d8999538b04cc9a882bb9769e5e7a6 Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Thu, 3 Mar 2016 16:21:12 +0100 Subject: [PATCH 123/128] ConvertFromUnicode fixes and misc hardening - Added missing ConvertFromUnicode checks - If ConvertToUnicode allocates memory, guarantee the null termination similar to ConvertFromUnicode's implementation - Fixed some TestUnicodeConversion.c CTest return values - Added some CTests for ConvertFromUnicode and ConvertToUnicode - Misc code and protocol hardening fixes in the surrounding code regions that have been touched --- channels/cliprdr/client/cliprdr_format.c | 32 +- channels/cliprdr/server/cliprdr_main.c | 39 ++- channels/echo/server/echo_main.c | 21 +- channels/rdpdr/server/rdpdr_main.c | 51 ++- channels/smartcard/client/smartcard_pack.c | 14 +- client/Windows/wf_rail.c | 41 ++- client/X11/xf_rail.c | 37 ++- libfreerdp/core/gcc.c | 16 +- libfreerdp/core/info.c | 310 +++++++++++++++--- libfreerdp/core/redirection.c | 111 +++++-- libfreerdp/core/window.c | 29 +- server/shadow/Win/win_wds.c | 20 +- .../libwinpr/crt/test/TestUnicodeConversion.c | 217 +++++++++++- winpr/libwinpr/crt/unicode.c | 35 +- winpr/libwinpr/file/generic.c | 4 +- 15 files changed, 853 insertions(+), 124 deletions(-) diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index e686a7c29..a7afae579 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -102,16 +102,25 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data formats[index].formatName = NULL; + /* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing + * the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters + * or 16 Unicode characters)" + * However, both Windows RDSH and mstsc violate this specs as seen in the following + * example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.] + * These are 16 unicode charaters - *without* terminating null ! + */ + if (asciiNames) { szFormatName = (char*) Stream_Pointer(s); if (szFormatName[0]) { + /* ensure null termination */ formats[index].formatName = (char*) malloc(32 + 1); if (!formats[index].formatName) { - WLog_ERR(TAG, "calloc failed!"); + WLog_ERR(TAG, "malloc failed!"); error = CHANNEL_RC_NO_MEMORY; goto error_out; } @@ -125,8 +134,16 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data if (wszFormatName[0]) { - ConvertFromUnicode(CP_UTF8, 0, wszFormatName, - 16, &(formats[index].formatName), 0, NULL, NULL); + /* ConvertFromUnicode always returns a null-terminated + * string on success, even if the source string isn't. + */ + if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16, + &(formats[index].formatName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert short clipboard format name"); + error = ERROR_INTERNAL_ERROR; + goto error_out; + } } } @@ -185,8 +202,13 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data if (formatNameLength) { - ConvertFromUnicode(CP_UTF8, 0, wszFormatName, - -1, &(formats[index].formatName), 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1, + &(formats[index].formatName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert long clipboard format name"); + error = ERROR_INTERNAL_ERROR; + goto error_out; + } } Stream_Seek(s, (formatNameLength + 1) * 2); diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 24a34c57f..ed981706f 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -597,8 +597,12 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con free(cliprdr->temporaryDirectory); cliprdr->temporaryDirectory = NULL; - ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1, - &(cliprdr->temporaryDirectory), 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1, + &(cliprdr->temporaryDirectory), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert temporary directory name"); + return ERROR_INVALID_DATA; + } length = strlen(cliprdr->temporaryDirectory); @@ -680,12 +684,21 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS formats[index].formatName = NULL; + /* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing + * the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters + * or 16 Unicode characters)" + * However, both Windows RDSH and mstsc violate this specs as seen in the following + * example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.] + * These are 16 unicode charaters - *without* terminating null ! + */ + if (asciiNames) { szFormatName = (char*) Stream_Pointer(s); if (szFormatName[0]) { + /* ensure null termination */ formats[index].formatName = (char*) malloc(32 + 1); CopyMemory(formats[index].formatName, szFormatName, 32); formats[index].formatName[32] = '\0'; @@ -697,8 +710,16 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS if (wszFormatName[0]) { - ConvertFromUnicode(CP_UTF8, 0, wszFormatName, - 16, &(formats[index].formatName), 0, NULL, NULL); + /* ConvertFromUnicode always returns a null-terminated + * string on success, even if the source string isn't. + */ + if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16, + &(formats[index].formatName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert short clipboard format name"); + error = ERROR_INVALID_DATA; + goto out; + } } } @@ -757,8 +778,13 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS if (formatNameLength) { - ConvertFromUnicode(CP_UTF8, 0, wszFormatName, - -1, &(formats[index].formatName), 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1, + &(formats[index].formatName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert long clipboard format name"); + error = ERROR_INVALID_DATA; + goto out; + } } Stream_Seek(s, (formatNameLength + 1) * 2); @@ -775,6 +801,7 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS if (error) WLog_ERR(TAG, "ClientFormatList failed with error %lu!", error); +out: for (index = 0; index < formatList.numFormats; index++) { free(formatList.formats[index].formatName); diff --git a/channels/echo/server/echo_main.c b/channels/echo/server/echo_main.c index 58cc81261..8c7f92191 100644 --- a/channels/echo/server/echo_main.c +++ b/channels/echo/server/echo_main.c @@ -116,12 +116,15 @@ static void* echo_server_thread_func(void* arg) DWORD BytesReturned = 0; echo_server* echo = (echo_server*) arg; UINT error; - DWORD status; + DWORD status; if ((error = echo_server_open_channel(echo))) { - IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED); + UINT error2 = 0; WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error); + IFCALLRET(echo->context.OpenResult, error2, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED); + if (error2) + WLog_ERR(TAG, "echo server's OpenResult callback failed with error %lu", error2); goto out; } @@ -145,14 +148,14 @@ static void* echo_server_thread_func(void* arg) while (1) { - status = WaitForMultipleObjects(nCount, events, FALSE, 100); + status = WaitForMultipleObjects(nCount, events, FALSE, 100); - if (status == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); - break; - } + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error); + break; + } if (status == WAIT_OBJECT_0) { diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c index 074d3e4fe..b29182fa6 100644 --- a/channels/rdpdr/server/rdpdr_main.c +++ b/channels/rdpdr/server/rdpdr_main.c @@ -152,9 +152,10 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */ Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */ - if (Stream_GetRemainingLength(s) < ComputerNameLen) + + if (UnicodeFlag > 1) /* must be 0x00000000 or 0x00000001 */ { - WLog_ERR(TAG, "not enough data in stream!"); + WLog_ERR(TAG, "invalid UnicodeFlag value: 0x%08X", UnicodeFlag); return ERROR_INVALID_DATA; } @@ -164,6 +165,39 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context * not in characters, including the NULL terminator! */ + if (UnicodeFlag) + { + if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2) + { + WLog_ERR(TAG, "invalid unicode computer name length: %u", ComputerNameLen); + return ERROR_INVALID_DATA; + } + } + else + { + if (ComputerNameLen > 256 || ComputerNameLen < 1) + { + WLog_ERR(TAG, "invalid ascii computer name length: %u", ComputerNameLen); + return ERROR_INVALID_DATA; + } + } + + if (Stream_GetRemainingLength(s) < ComputerNameLen) + { + WLog_ERR(TAG, "not enough data in stream!"); + return ERROR_INVALID_DATA; + } + + /* ComputerName must be null terminated, check if it really is */ + + if (Stream_Pointer(s)[ComputerNameLen-1] || + (UnicodeFlag && Stream_Pointer(s)[ComputerNameLen-2])) + { + WLog_ERR(TAG, "computer name must be null terminated"); + return ERROR_INVALID_DATA; + } + + if (context->priv->ClientComputerName) { free(context->priv->ClientComputerName); @@ -172,12 +206,21 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context if (UnicodeFlag) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), - -1, &(context->priv->ClientComputerName), 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, + &(context->priv->ClientComputerName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert client computer name"); + return ERROR_INVALID_DATA; + } } else { context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s)); + if (!context->priv->ClientComputerName) + { + WLog_ERR(TAG, "failed to duplicate client computer name"); + return CHANNEL_RC_NO_MEMORY; + } } Stream_Seek(s, ComputerNameLen); diff --git a/channels/smartcard/client/smartcard_pack.c b/channels/smartcard/client/smartcard_pack.c index 421cc618d..766648bfe 100644 --- a/channels/smartcard/client/smartcard_pack.c +++ b/channels/smartcard/client/smartcard_pack.c @@ -707,7 +707,12 @@ void smartcard_trace_list_readers_return(SMARTCARD_DEVICE* smartcard, ListReader if (unicode) { length = ret->cBytes / 2; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->msz, (int)length, &mszA, 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->msz, (int)length, + &mszA, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "ConvertFromUnicode failed"); + return; + } } else { @@ -1767,7 +1772,12 @@ void smartcard_trace_status_return(SMARTCARD_DEVICE* smartcard, Status_Return* r if (unicode) { length = ret->cBytes / 2; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length, &mszReaderNamesA, 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length, + &mszReaderNamesA, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "ConvertFromUnicode failed"); + return; + } } else { diff --git a/client/Windows/wf_rail.c b/client/Windows/wf_rail.c index c00a465ac..9ee65ce75 100644 --- a/client/Windows/wf_rail.c +++ b/client/Windows/wf_rail.c @@ -456,14 +456,33 @@ static BOOL wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI { char* title = NULL; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, - windowState->titleInfo.length / 2, &title, 0, NULL, NULL); + if (windowState->titleInfo.length == 0) + { + if (!(title = _strdup(""))) + { + WLog_ERR(TAG, "failed to duplicate empty window title string"); + /* error handled below */ + } + } + else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, + windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert window title"); + /* error handled below */ + } railWindow->title = title; } else { - railWindow->title = _strdup("RdpRailWindow"); + if (!(railWindow->title = _strdup("RdpRailWindow"))) + WLog_ERR(TAG, "failed to duplicate default window title string"); + } + + if (!railWindow->title) + { + free(railWindow); + return FALSE; } ConvertToUnicode(CP_UTF8, 0, railWindow->title, -1, &titleW, 0); @@ -569,8 +588,20 @@ static BOOL wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI char* title = NULL; WCHAR* titleW = NULL; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, - windowState->titleInfo.length / 2, &title, 0, NULL, NULL); + if (windowState->titleInfo.length == 0) + { + if (!(title = _strdup(""))) + { + WLog_ERR(TAG, "failed to duplicate empty window title string"); + return FALSE; + } + } + else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, + windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert window title"); + return FALSE; + } free(railWindow->title); railWindow->title = title; diff --git a/client/X11/xf_rail.c b/client/X11/xf_rail.c index 22a941c53..6b49d5684 100644 --- a/client/X11/xf_rail.c +++ b/client/X11/xf_rail.c @@ -290,15 +290,29 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI { char* title = NULL; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, - windowState->titleInfo.length / 2, &title, 0, NULL, NULL); + if (windowState->titleInfo.length == 0) + { + if (!(title = _strdup(""))) + { + WLog_ERR(TAG, "failed to duplicate empty window title string"); + /* error handled below */ + } + } + else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, + windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert window title"); + /* error handled below */ + } appWindow->title = title; } else { - appWindow->title = _strdup("RdpRailWindow"); + if (!(appWindow->title = _strdup("RdpRailWindow"))) + WLog_ERR(TAG, "failed to duplicate default window title string"); } + if (!appWindow->title) { free(appWindow); @@ -365,9 +379,20 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI { char* title = NULL; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, - windowState->titleInfo.length / 2, &title, 0, NULL, NULL); - + if (windowState->titleInfo.length == 0) + { + if (!(title = _strdup(""))) + { + WLog_ERR(TAG, "failed to duplicate empty window title string"); + return FALSE; + } + } + else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string, + windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert window title"); + return FALSE; + } free(appWindow->title); appWindow->title = title; } diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c index 7078a1df8..e19e01937 100644 --- a/libfreerdp/core/gcc.c +++ b/libfreerdp/core/gcc.c @@ -590,7 +590,12 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */ /* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */ - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, + &str, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert client host name"); + return FALSE; + } Stream_Seek(s, 32); free(settings->ClientHostname); settings->ClientHostname = str; @@ -644,10 +649,17 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength) settings->EarlyCapabilityFlags = (UINT32) earlyCapabilityFlags; blockLength -= 2; + /* clientDigProductId (64 bytes): Contains a value that uniquely identifies the client */ + if (blockLength < 64) break; - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL); + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, + &str, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert the client product identifier"); + return FALSE; + } Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */ free(settings->ClientProductId); settings->ClientProductId = str; diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 25fe94098..6a918c42c 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -199,6 +199,7 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) UINT16 cbClientDir; UINT16 cbAutoReconnectLen; rdpSettings* settings = rdp->settings; + WCHAR* wstr; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -206,6 +207,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */ Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */ + /* cbClientAddress is the size in bytes of the character data in the clientAddress field. + * This size includes the length of the mandatory null terminator. + * The maximum allowed value is 80 bytes + */ + + if ((cbClientAddress % 2) || cbClientAddress < 2 || cbClientAddress > 80) + { + WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %u", cbClientAddress); + return FALSE; + } + settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE); if (Stream_GetRemainingLength(s) < cbClientAddress) @@ -217,7 +229,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) settings->ClientAddress = NULL; } - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientAddress / 2, &settings->ClientAddress, 0, NULL, NULL); + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbClientAddress / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: clientAddress must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ClientAddress, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert client address"); + return FALSE; + } Stream_Seek(s, cbClientAddress); if (Stream_GetRemainingLength(s) < 2) @@ -225,6 +247,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */ + /* cbClientDir is the size in bytes of the character data in the clientDir field. + * This size includes the length of the mandatory null terminator. + * The maximum allowed value is 512 bytes + */ + + if ((cbClientDir % 2) || cbClientDir < 2 || cbClientDir > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %u", cbClientDir); + return FALSE; + } + if (Stream_GetRemainingLength(s) < cbClientDir) return FALSE; @@ -234,7 +267,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s) settings->ClientDir = NULL; } - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientDir / 2, &settings->ClientDir, 0, NULL, NULL); + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbClientDir / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: clientDir must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &settings->ClientDir, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert client directory"); + return FALSE; + } Stream_Seek(s, cbClientDir); if (!rdp_read_client_time_zone(s, settings)) @@ -337,6 +380,7 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) UINT16 cbWorkingDir; UINT32 CompressionLevel; rdpSettings* settings = rdp->settings; + WCHAR* wstr; if (Stream_GetRemainingLength(s) < 18) return FALSE; @@ -357,6 +401,12 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) settings->CompressionLevel = CompressionLevel; } + if (!(flags & INFO_UNICODE)) + { + WLog_ERR(TAG, "Client without INFO_UNICODE flag: this is currently not supported"); + return FALSE; + } + Stream_Read_UINT16(s, cbDomain); /* cbDomain (2 bytes) */ Stream_Read_UINT16(s, cbUserName); /* cbUserName (2 bytes) */ Stream_Read_UINT16(s, cbPassword); /* cbPassword (2 bytes) */ @@ -368,7 +418,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) if (cbDomain > 0) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain / 2, &settings->Domain, 0, NULL, NULL); + /* cbDomain is the size in bytes of the character data in the Domain field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbDomain % 2) || cbDomain > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbDomain value: %u", cbDomain); + return FALSE; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbDomain / 2]) + { + WLog_ERR(TAG, "protocol error: Domain must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->Domain, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert Domain string"); + return FALSE; + } Stream_Seek(s, cbDomain); } Stream_Seek(s, 2); @@ -378,7 +447,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) if (cbUserName > 0) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName / 2, &settings->Username, 0, NULL, NULL); + /* cbUserName is the size in bytes of the character data in the UserName field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbUserName % 2) || cbUserName > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbUserName value: %u", cbUserName); + return FALSE; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbUserName / 2]) + { + WLog_ERR(TAG, "protocol error: UserName must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->Username, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert UserName string"); + return FALSE; + } Stream_Seek(s, cbUserName); } Stream_Seek(s, 2); @@ -388,7 +476,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) if (cbPassword > 0) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbPassword / 2, &settings->Password, 0, NULL, NULL); + /* cbPassword is the size in bytes of the character data in the Password field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbPassword % 2) || cbPassword > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbPassword value: %u", cbPassword); + return FALSE; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbPassword / 2]) + { + WLog_ERR(TAG, "protocol error: Password must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->Password, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert Password string"); + return FALSE; + } Stream_Seek(s, cbPassword); } Stream_Seek(s, 2); @@ -398,7 +505,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) if (cbAlternateShell > 0) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbAlternateShell / 2, &settings->AlternateShell, 0, NULL, NULL); + /* cbAlternateShell is the size in bytes of the character data in the AlternateShell field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbAlternateShell % 2) || cbAlternateShell > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbAlternateShell value: %u", cbAlternateShell); + return FALSE; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbAlternateShell / 2]) + { + WLog_ERR(TAG, "protocol error: AlternateShell must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->AlternateShell, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert AlternateShell string"); + return FALSE; + } Stream_Seek(s, cbAlternateShell); } Stream_Seek(s, 2); @@ -408,7 +534,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s) if (cbWorkingDir > 0) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbWorkingDir / 2, &settings->ShellWorkingDirectory, 0, NULL, NULL); + /* cbWorkingDir is the size in bytes of the character data in the WorkingDir field. + * This size excludes (!) the length of the mandatory null terminator. + * Maximum value including the mandatory null terminator: 512 + */ + if ((cbWorkingDir % 2) || cbWorkingDir > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbWorkingDir value: %u", cbWorkingDir); + return FALSE; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbWorkingDir / 2]) + { + WLog_ERR(TAG, "protocol error: WorkingDir must be null terminated"); + return FALSE; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ShellWorkingDirectory, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert AlternateShell string"); + return FALSE; + } Stream_Seek(s, cbWorkingDir); } Stream_Seek(s, 2); @@ -664,6 +809,7 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) { UINT32 cbDomain; UINT32 cbUserName; + WCHAR* wstr; ZeroMemory(info, sizeof(*info)); @@ -671,35 +817,63 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) return FALSE; Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */ - if (cbDomain > 52) - return FALSE; - if (cbDomain) - { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); - if (!info->domain) - return FALSE; - } + /* cbDomain is the size of the Unicode character data (including the mandatory + * null terminator) in bytes present in the fixed-length (52 bytes) Domain field + */ + if ((cbDomain % 2) || cbDomain < 2 || cbDomain > 52) + { + WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain); + goto fail; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbDomain / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: Domain must be null terminated"); + goto fail; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the Domain string"); + goto fail; + } Stream_Seek(s, 52); /* domain (52 bytes) */ + Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ - if (cbUserName > 512) - goto error_username; - if (cbUserName) + + /* cbUserName is the size of the Unicode character data (including the mandatory + * null terminator) in bytes present in the fixed-length (512 bytes) UserName field. + */ + + if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); - if (!info->username) - goto error_username; + WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName); + goto fail; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbUserName / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: UserName must be null terminated"); + goto fail; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the UserName string"); + goto fail; } Stream_Seek(s, 512); /* userName (512 bytes) */ Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */ - WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", info->sessionId); + WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X UserName: [%s] Domain: [%s]", + info->sessionId, info->username, info->domain); return TRUE; -error_username: +fail: + free(info->username); + info->username = NULL; free(info->domain); info->domain = NULL; return FALSE; @@ -711,6 +885,7 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) UINT32 Size; UINT32 cbDomain; UINT32 cbUserName; + WCHAR* wstr; ZeroMemory(info, sizeof(*info)); @@ -724,32 +899,87 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */ Stream_Seek(s, 558); /* pad (558 bytes) */ - if (Stream_GetRemainingLength(s) < (cbDomain + cbUserName)) - return FALSE; - if (cbDomain) + /* cbDomain is the size in bytes of the Unicode character data in the Domain field. + * The size of the mandatory null terminator is include in this value. + * Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume + * that the maximum value is 52 bytes, according to the fixed size of the + * Domain field in the Logon Info Version 1 (TS_LOGON_INFO) structure. + */ + + if ((cbDomain % 2) || cbDomain < 2 || cbDomain > 52) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE); - if (!info->domain) - return FALSE; - Stream_Seek(s, cbDomain); /* domain */ + WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain); + goto fail; } - if (cbUserName) + if (Stream_GetRemainingLength(s) < (size_t) cbDomain) { - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE); - if (!info->username) - { - free(info->domain); - info->domain = NULL; - return FALSE; - } - Stream_Seek(s, cbUserName); /* userName */ + WLog_ERR(TAG, "insufficient remaining stream length"); + goto fail; } - WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", info->sessionId); + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbDomain / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: Domain field must be null terminated"); + goto fail; + } + + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the Domain string"); + goto fail; + } + + Stream_Seek(s, cbDomain); /* domain */ + + + /* cbUserName is the size in bytes of the Unicode character data in the UserName field. + * The size of the mandatory null terminator is include in this value. + * Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume + * that the maximum value is 512 bytes, according to the fixed size of the + * Username field in the Logon Info Version 1 (TS_LOGON_INFO) structure. + */ + + if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName); + goto fail; + } + + if (Stream_GetRemainingLength(s) < (size_t) cbUserName) + { + WLog_ERR(TAG, "insufficient remaining stream length"); + goto fail; + } + + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbUserName / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: UserName field must be null terminated"); + goto fail; + } + + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the Domain string"); + goto fail; + } + + Stream_Seek(s, cbUserName); /* userName */ + + WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X UserName: [%s] Domain: [%s]", + info->sessionId, info->username, info->domain); return TRUE; + +fail: + free(info->username); + info->username = NULL; + free(info->domain); + info->domain = NULL; + return FALSE; } BOOL rdp_recv_logon_plain_notify(rdpRdp* rdp, wStream* s) diff --git a/libfreerdp/core/redirection.c b/libfreerdp/core/redirection.c index 6d3125749..092290215 100644 --- a/libfreerdp/core/redirection.c +++ b/libfreerdp/core/redirection.c @@ -30,7 +30,7 @@ #define TAG FREERDP_TAG("core.redirection") -void rdp_print_redirection_flags(UINT32 flags) +static void rdp_print_redirection_flags(UINT32 flags) { WLog_DBG(TAG, "redirectionFlags = {"); @@ -76,9 +76,10 @@ void rdp_print_redirection_flags(UINT32 flags) WLog_DBG(TAG, "}"); } -BOOL rdp_redirection_read_string(wStream* s, char** str) +static BOOL rdp_redirection_read_unicode_string(wStream* s, char** str, size_t maxLength) { UINT32 length; + WCHAR* wstr = NULL; if (Stream_GetRemainingLength(s) < 4) { @@ -88,13 +89,31 @@ BOOL rdp_redirection_read_string(wStream* s, char** str) Stream_Read_UINT32(s, length); - if (Stream_GetRemainingLength(s) < length) + if ((length % 2) || length < 2 || length > maxLength) { - WLog_ERR(TAG, "rdp_redirection_read_string failure: incorrect length %d", length); + WLog_ERR(TAG, "rdp_redirection_read_string failure: invalid unicode string length: %lu", length); return FALSE; } - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), length / 2, str, 0, NULL, NULL); + if (Stream_GetRemainingLength(s) < length) + { + WLog_ERR(TAG, "rdp_redirection_read_string failure: insufficient stream length (%lu bytes required)", length); + return FALSE; + } + + wstr = (WCHAR*) Stream_Pointer(s); + + if (wstr[length / 2 - 1]) + { + WLog_ERR(TAG, "rdp_redirection_read_string failure: unterminated unicode string"); + return FALSE; + } + + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, str, 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "rdp_redirection_read_string failure: string conversion failed"); + return FALSE; + } Stream_Seek(s, length); return TRUE; } @@ -173,7 +192,10 @@ int rdp_redirection_apply_settings(rdpRdp* rdp) /* Password may be a cookie without a null terminator */ free(settings->RedirectionPassword); settings->RedirectionPasswordLength = redirection->PasswordLength; - settings->RedirectionPassword = (BYTE*) malloc(settings->RedirectionPasswordLength); + /* For security reasons we'll allocate an additional zero WCHAR at the + * end of the buffer that is not included in RedirectionPasswordLength + */ + settings->RedirectionPassword = (BYTE*) calloc(1, settings->RedirectionPasswordLength + sizeof(WCHAR)); if (!settings->RedirectionPassword) return -1; CopyMemory(settings->RedirectionPassword, redirection->Password, settings->RedirectionPasswordLength); @@ -219,7 +241,7 @@ int rdp_redirection_apply_settings(rdpRdp* rdp) return 0; } -BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) +static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) { UINT16 flags; UINT16 length; @@ -238,14 +260,33 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) rdp_print_redirection_flags(redirection->flags); + /* Although MS-RDPBCGR does not mention any length constraints limits for the + * variable length null-terminated unicode strings in the RDP_SERVER_REDIRECTION_PACKET + * structure we will use the following limits in bytes including the null terminator: + * + * TargetNetAddress: 80 bytes + * UserName: 512 bytes + * Domain: 52 bytes + * Password(Cookie): 512 bytes + * TargetFQDN: 512 bytes + * TargetNetBiosName: 32 bytes + */ + if (redirection->flags & LB_TARGET_NET_ADDRESS) { - if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddress))) + if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddress), 80)) return -1; } if (redirection->flags & LB_LOAD_BALANCE_INFO) { + /* See [MSFT-SDLBTS] (a.k.a. TS_Session_Directory.doc) + * load balance info example data: + * 0000 43 6f 6f 6b 69 65 3a 20 6d 73 74 73 3d 32 31 33 Cookie: msts=213 + * 0010 34 30 32 36 34 33 32 2e 31 35 36 32 39 2e 30 30 4026432.15629.00 + * 0020 30 30 0d 0a 00.. + */ + if (Stream_GetRemainingLength(s) < 4) return -1; @@ -265,7 +306,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) if (redirection->flags & LB_USERNAME) { - if (!rdp_redirection_read_string(s, &(redirection->Username))) + if (!rdp_redirection_read_unicode_string(s, &(redirection->Username), 512)) return -1; WLog_DBG(TAG, "Username: %s", redirection->Username); @@ -273,7 +314,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) if (redirection->flags & LB_DOMAIN) { - if (!rdp_redirection_read_string(s, &(redirection->Domain))) + if (!rdp_redirection_read_unicode_string(s, &(redirection->Domain), 52)) return FALSE; WLog_DBG(TAG, "Domain: %s", redirection->Domain); @@ -281,12 +322,45 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) if (redirection->flags & LB_PASSWORD) { - /* Note: length (hopefully) includes double zero termination */ + /* Note: Password is a variable-length array of bytes containing the + * password used by the user in Unicode format, including a null-terminator + * or (!) or a cookie value that MUST be passed to the target server on + * successful connection. + * Since the format of the password cookie (probably some salted hash) is + * currently unknown we'll treat it as opaque data. All cookies seen so far + * are 120 bytes including \0\0 termination. + * Here is an observed example of a redirection password cookie: + * + * 0000 02 00 00 80 44 53 48 4c 60 ab 69 2f 07 d6 9e 2d ....DSHL`.i/...- + * 0010 f0 3a 97 3b a9 c5 ec 7e 66 bd b3 84 6c b1 ef b9 .:.;...~f...l... + * 0020 b6 82 4e cc 3a df 64 b7 7b 25 04 54 c2 58 98 f8 ..N.:.d.{%.T.X.. + * 0030 97 87 d4 93 c7 c1 e1 5b c2 85 f8 22 49 1f 81 88 .......[..."I... + * 0040 43 44 83 f6 9a 72 40 24 dc 4d 43 cb d9 92 3c 8f CD...r@$.MC...<. + * 0050 3a 37 5c 77 13 a0 72 3c 72 08 64 2a 29 fb dc eb :7\w..rPasswordLength); - redirection->Password = (BYTE*) malloc(redirection->PasswordLength); + + /* [MS-RDPBCGR] specifies 512 bytes as the upper limit for the password length + * including the null terminatior(s). This should also be enough for the unknown + * password cookie format (see previous comment). + */ + + if (Stream_GetRemainingLength(s) < redirection->PasswordLength) + return -1; + + if (redirection->PasswordLength > 512) + return -1; + + redirection->Password = (BYTE*) calloc(1, redirection->PasswordLength + sizeof(WCHAR)); if (!redirection->Password) return -1; Stream_Read(s, redirection->Password, redirection->PasswordLength); @@ -297,7 +371,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) if (redirection->flags & LB_TARGET_FQDN) { - if (!rdp_redirection_read_string(s, &(redirection->TargetFQDN))) + if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetFQDN), 512)) return -1; WLog_DBG(TAG, "TargetFQDN: %s", redirection->TargetFQDN); @@ -305,7 +379,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) if (redirection->flags & LB_TARGET_NETBIOS_NAME) { - if (!rdp_redirection_read_string(s, &(redirection->TargetNetBiosName))) + if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetBiosName), 32)) return -1; WLog_DBG(TAG, "TargetNetBiosName: %s", redirection->TargetNetBiosName); @@ -352,7 +426,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) for (i = 0; i < (int) count; i++) { - if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddresses[i]))) + if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddresses[i]), 80)) return FALSE; WLog_DBG(TAG, "TargetNetAddresses[%d]: %s", i, redirection->TargetNetAddresses[i]); @@ -371,13 +445,6 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s) return 1; } -int rdp_recv_redirection_packet(rdpRdp* rdp, wStream* s) -{ - int status = 0; - status = rdp_recv_server_redirection_pdu(rdp, s); - return status; -} - int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s) { int status = 0; diff --git a/libfreerdp/core/window.c b/libfreerdp/core/window.c index e31fe4582..e197b76e4 100644 --- a/libfreerdp/core/window.c +++ b/libfreerdp/core/window.c @@ -371,6 +371,7 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; + BOOL result = TRUE; if (Stream_GetRemainingLength(s) < 4) return FALSE; @@ -382,20 +383,20 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I if (!update_read_window_icon_order(s, orderInfo, &window->window_icon)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "WindowIcon"); - IFCALL(window->WindowIcon, context, orderInfo, &window->window_icon); + IFCALLRET(window->WindowIcon, result, context, orderInfo, &window->window_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON) { if (!update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "WindowCachedIcon"); - IFCALL(window->WindowCachedIcon, context, orderInfo, &window->window_cached_icon); + IFCALLRET(window->WindowCachedIcon, result, context, orderInfo, &window->window_cached_icon); } else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED) { update_read_window_delete_order(s, orderInfo); WLog_Print(update->log, WLOG_DEBUG, "WindowDelete"); - IFCALL(window->WindowDelete, context, orderInfo); + IFCALLRET(window->WindowDelete, result, context, orderInfo); } else { @@ -405,16 +406,16 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) { WLog_Print(update->log, WLOG_DEBUG, "WindowCreate"); - IFCALL(window->WindowCreate, context, orderInfo, &window->window_state); + IFCALLRET(window->WindowCreate, result, context, orderInfo, &window->window_state); } else { WLog_Print(update->log, WLOG_DEBUG, "WindowUpdate"); - IFCALL(window->WindowUpdate, context, orderInfo, &window->window_state); + IFCALLRET(window->WindowUpdate, result, context, orderInfo, &window->window_state); } } - return TRUE; + return result; } BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state) @@ -470,6 +471,7 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; + BOOL result = TRUE; if (Stream_GetRemainingLength(s) < 8) return FALSE; @@ -481,7 +483,7 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN { update_read_notification_icon_delete_order(s, orderInfo); WLog_Print(update->log, WLOG_DEBUG, "NotifyIconDelete"); - IFCALL(window->NotifyIconDelete, context, orderInfo); + IFCALLRET(window->NotifyIconDelete, result, context, orderInfo); } else { @@ -491,16 +493,16 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW) { WLog_Print(update->log, WLOG_DEBUG, "NotifyIconCreate"); - IFCALL(window->NotifyIconCreate, context, orderInfo, &window->notify_icon_state); + IFCALLRET(window->NotifyIconCreate, result, context, orderInfo, &window->notify_icon_state); } else { WLog_Print(update->log, WLOG_DEBUG, "NotifyIconUpdate"); - IFCALL(window->NotifyIconUpdate, context, orderInfo, &window->notify_icon_state); + IFCALLRET(window->NotifyIconUpdate, result, context, orderInfo, &window->notify_icon_state); } } - return TRUE; + return result; } BOOL update_read_desktop_actively_monitored_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, MONITORED_DESKTOP_ORDER* monitored_desktop) @@ -560,22 +562,23 @@ BOOL update_recv_desktop_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_ { rdpContext* context = update->context; rdpWindowUpdate* window = update->window; + BOOL result = TRUE; if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_NONE) { update_read_desktop_non_monitored_order(s, orderInfo); WLog_Print(update->log, WLOG_DEBUG, "NonMonitoredDesktop"); - IFCALL(window->NonMonitoredDesktop, context, orderInfo); + IFCALLRET(window->NonMonitoredDesktop, result, context, orderInfo); } else { if (!update_read_desktop_actively_monitored_order(s, orderInfo, &window->monitored_desktop)) return FALSE; WLog_Print(update->log, WLOG_DEBUG, "ActivelyMonitoredDesktop"); - IFCALL(window->MonitoredDesktop, context, orderInfo, &window->monitored_desktop); + IFCALLRET(window->MonitoredDesktop, result, context, orderInfo, &window->monitored_desktop); } - return TRUE; + return result; } BOOL update_recv_altsec_window_order(rdpUpdate* update, wStream* s) diff --git a/server/shadow/Win/win_wds.c b/server/shadow/Win/win_wds.c index 44a12d286..2bfc4231a 100644 --- a/server/shadow/Win/win_wds.c +++ b/server/shadow/Win/win_wds.c @@ -744,7 +744,7 @@ int win_shadow_wds_init(winShadowSubsystem* subsystem) return -1; } - subsystem->pInvitation->lpVtbl->get_ConnectionString(subsystem->pInvitation, &bstrConnectionString); + hr = subsystem->pInvitation->lpVtbl->get_ConnectionString(subsystem->pInvitation, &bstrConnectionString); if (FAILED(hr)) { @@ -752,10 +752,24 @@ int win_shadow_wds_init(winShadowSubsystem* subsystem) return -1; } + status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) bstrConnectionString, + ((UINT32*) bstrConnectionString)[-1], &(file->ConnectionString2), 0, NULL, NULL); + + SysFreeString(bstrConnectionString); + + if (status < 1) + { + WLog_ERR(TAG, "failed to convert connection string"); + return -1; + } + file = subsystem->pAssistanceFile = freerdp_assistance_file_new(); - ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) bstrConnectionString, - ((UINT32*) bstrConnectionString)[-1], &(file->ConnectionString2), 0, NULL, NULL); + if (!file) + { + WLog_ERR(TAG, "freerdp_assistance_file_new() failed"); + return -1; + } status = freerdp_assistance_parse_connection_string2(file); diff --git a/winpr/libwinpr/crt/test/TestUnicodeConversion.c b/winpr/libwinpr/crt/test/TestUnicodeConversion.c index 559c919be..08497bf82 100644 --- a/winpr/libwinpr/crt/test/TestUnicodeConversion.c +++ b/winpr/libwinpr/crt/test/TestUnicodeConversion.c @@ -260,7 +260,7 @@ int convert_utf16_to_utf8(BYTE* lpWideCharStr, BYTE* expected_lpMultiByteStr, in return length; } -int test_unicode_uppercasing(BYTE* lower, BYTE* upper) +BOOL test_unicode_uppercasing(BYTE* lower, BYTE* upper) { WCHAR* lowerW = NULL; int lowerLength; @@ -280,13 +280,182 @@ int test_unicode_uppercasing(BYTE* lower, BYTE* upper) printf("Uppercase String:\n"); string_hexdump((BYTE*) upperW, upperLength * 2); - return -1; + return FALSE; } free(lowerW); free(upperW); - return 0; + printf("success\n\n"); + return TRUE; +} + +BOOL test_ConvertFromUnicode_wrapper() +{ + /* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 */ + WCHAR src1[] = { 'R','I','C','H',' ','T','E','X','T',' ','F','O','R','M','A','T','@','@','@' }; + WCHAR src2[] = { 'R','I','C','H',' ','T','E','X','T',' ','F','O','R','M','A','T', 0 }; + CHAR cmp0[] = { 'R','I','C','H',' ','T','E','X','T',' ','F','O','R','M','A','T', 0 }; + CHAR* dst = NULL; + int i; + + /* Test unterminated unicode string: + * ConvertFromUnicode must always null-terminate, even if the src string isn't + */ + + printf("Input UTF16 String:\n"); + string_hexdump((BYTE*) src1, 19 * sizeof(WCHAR)); + + i = ConvertFromUnicode(CP_UTF8, 0, src1, 16, &dst, 0, NULL, NULL); + if (i != 16) + { + fprintf(stderr, "ConvertFromUnicode failure A1: unexpectedly returned %d instead of 16\n", i); + goto fail; + } + if (dst == NULL) + { + fprintf(stderr, "ConvertFromUnicode failure A2: destination ist NULL\n"); + goto fail; + } + if ((i = strlen(dst)) != 16) + { + fprintf(stderr, "ConvertFromUnicode failure A3: dst length is %d instead of 16\n", i); + goto fail; + } + if (strcmp(dst, cmp0)) + { + fprintf(stderr, "ConvertFromUnicode failure A4: data mismatch\n"); + goto fail; + } + printf("Output UTF8 String:\n"); + string_hexdump((BYTE*) dst, i + 1); + + free(dst); + dst = NULL; + + /* Test null-terminated string */ + + printf("Input UTF16 String:\n"); + string_hexdump((BYTE*) src2, (_wcslen(src2) + 1 ) * sizeof(WCHAR)); + + i = ConvertFromUnicode(CP_UTF8, 0, src2, -1, &dst, 0, NULL, NULL); + if (i != 17) + { + fprintf(stderr, "ConvertFromUnicode failure B1: unexpectedly returned %d instead of 17\n", i); + goto fail; + } + if (dst == NULL) + { + fprintf(stderr, "ConvertFromUnicode failure B2: destination ist NULL\n"); + goto fail; + } + if ((i = strlen(dst)) != 16) + { + fprintf(stderr, "ConvertFromUnicode failure B3: dst length is %d instead of 16\n", i); + goto fail; + } + if (strcmp(dst, cmp0)) + { + fprintf(stderr, "ConvertFromUnicode failure B: data mismatch\n"); + goto fail; + } + printf("Output UTF8 String:\n"); + string_hexdump((BYTE*) dst, i + 1); + + free(dst); + dst = NULL; + + printf("success\n\n"); + + return TRUE; + +fail: + free(dst); + return FALSE; +} + +BOOL test_ConvertToUnicode_wrapper() +{ + /* 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 */ + CHAR src1[] = { 'R','I','C','H',' ','T','E','X','T',' ','F','O','R','M','A','T','@','@','@' }; + CHAR src2[] = { 'R','I','C','H',' ','T','E','X','T',' ','F','O','R','M','A','T', 0 }; + WCHAR cmp0[] = { 'R','I','C','H',' ','T','E','X','T',' ','F','O','R','M','A','T', 0 }; + WCHAR* dst = NULL; + int i; + + /* Test unterminated unicode string: + * ConvertToUnicode must always null-terminate, even if the src string isn't + */ + + printf("Input UTF8 String:\n"); + string_hexdump((BYTE*) src1, 19); + + i = ConvertToUnicode(CP_UTF8, 0, src1, 16, &dst, 0); + if (i != 16) + { + fprintf(stderr, "ConvertToUnicode failure A1: unexpectedly returned %d instead of 16\n", i); + goto fail; + } + if (dst == NULL) + { + fprintf(stderr, "ConvertToUnicode failure A2: destination ist NULL\n"); + goto fail; + } + if ((i = _wcslen(dst)) != 16) + { + fprintf(stderr, "ConvertToUnicode failure A3: dst length is %d instead of 16\n", i); + goto fail; + } + if (_wcscmp(dst, cmp0)) + { + fprintf(stderr, "ConvertToUnicode failure A4: data mismatch\n"); + goto fail; + } + printf("Output UTF16 String:\n"); + string_hexdump((BYTE*) dst, (i + 1) * sizeof(WCHAR)); + + free(dst); + dst = NULL; + + /* Test null-terminated string */ + + printf("Input UTF8 String:\n"); + string_hexdump((BYTE*) src2, strlen(src2) + 1); + + i = ConvertToUnicode(CP_UTF8, 0, src2, -1, &dst, 0); + if (i != 17) + { + fprintf(stderr, "ConvertToUnicode failure B1: unexpectedly returned %d instead of 17\n", i); + goto fail; + } + if (dst == NULL) + { + fprintf(stderr, "ConvertToUnicode failure B2: destination ist NULL\n"); + goto fail; + } + if ((i = _wcslen(dst)) != 16) + { + fprintf(stderr, "ConvertToUnicode failure B3: dst length is %d instead of 16\n", i); + goto fail; + } + if (_wcscmp(dst, cmp0)) + { + fprintf(stderr, "ConvertToUnicode failure B: data mismatch\n"); + goto fail; + } + printf("Output UTF16 String:\n"); + string_hexdump((BYTE*) dst, (i + 1) * 2); + + free(dst); + dst = NULL; + + printf("success\n\n"); + + return TRUE; + +fail: + free(dst); + return FALSE; } int TestUnicodeConversion(int argc, char* argv[]) @@ -375,7 +544,47 @@ int TestUnicodeConversion(int argc, char* argv[]) printf("Uppercasing\n"); - test_unicode_uppercasing(ru_Administrator_lower, ru_Administrator_upper); + if (!test_unicode_uppercasing(ru_Administrator_lower, ru_Administrator_upper)) + return -1; + /* ConvertFromUnicode */ + + printf("ConvertFromUnicode\n"); + + if (!test_ConvertFromUnicode_wrapper()) + return -1; + + /* ConvertToUnicode */ + + printf("ConvertToUnicode\n"); + + if (!test_ConvertToUnicode_wrapper()) + return -1; +/* + + printf("----------------------------------------------------------\n\n"); + + if (0) + { + BYTE src[] = { 'R',0,'I',0,'C',0,'H',0,' ',0, 'T',0,'E',0,'X',0,'T',0,' ',0,'F',0,'O',0,'R',0,'M',0,'A',0,'T',0,'@',0,'@',0 }; + //BYTE src[] = { 'R',0,'I',0,'C',0,'H',0,' ',0, 0,0, 'T',0,'E',0,'X',0,'T',0,' ',0,'F',0,'O',0,'R',0,'M',0,'A',0,'T',0,'@',0,'@',0 }; + //BYTE src[] = { 0,0,'R',0,'I',0,'C',0,'H',0,' ',0, 'T',0,'E',0,'X',0,'T',0,' ',0,'F',0,'O',0,'R',0,'M',0,'A',0,'T',0,'@',0,'@',0 }; + char* dst = NULL; + int num; + num = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) src, 16, &dst, 0, NULL, NULL); + printf("ConvertFromUnicode returned %d dst=[%s]\n", num, dst); + string_hexdump((BYTE*)dst, num+1); + } + if (1) + { + char src[] = "RICH TEXT FORMAT@@@@@@"; + WCHAR *dst = NULL; + int num; + num = ConvertToUnicode(CP_UTF8, 0, src, 16, &dst, 0); + printf("ConvertToUnicode returned %d dst=%p\n", num, dst); + string_hexdump((BYTE*)dst, num * 2 + 2); + + } +*/ return 0; } diff --git a/winpr/libwinpr/crt/unicode.c b/winpr/libwinpr/crt/unicode.c index fc5134f55..0816fe03a 100644 --- a/winpr/libwinpr/crt/unicode.c +++ b/winpr/libwinpr/crt/unicode.c @@ -276,6 +276,19 @@ int WideCharToMultiByte(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int #endif +/** + * ConvertToUnicode is a convenience wrapper for MultiByteToWideChar: + * + * If the lpWideCharStr prarameter for the converted string points to NULL + * or if the cchWideChar parameter is set to 0 this function will automatically + * allocate the required memory which is guaranteed to be null-terminated + * after the conversion, even if the source c string isn't. + * + * If the cbMultiByte parameter is set to -1 the passed lpMultiByteStr must + * be null-terminated and the required length for the converted string will be + * calculated accordingly. + */ + int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, int cbMultiByte, LPWSTR* lpWideCharStr, int cchWideChar) { @@ -305,7 +318,7 @@ int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, if (allocate) { - *lpWideCharStr = (LPWSTR) calloc(cchWideChar, sizeof(WCHAR)); + *lpWideCharStr = (LPWSTR) calloc(cchWideChar + 1, sizeof(WCHAR)); if (!(*lpWideCharStr)) { @@ -317,11 +330,31 @@ int ConvertToUnicode(UINT CodePage, DWORD dwFlags, LPCSTR lpMultiByteStr, status = MultiByteToWideChar(CodePage, dwFlags, lpMultiByteStr, cbMultiByte, *lpWideCharStr, cchWideChar); if (status != cchWideChar) + { + if (allocate) + { + free(*lpWideCharStr); + *lpWideCharStr = NULL; + } status = 0; + } return status; } +/** + * ConvertFromUnicode is a convenience wrapper for WideCharToMultiByte: + * + * If the lpMultiByteStr parameter for the converted string points to NULL + * or if the cbMultiByte parameter is set to 0 this function will automatically + * allocate the required memory which is guaranteed to be null-terminated + * after the conversion, even if the source unicode string isn't. + * + * If the cchWideChar parameter is set to -1 the passed lpWideCharStr must + * be null-terminated and the required length for the converted string will be + * calculated accordingly. + */ + int ConvertFromUnicode(UINT CodePage, DWORD dwFlags, LPCWSTR lpWideCharStr, int cchWideChar, LPSTR* lpMultiByteStr, int cbMultiByte, LPCSTR lpDefaultChar, LPBOOL lpUsedDefaultChar) { diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c index 367d28292..71d4756a2 100644 --- a/winpr/libwinpr/file/generic.c +++ b/winpr/libwinpr/file/generic.c @@ -274,7 +274,7 @@ HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSTR lpFileNameA = NULL; HANDLE hdl; - if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL)) + if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL) < 1) return NULL; hdl= CreateFileA(lpFileNameA, dwDesiredAccess, dwShareMode, lpSecurityAttributes, @@ -296,7 +296,7 @@ BOOL DeleteFileW(LPCWSTR lpFileName) LPSTR lpFileNameA = NULL; BOOL rc = FALSE; - if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL)) + if (ConvertFromUnicode(CP_UTF8, 0, lpFileName, -1, &lpFileNameA, 0, NULL, NULL) < 1) return FALSE; rc = DeleteFileA(lpFileNameA); free (lpFileNameA); From fb88ad0ee6d0813503b2578adc68b914adf0febb Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Thu, 3 Mar 2016 17:11:26 +0100 Subject: [PATCH 124/128] Fixed symbol export for sound plugins. --- channels/audin/client/alsa/audin_alsa.c | 2 ++ channels/audin/client/mac/audin_mac.c | 2 ++ channels/audin/client/opensles/audin_opensl_es.c | 3 +++ channels/audin/client/oss/audin_oss.c | 2 ++ channels/audin/client/pulse/audin_pulse.c | 2 ++ channels/audin/client/winmm/audin_winmm.c | 2 ++ channels/rdpsnd/client/alsa/rdpsnd_alsa.c | 2 ++ channels/rdpsnd/client/ios/rdpsnd_ios.c | 2 ++ channels/rdpsnd/client/mac/rdpsnd_mac.c | 2 ++ channels/rdpsnd/client/opensles/rdpsnd_opensles.c | 3 +++ channels/rdpsnd/client/oss/rdpsnd_oss.c | 2 ++ channels/rdpsnd/client/pulse/rdpsnd_pulse.c | 2 ++ channels/rdpsnd/client/winmm/rdpsnd_winmm.c | 2 ++ channels/tsmf/client/alsa/tsmf_alsa.c | 2 ++ channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c | 2 ++ channels/tsmf/client/gstreamer/tsmf_gstreamer.c | 2 ++ channels/tsmf/client/oss/tsmf_oss.c | 2 ++ channels/tsmf/client/pulse/tsmf_pulse.c | 2 ++ channels/urbdrc/client/libusb/libusb_udevman.c | 2 ++ 19 files changed, 40 insertions(+) diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index a3a7b3a02..e49a1cc97 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -522,6 +522,8 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** diff --git a/channels/audin/client/mac/audin_mac.c b/channels/audin/client/mac/audin_mac.c index 07b789477..d7d8db879 100644 --- a/channels/audin/client/mac/audin_mac.c +++ b/channels/audin/client/mac/audin_mac.c @@ -402,6 +402,8 @@ static UINT audin_mac_parse_addin_args(AudinMacDevice *device, ADDIN_ARGV *args) #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index a9123c537..cd0d3999d 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -476,6 +476,9 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry \ opensles_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry \ + FREERDP_API freerdp_audin_client_subsystem_entry #endif /** diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c index e79937a37..753298bb2 100644 --- a/channels/audin/client/oss/audin_oss.c +++ b/channels/audin/client/oss/audin_oss.c @@ -485,6 +485,8 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args) #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index 829e50503..ad2f480fc 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -525,6 +525,8 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c index 5f7c6d9b8..e59a84ed6 100644 --- a/channels/audin/client/winmm/audin_winmm.c +++ b/channels/audin/client/winmm/audin_winmm.c @@ -393,6 +393,8 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a #ifdef STATIC_CHANNELS #define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry +#else +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c index 36f821440..ea4230d28 100644 --- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c +++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c @@ -649,6 +649,8 @@ static UINT rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/ios/rdpsnd_ios.c b/channels/rdpsnd/client/ios/rdpsnd_ios.c index f307b2318..148c846a8 100644 --- a/channels/rdpsnd/client/ios/rdpsnd_ios.c +++ b/channels/rdpsnd/client/ios/rdpsnd_ios.c @@ -281,6 +281,8 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device) #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/mac/rdpsnd_mac.c b/channels/rdpsnd/client/mac/rdpsnd_mac.c index 5867480bd..a2162a273 100644 --- a/channels/rdpsnd/client/mac/rdpsnd_mac.c +++ b/channels/rdpsnd/client/mac/rdpsnd_mac.c @@ -345,6 +345,8 @@ static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave) #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry mac_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c index c42f1b207..8c8b34e0d 100644 --- a/channels/rdpsnd/client/opensles/rdpsnd_opensles.c +++ b/channels/rdpsnd/client/opensles/rdpsnd_opensles.c @@ -407,6 +407,9 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device, #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry \ opensles_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry \ + FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c index df01ec008..2a6d3651b 100644 --- a/channels/rdpsnd/client/oss/rdpsnd_oss.c +++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c @@ -477,6 +477,8 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c index 13899ec00..5181d0d07 100644 --- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c +++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c @@ -636,6 +636,8 @@ static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c index 5e143635a..7eb1a5f88 100644 --- a/channels/rdpsnd/client/winmm/rdpsnd_winmm.c +++ b/channels/rdpsnd/client/winmm/rdpsnd_winmm.c @@ -346,6 +346,8 @@ static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV #ifdef STATIC_CHANNELS #define freerdp_rdpsnd_client_subsystem_entry winmm_freerdp_rdpsnd_client_subsystem_entry +#else +#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry #endif /** diff --git a/channels/tsmf/client/alsa/tsmf_alsa.c b/channels/tsmf/client/alsa/tsmf_alsa.c index 91af225a8..078c7d8f1 100644 --- a/channels/tsmf/client/alsa/tsmf_alsa.c +++ b/channels/tsmf/client/alsa/tsmf_alsa.c @@ -233,6 +233,8 @@ static void tsmf_alsa_free(ITSMFAudioDevice *audio) #ifdef STATIC_CHANNELS #define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry +#else +#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry #endif ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) diff --git a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c index e1b9f83ef..4e5beff8f 100644 --- a/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c +++ b/channels/tsmf/client/ffmpeg/tsmf_ffmpeg.c @@ -543,6 +543,8 @@ static BOOL initialized = FALSE; #ifdef STATIC_CHANNELS #define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry +#else +#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry #endif ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) diff --git a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c index 0e35f73fa..466dd7d24 100644 --- a/channels/tsmf/client/gstreamer/tsmf_gstreamer.c +++ b/channels/tsmf/client/gstreamer/tsmf_gstreamer.c @@ -1012,6 +1012,8 @@ BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, void (*cb)(void *), void *stream #ifdef STATIC_CHANNELS #define freerdp_tsmf_client_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry +#else +#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry #endif ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void) diff --git a/channels/tsmf/client/oss/tsmf_oss.c b/channels/tsmf/client/oss/tsmf_oss.c index fe9785128..da792bea9 100644 --- a/channels/tsmf/client/oss/tsmf_oss.c +++ b/channels/tsmf/client/oss/tsmf_oss.c @@ -238,6 +238,8 @@ static void tsmf_oss_free(ITSMFAudioDevice* audio) #ifdef STATIC_CHANNELS #define freerdp_tsmf_client_audio_subsystem_entry oss_freerdp_tsmf_client_audio_subsystem_entry +#else +#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry #endif ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void) diff --git a/channels/tsmf/client/pulse/tsmf_pulse.c b/channels/tsmf/client/pulse/tsmf_pulse.c index c0d6caaf3..5a8c90d8c 100644 --- a/channels/tsmf/client/pulse/tsmf_pulse.c +++ b/channels/tsmf/client/pulse/tsmf_pulse.c @@ -360,6 +360,8 @@ static void tsmf_pulse_free(ITSMFAudioDevice *audio) #ifdef STATIC_CHANNELS #define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry +#else +#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry #endif ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void) diff --git a/channels/urbdrc/client/libusb/libusb_udevman.c b/channels/urbdrc/client/libusb/libusb_udevman.c index 7dfa505f2..b8af3a4c7 100644 --- a/channels/urbdrc/client/libusb/libusb_udevman.c +++ b/channels/urbdrc/client/libusb/libusb_udevman.c @@ -579,6 +579,8 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args) #ifdef STATIC_CHANNELS #define freerdp_urbdrc_client_subsystem_entry libusb_freerdp_urbdrc_client_subsystem_entry +#else +#define freerdp_urbdrc_client_subsystem_entry FREERDP_API freerdp_urbdrc_client_subsystem_entry #endif int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints) From de4adeff0e4c72335e4fa11813182c53ac90d642 Mon Sep 17 00:00:00 2001 From: Norbert Federa Date: Fri, 4 Mar 2016 00:45:26 +0100 Subject: [PATCH 125/128] fix logon info processing since there have been reports that certain windows versions send zero values in the cbDomain field of the Logon Info Version 2 (TS_LOGON_INFO_VERSION_2) struct we allow zero values for cbUserName and cbDomain in rdp_recv_logon_info_v1 and rdp_recv_logon_info_v2. --- libfreerdp/core/info.c | 156 ++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c index 6a918c42c..57d1894c9 100644 --- a/libfreerdp/core/info.c +++ b/libfreerdp/core/info.c @@ -821,21 +821,24 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) /* cbDomain is the size of the Unicode character data (including the mandatory * null terminator) in bytes present in the fixed-length (52 bytes) Domain field */ - if ((cbDomain % 2) || cbDomain < 2 || cbDomain > 52) + if (cbDomain) { - WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain); - goto fail; - } - wstr = (WCHAR*) Stream_Pointer(s); - if (wstr[cbDomain / 2 - 1]) - { - WLog_ERR(TAG, "protocol error: Domain must be null terminated"); - goto fail; - } - if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1) - { - WLog_ERR(TAG, "failed to convert the Domain string"); - goto fail; + if ((cbDomain % 2) || cbDomain > 52) + { + WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain); + goto fail; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbDomain / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: Domain must be null terminated"); + goto fail; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the Domain string"); + goto fail; + } } Stream_Seek(s, 52); /* domain (52 bytes) */ @@ -845,22 +848,24 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info) /* cbUserName is the size of the Unicode character data (including the mandatory * null terminator) in bytes present in the fixed-length (512 bytes) UserName field. */ - - if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512) + if (cbUserName) { - WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName); - goto fail; - } - wstr = (WCHAR*) Stream_Pointer(s); - if (wstr[cbUserName / 2 - 1]) - { - WLog_ERR(TAG, "protocol error: UserName must be null terminated"); - goto fail; - } - if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1) - { - WLog_ERR(TAG, "failed to convert the UserName string"); - goto fail; + if ((cbUserName % 2) || cbUserName > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName); + goto fail; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbUserName / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: UserName must be null terminated"); + goto fail; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the UserName string"); + goto fail; + } } Stream_Seek(s, 512); /* userName (512 bytes) */ @@ -906,67 +911,62 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info) * that the maximum value is 52 bytes, according to the fixed size of the * Domain field in the Logon Info Version 1 (TS_LOGON_INFO) structure. */ - - if ((cbDomain % 2) || cbDomain < 2 || cbDomain > 52) + if (cbDomain) { - WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain); - goto fail; + if ((cbDomain % 2) || cbDomain > 52) + { + WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain); + goto fail; + } + if (Stream_GetRemainingLength(s) < (size_t) cbDomain) + { + WLog_ERR(TAG, "insufficient remaining stream length"); + goto fail; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbDomain / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: Domain field must be null terminated"); + goto fail; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the Domain string"); + goto fail; + } } - - if (Stream_GetRemainingLength(s) < (size_t) cbDomain) - { - WLog_ERR(TAG, "insufficient remaining stream length"); - goto fail; - } - - wstr = (WCHAR*) Stream_Pointer(s); - if (wstr[cbDomain / 2 - 1]) - { - WLog_ERR(TAG, "protocol error: Domain field must be null terminated"); - goto fail; - } - - if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1) - { - WLog_ERR(TAG, "failed to convert the Domain string"); - goto fail; - } - Stream_Seek(s, cbDomain); /* domain */ - /* cbUserName is the size in bytes of the Unicode character data in the UserName field. * The size of the mandatory null terminator is include in this value. * Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume * that the maximum value is 512 bytes, according to the fixed size of the * Username field in the Logon Info Version 1 (TS_LOGON_INFO) structure. */ - - if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512) + if (cbUserName) { - WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName); - goto fail; + if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512) + { + WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName); + goto fail; + } + if (Stream_GetRemainingLength(s) < (size_t) cbUserName) + { + WLog_ERR(TAG, "insufficient remaining stream length"); + goto fail; + } + wstr = (WCHAR*) Stream_Pointer(s); + if (wstr[cbUserName / 2 - 1]) + { + WLog_ERR(TAG, "protocol error: UserName field must be null terminated"); + goto fail; + } + if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1) + { + WLog_ERR(TAG, "failed to convert the Domain string"); + goto fail; + } } - - if (Stream_GetRemainingLength(s) < (size_t) cbUserName) - { - WLog_ERR(TAG, "insufficient remaining stream length"); - goto fail; - } - - wstr = (WCHAR*) Stream_Pointer(s); - if (wstr[cbUserName / 2 - 1]) - { - WLog_ERR(TAG, "protocol error: UserName field must be null terminated"); - goto fail; - } - - if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1) - { - WLog_ERR(TAG, "failed to convert the Domain string"); - goto fail; - } - Stream_Seek(s, cbUserName); /* userName */ WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X UserName: [%s] Domain: [%s]", From 701f54e07d1d730105658e7410eafc2464528411 Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 4 Mar 2016 13:22:58 +0000 Subject: [PATCH 126/128] winpr: Bump API version to 2.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In commit 12bd0ec8 ("winpr: BUMP the API version to 1.2") it was stated that the intention was to allow multiple winpr versions to be installed in parallel. However, it's not sufficient to change just the *minor* version of the library. The soname is still 'libwinpr.so.1', and thus we still can't coexist with earlier versions — in particular, we can't install FreeRDP2 in parallel with existing distribution packages of earlier versions. Bump the soname so it does actually work --- winpr/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt index 2e3b673f6..ae5280e2c 100644 --- a/winpr/CMakeLists.txt +++ b/winpr/CMakeLists.txt @@ -48,8 +48,8 @@ include(GNUInstallDirsWrapper) include(CMakePackageConfigHelpers) # Soname versioning -set(WINPR_VERSION_MAJOR "1") -set(WINPR_VERSION_MINOR "2") +set(WINPR_VERSION_MAJOR "2") +set(WINPR_VERSION_MINOR "0") set(WINPR_VERSION_REVISION "0") set(WINPR_VERSION "${WINPR_VERSION_MAJOR}.${WINPR_VERSION_MINOR}.${WINPR_VERSION_REVISION}") set(WINPR_VERSION_FULL "${WINPR_VERSION}") From 34b12362cb4106a98a332f95972da0e8f82e6ab0 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Fri, 4 Mar 2016 09:25:04 +0100 Subject: [PATCH 127/128] Fixed FreeBSD support for filetime settings. --- winpr/libwinpr/file/file.c | 39 ++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c index 606121f78..4af0cb62e 100644 --- a/winpr/libwinpr/file/file.c +++ b/winpr/libwinpr/file/file.c @@ -352,10 +352,11 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime) { int rc; -#if defined(__APPLE__) || defined(ANDROID) +#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) struct stat buf; #endif -#ifdef ANDROID +/* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */ +#if defined(ANDROID) || defined(__FreeBSD__) struct timeval timevals[2]; #else struct timespec times[2]; /* last access, last modification */ @@ -366,23 +367,30 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, if (!hFile) return FALSE; -#if defined(__APPLE__) || defined(ANDROID) +#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) rc = fstat(fileno(pFile->fp), &buf); if (rc < 0) return FALSE; #endif if (!lpLastAccessTime) { -#ifdef __APPLE__ +#if defined(__APPLE__) #if !defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE) times[0] = buf.st_atimespec; #else times[0].tv_sec = buf.st_atime; times[0].tv_nsec = buf.st_atimensec; #endif -#elif ANDROID - timevals[0].tv_sec = buf.st_mtime; - timevals[0].tv_usec = buf.st_mtimensec / 1000UL; +#elif defined(__FreeBSD__) + timevals[0].tv_sec = buf.st_atime; +#ifdef _POSIX_SOURCE + TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim); +#else + TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atimespec); +#endif +#elif defined(ANDROID) + timevals[0].tv_sec = buf.st_atime; + timevals[0].tv_usec = buf.st_atimensec / 1000UL; #else times[0].tv_sec = UTIME_OMIT; times[0].tv_nsec = UTIME_OMIT; @@ -395,7 +403,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, tmp -= EPOCH_DIFF; tmp /= 10ULL; -#ifdef ANDROID +#if defined(ANDROID) || defined(__FreeBSD__) tmp /= 10000ULL; timevals[0].tv_sec = tmp / 10000ULL; @@ -414,7 +422,14 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, times[1].tv_sec = buf.st_mtime; times[1].tv_nsec = buf.st_mtimensec; #endif -#elif ANDROID +#elif defined(__FreeBSD__) + timevals[1].tv_sec = buf.st_mtime; +#ifdef _POSIX_SOURCE + TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim); +#else + TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtimespec); +#endif +#elif defined(ANDROID) timevals[1].tv_sec = buf.st_mtime; timevals[1].tv_usec = buf.st_mtimensec / 1000UL; #else @@ -429,7 +444,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, tmp -= EPOCH_DIFF; tmp /= 10ULL; -#ifdef ANDROID +#if defined(ANDROID) || defined(__FreeBSD__) tmp /= 10000ULL; timevals[1].tv_sec = tmp / 10000ULL; @@ -443,7 +458,7 @@ static BOOL FileSetFileTime(HANDLE hFile, const FILETIME *lpCreationTime, // TODO: Creation time can not be handled! #ifdef __APPLE__ rc = futimes(fileno(pFile->fp), times); -#elif ANDROID +#elif defined(ANDROID) || defined(__FreeBSD__) rc = utimes(pFile->lpFileName, timevals); #else rc = futimens(fileno(pFile->fp), times); @@ -617,7 +632,7 @@ BOOL IsFileDevice(LPCTSTR lpDeviceName) return TRUE; } -HANDLE_CREATOR _FileHandleCreator = +HANDLE_CREATOR _FileHandleCreator = { IsFileDevice, FileCreateFileA From 2208a84cd49169cddb4377a3b49bf829d13a4504 Mon Sep 17 00:00:00 2001 From: Armin Novak Date: Mon, 7 Mar 2016 11:51:13 +0100 Subject: [PATCH 128/128] Moved assistance to winpr crypto. --- libfreerdp/common/CMakeLists.txt | 3 +- libfreerdp/common/assistance.c | 123 +++++++++++++------------------ winpr/include/winpr/crypto.h | 2 + 3 files changed, 56 insertions(+), 72 deletions(-) diff --git a/libfreerdp/common/CMakeLists.txt b/libfreerdp/common/CMakeLists.txt index 05cadf43c..1683f449d 100644 --- a/libfreerdp/common/CMakeLists.txt +++ b/libfreerdp/common/CMakeLists.txt @@ -25,10 +25,9 @@ set(${MODULE_PREFIX}_SRCS freerdp_module_add(${${MODULE_PREFIX}_SRCS}) -freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR}) freerdp_include_directory_add(${ZLIB_INCLUDE_DIRS}) -freerdp_library_add(${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES}) +freerdp_library_add(${ZLIB_LIBRARIES}) if(BUILD_TESTING) add_subdirectory(test) diff --git a/libfreerdp/common/assistance.c b/libfreerdp/common/assistance.c index 63970de35..9f231be2d 100644 --- a/libfreerdp/common/assistance.c +++ b/libfreerdp/common/assistance.c @@ -26,11 +26,6 @@ #include #include -#include -#include -#include -#include - #include #include #include @@ -77,11 +72,12 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* key, int keyLength) { + int rc = -1; int i; BYTE* buffer; BYTE pad1[64]; BYTE pad2[64]; - SHA_CTX hashCtx; + WINPR_SHA1_CTX hashCtx; memset(pad1, 0x36, 64); memset(pad2, 0x5C, 64); @@ -95,21 +91,29 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k buffer = (BYTE*) calloc(1, hashLength * 2); if (!buffer) - return -1; + goto fail; - SHA1_Init(&hashCtx); - SHA1_Update(&hashCtx, pad1, 64); - SHA1_Final((void*) buffer, &hashCtx); + if (!winpr_SHA1_Init(&hashCtx)) + goto fail; + if (!winpr_SHA1_Update(&hashCtx, pad1, 64)) + goto fail; + if (!winpr_SHA1_Final(&hashCtx, buffer, hashLength)) + goto fail; - SHA1_Init(&hashCtx); - SHA1_Update(&hashCtx, pad2, 64); - SHA1_Final((void*) &buffer[hashLength], &hashCtx); + if (!winpr_SHA1_Init(&hashCtx)) + goto fail; + if (!winpr_SHA1_Update(&hashCtx, pad2, 64)) + goto fail; + if (!winpr_SHA1_Final(&hashCtx, &buffer[hashLength], hashLength)) + goto fail; CopyMemory(key, buffer, keyLength); + rc = 1; +fail: free(buffer); - return 1; + return rc; } int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list) @@ -543,15 +547,16 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags) BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize) { + BOOL rc; int status; WINPR_MD5_CTX md5Ctx; int cbPasswordW; int cbPassStubW; int EncryptedSize; BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH]; - EVP_CIPHER_CTX rc4Ctx; + WINPR_CIPHER_CTX* rc4Ctx; BYTE* pbIn, *pbOut; - int cbOut, cbIn, cbFinal; + size_t cbOut, cbIn, cbFinal; WCHAR* PasswordW = NULL; WCHAR* PassStubW = NULL; @@ -617,21 +622,9 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas free(PasswordW); free(PassStubW); - EVP_CIPHER_CTX_init(&rc4Ctx); - - status = EVP_EncryptInit_ex(&rc4Ctx, EVP_rc4(), NULL, NULL, NULL); - - if (!status) - { - WLog_ERR(TAG, "EVP_CipherInit_ex failure"); - free (pbOut); - free (pbIn); - return NULL; - } - - status = EVP_EncryptInit_ex(&rc4Ctx, NULL, NULL, PasswordHash, NULL); - - if (!status) + rc4Ctx = winpr_Cipher_New(WINPR_CIPHER_ARC4_128, WINPR_ENCRYPT, + PasswordHash, NULL); + if (!rc4Ctx) { WLog_ERR(TAG, "EVP_CipherInit_ex failure"); free (pbOut); @@ -642,26 +635,26 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas cbOut = cbFinal = 0; cbIn = EncryptedSize; - status = EVP_EncryptUpdate(&rc4Ctx, pbOut, &cbOut, pbIn, cbIn); + rc = winpr_Cipher_Update(rc4Ctx, pbIn, cbIn, pbOut, &cbOut); free(pbIn); - if (!status) + if (!rc) { WLog_ERR(TAG, "EVP_CipherUpdate failure"); + winpr_Cipher_Free(rc4Ctx); free (pbOut); return NULL; } - status = EVP_EncryptFinal_ex(&rc4Ctx, pbOut + cbOut, &cbFinal); - - if (!status) + if (!winpr_Cipher_Final(rc4Ctx, pbOut + cbOut, &cbFinal)) { WLog_ERR(TAG, "EVP_CipherFinal_ex failure"); + winpr_Cipher_Free(rc4Ctx); free (pbOut); return NULL; } - EVP_CIPHER_CTX_cleanup(&rc4Ctx); + winpr_Cipher_Free(rc4Ctx); *pEncryptedSize = EncryptedSize; @@ -671,17 +664,17 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) { int status; - SHA_CTX shaCtx; + WINPR_SHA1_CTX shaCtx; int cbPasswordW; int cchOutW = 0; WCHAR* pbOutW = NULL; - EVP_CIPHER_CTX aesDec; + WINPR_CIPHER_CTX* aesDec; WCHAR* PasswordW = NULL; BYTE* pbIn, *pbOut; - int cbOut, cbIn, cbFinal; - BYTE DerivedKey[AES_BLOCK_SIZE]; - BYTE InitializationVector[AES_BLOCK_SIZE]; - BYTE PasswordHash[SHA_DIGEST_LENGTH]; + size_t cbOut, cbIn, cbFinal; + BYTE DerivedKey[WINPR_AES_BLOCK_SIZE]; + BYTE InitializationVector[WINPR_AES_BLOCK_SIZE]; + BYTE PasswordHash[WINPR_SHA1_DIGEST_LENGTH]; status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0); @@ -690,9 +683,13 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) cbPasswordW = (status - 1) * 2; - SHA1_Init(&shaCtx); - SHA1_Update(&shaCtx, PasswordW, cbPasswordW); - SHA1_Final((void*) PasswordHash, &shaCtx); + if (!winpr_SHA1_Init(&shaCtx) || + !winpr_SHA1_Update(&shaCtx, (BYTE*)PasswordW, cbPasswordW) || + !winpr_SHA1_Final(&shaCtx, PasswordHash, sizeof(PasswordHash))) + { + free (PasswordW); + return -1; + } status = freerdp_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash), DerivedKey, sizeof(DerivedKey)); @@ -705,22 +702,9 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) ZeroMemory(InitializationVector, sizeof(InitializationVector)); - EVP_CIPHER_CTX_init(&aesDec); - - status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, NULL, NULL); - - if (status != 1) - { - free(PasswordW); - return -1; - } - - EVP_CIPHER_CTX_set_key_length(&aesDec, (128 / 8)); - EVP_CIPHER_CTX_set_padding(&aesDec, 0); - - status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, DerivedKey, InitializationVector); - - if (status != 1) + aesDec = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT, + DerivedKey, InitializationVector); + if (!aesDec) { free(PasswordW); return -1; @@ -729,34 +713,33 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password) cbOut = cbFinal = 0; cbIn = file->EncryptedLHTicketLength; pbIn = (BYTE*) file->EncryptedLHTicket; - pbOut = (BYTE*) calloc(1, cbIn + AES_BLOCK_SIZE + 2); + pbOut = (BYTE*) calloc(1, cbIn + WINPR_AES_BLOCK_SIZE + 2); if (!pbOut) { + winpr_Cipher_Free(aesDec); free(PasswordW); return -1; } - status = EVP_DecryptUpdate(&aesDec, pbOut, &cbOut, pbIn, cbIn); - - if (status != 1) + if (!winpr_Cipher_Update(aesDec, pbIn, cbIn, pbOut, &cbOut)) { + winpr_Cipher_Free(aesDec); free(PasswordW); free(pbOut); return -1; } - status = EVP_DecryptFinal_ex(&aesDec, pbOut + cbOut, &cbFinal); - - if (status != 1) + if (!winpr_Cipher_Final(aesDec, pbOut + cbOut, &cbFinal)) { WLog_ERR(TAG, "EVP_DecryptFinal_ex failure"); + winpr_Cipher_Free(aesDec); free(PasswordW); free(pbOut); return -1; } - EVP_CIPHER_CTX_cleanup(&aesDec); + winpr_Cipher_Free(aesDec); cbOut += cbFinal; cbFinal = 0; diff --git a/winpr/include/winpr/crypto.h b/winpr/include/winpr/crypto.h index 54a12ac98..7e05124f6 100644 --- a/winpr/include/winpr/crypto.h +++ b/winpr/include/winpr/crypto.h @@ -913,6 +913,8 @@ WINPR_API void winpr_RC4_Free(WINPR_RC4_CTX* ctx); * Generic Cipher API */ +#define WINPR_AES_BLOCK_SIZE 16 + /* cipher operation types */ #define WINPR_ENCRYPT 0 #define WINPR_DECRYPT 1