summaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/LECHash.c101
-rw-r--r--scripts/LOMHash.c77
-rw-r--r--scripts/TimeZones.csx205
-rw-r--r--scripts/blacklist-address-sanitizer.txt0
-rw-r--r--scripts/blacklist-memory-sanitizer.txt1
-rw-r--r--scripts/blacklist-thread-sanitizer.txt0
-rwxr-xr-xscripts/bundle-mac-os.sh298
-rwxr-xr-xscripts/create_release_tarball.sh65
-rwxr-xr-xscripts/fetch_language_identifiers.py129
-rwxr-xr-xscripts/gprof_generate.sh.cmake56
-rw-r--r--scripts/specBytesToCode.py69
-rw-r--r--scripts/test-scard.cpp921
-rwxr-xr-xscripts/toolchains_path.py49
-rwxr-xr-xscripts/update-windows-zones.py41
-rwxr-xr-xscripts/xcode.sh74
-rwxr-xr-xscripts/xkb.pl303
16 files changed, 2389 insertions, 0 deletions
diff --git a/scripts/LECHash.c b/scripts/LECHash.c
new file mode 100644
index 0000000..3464fe3
--- /dev/null
+++ b/scripts/LECHash.c
@@ -0,0 +1,101 @@
+#include <stdio.h>
+typedef unsigned short UINT16;
+
+static UINT16 HuffCodeLEC[] = {
+ 0x0004, 0x0024, 0x0014, 0x0011, 0x0051, 0x0031, 0x0071, 0x0009, 0x0049, 0x0029, 0x0069, 0x0015,
+ 0x0095, 0x0055, 0x00d5, 0x0035, 0x00b5, 0x0075, 0x001d, 0x00f5, 0x011d, 0x009d, 0x019d, 0x005d,
+ 0x000d, 0x008d, 0x015d, 0x00dd, 0x01dd, 0x003d, 0x013d, 0x00bd, 0x004d, 0x01bd, 0x007d, 0x006b,
+ 0x017d, 0x00fd, 0x01fd, 0x0003, 0x0103, 0x0083, 0x0183, 0x026b, 0x0043, 0x016b, 0x036b, 0x00eb,
+ 0x0143, 0x00c3, 0x02eb, 0x01c3, 0x01eb, 0x0023, 0x03eb, 0x0123, 0x00a3, 0x01a3, 0x001b, 0x021b,
+ 0x0063, 0x011b, 0x0163, 0x00e3, 0x00cd, 0x01e3, 0x0013, 0x0113, 0x0093, 0x031b, 0x009b, 0x029b,
+ 0x0193, 0x0053, 0x019b, 0x039b, 0x005b, 0x025b, 0x015b, 0x035b, 0x0153, 0x00d3, 0x00db, 0x02db,
+ 0x01db, 0x03db, 0x003b, 0x023b, 0x013b, 0x01d3, 0x033b, 0x00bb, 0x02bb, 0x01bb, 0x03bb, 0x007b,
+ 0x002d, 0x027b, 0x017b, 0x037b, 0x00fb, 0x02fb, 0x01fb, 0x03fb, 0x0007, 0x0207, 0x0107, 0x0307,
+ 0x0087, 0x0287, 0x0187, 0x0387, 0x0033, 0x0047, 0x0247, 0x0147, 0x0347, 0x00c7, 0x02c7, 0x01c7,
+ 0x0133, 0x03c7, 0x0027, 0x0227, 0x0127, 0x0327, 0x00a7, 0x00b3, 0x0019, 0x01b3, 0x0073, 0x02a7,
+ 0x0173, 0x01a7, 0x03a7, 0x0067, 0x00f3, 0x0267, 0x0167, 0x0367, 0x00e7, 0x02e7, 0x01e7, 0x03e7,
+ 0x01f3, 0x0017, 0x0217, 0x0117, 0x0317, 0x0097, 0x0297, 0x0197, 0x0397, 0x0057, 0x0257, 0x0157,
+ 0x0357, 0x00d7, 0x02d7, 0x01d7, 0x03d7, 0x0037, 0x0237, 0x0137, 0x0337, 0x00b7, 0x02b7, 0x01b7,
+ 0x03b7, 0x0077, 0x0277, 0x07ff, 0x0177, 0x0377, 0x00f7, 0x02f7, 0x01f7, 0x03f7, 0x03ff, 0x000f,
+ 0x020f, 0x010f, 0x030f, 0x008f, 0x028f, 0x018f, 0x038f, 0x004f, 0x024f, 0x014f, 0x034f, 0x00cf,
+ 0x000b, 0x02cf, 0x01cf, 0x03cf, 0x002f, 0x022f, 0x010b, 0x012f, 0x032f, 0x00af, 0x02af, 0x01af,
+ 0x008b, 0x03af, 0x006f, 0x026f, 0x018b, 0x016f, 0x036f, 0x00ef, 0x02ef, 0x01ef, 0x03ef, 0x001f,
+ 0x021f, 0x011f, 0x031f, 0x009f, 0x029f, 0x019f, 0x039f, 0x005f, 0x004b, 0x025f, 0x015f, 0x035f,
+ 0x00df, 0x02df, 0x01df, 0x03df, 0x003f, 0x023f, 0x013f, 0x033f, 0x00bf, 0x02bf, 0x014b, 0x01bf,
+ 0x00ad, 0x00cb, 0x01cb, 0x03bf, 0x002b, 0x007f, 0x027f, 0x017f, 0x012b, 0x037f, 0x00ff, 0x02ff,
+ 0x00ab, 0x01ab, 0x006d, 0x0059, 0x17ff, 0x0fff, 0x0039, 0x0079, 0x01ff, 0x0005, 0x0045, 0x0034,
+ 0x000c, 0x002c, 0x001c, 0x0000, 0x003c, 0x0002, 0x0022, 0x0010, 0x0012, 0x0008, 0x0032, 0x000a,
+ 0x002a, 0x001a, 0x003a, 0x0006, 0x0026, 0x0016, 0x0036, 0x000e, 0x002e, 0x001e, 0x003e, 0x0001,
+ 0x00ed, 0x0018, 0x0021, 0x0025, 0x0065
+};
+
+UINT16 HashTable[512] = { [0 ... 511] = 0xffff };
+
+static UINT16 tab[8] = { 511, 0, 508, 448, 494, 347, 486, 482 };
+
+UINT16 hash(UINT16 key)
+{
+ UINT16 h;
+ h = (key & 0x1ff) ^ (key >> 9) ^ (key >> 4) ^ (key >> 7);
+ return h;
+}
+
+UINT16 minihash(UINT16 key)
+{
+ UINT16 h;
+ h = ((((key >> 8) ^ (key & 0xff)) >> 2) & 0xf);
+
+ if (key >> 9)
+ h = ~h;
+
+ return (h % 12);
+}
+
+void buildhashtable(void)
+{
+ for (int i = 0; i < 293; i++)
+ {
+ UINT16 h = hash(HuffCodeLEC[i]);
+
+ if (HashTable[h] != 0xffff)
+ {
+ HashTable[h] ^= (HuffCodeLEC[i] & 0xfe00) ^ 0xfe00;
+ HashTable[tab[minihash(HuffCodeLEC[i])]] = i;
+ }
+ else
+ {
+ HashTable[h] = i;
+ HashTable[h] ^= 0xfe00;
+ }
+ }
+}
+
+UINT16 getvalue(UINT16 huff)
+{
+ UINT16 h = HashTable[hash(huff)];
+
+ if ((h ^ huff) >> 9)
+ return h & 0x1ff;
+ else
+ return HashTable[tab[minihash(huff)]];
+}
+
+main()
+{
+ buildhashtable();
+ printf("static UINT16 HuffIndexLEC[512] = {\n");
+
+ for (int i = 0; i < 512; i++)
+ {
+ if (i == 511)
+ printf("0x%04" PRIx16 " };\n", HashTable[i]);
+ else
+ printf("0x%04" PRIx16 ", ", HashTable[i]);
+ }
+
+ for (int i = 0; i < 293; i++)
+ if (i != getvalue(HuffCodeLEC[i]))
+ printf("Fail :( at %d : 0x%04" PRIx16 "\n", i, HuffCodeLEC[i]);
+
+ return 0;
+}
diff --git a/scripts/LOMHash.c b/scripts/LOMHash.c
new file mode 100644
index 0000000..b3b97c3
--- /dev/null
+++ b/scripts/LOMHash.c
@@ -0,0 +1,77 @@
+#include <stdio.h>
+typedef unsigned short UINT16;
+typedef unsigned char BYTE;
+static UINT16 HuffCodeLOM[] = { 0x0001, 0x0000, 0x0002, 0x0009, 0x0006, 0x0005, 0x000d, 0x000b,
+ 0x0003, 0x001b, 0x0007, 0x0017, 0x0037, 0x000f, 0x004f, 0x006f,
+ 0x002f, 0x00ef, 0x001f, 0x005f, 0x015f, 0x009f, 0x00df, 0x01df,
+ 0x003f, 0x013f, 0x00bf, 0x01bf, 0x007f, 0x017f, 0x00ff, 0x01ff };
+
+UINT16 HashTable[32] = { [0 ... 31] = 0xffff };
+
+BYTE tab[4] = { 0, 4, 10, 19 };
+
+UINT16 hash(UINT16 key)
+{
+ return ((key & 0x1f) ^ (key >> 5) ^ (key >> 9));
+}
+
+BYTE minihash(UINT16 key)
+{
+ BYTE h;
+ h = (key >> 4) & 0xf;
+ return ((h ^ (h >> 2) ^ (h >> 3)) & 0x3);
+}
+
+void buildhashtable(void)
+{
+ for (int i = 0; i < 32; i++)
+ {
+ UINT16 h = hash(HuffCodeLOM[i]);
+
+ if (HashTable[h] != 0xffff)
+ {
+ HashTable[h] ^= (HuffCodeLOM[i] & 0xfe0) ^ 0xfe0;
+ HashTable[tab[minihash(HuffCodeLOM[i])]] = i;
+ }
+ else
+ {
+ HashTable[h] = i;
+ HashTable[h] ^= 0xfe0;
+ }
+
+ printf("at %d %" PRIu16 "=0x%" PRIx16 "\n", i, h, HashTable[h]);
+ }
+}
+
+BYTE getvalue(UINT16 huff)
+{
+ UINT16 h = HashTable[hash(huff)];
+
+ if ((h ^ huff) >> 5)
+ {
+ return h & 0x1f;
+ }
+ else
+ return HashTable[tab[minihash(huff)]];
+}
+
+main()
+{
+ buildhashtable();
+ printf("static UINT16 HuffIndexLOM[32] = {\n");
+
+ for (int i = 0; i < 32; i++)
+ {
+ if (i == 31)
+ printf("0x%" PRIx16 " };\n", HashTable[i]);
+ else
+ printf("0x%" PRIx16 ", ", HashTable[i]);
+ }
+
+ for (int i = 0; i < 32; i++)
+ if (i != getvalue(HuffCodeLOM[i]))
+ printf("Fail :( at %d : 0x%04" PRIx16 " got %" PRIu8 "\n", i, HuffCodeLOM[i],
+ getvalue(HuffCodeLOM[i]));
+
+ return 0;
+}
diff --git a/scripts/TimeZones.csx b/scripts/TimeZones.csx
new file mode 100644
index 0000000..d0a39ba
--- /dev/null
+++ b/scripts/TimeZones.csx
@@ -0,0 +1,205 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Time Zone Redirection Table Generator
+ *
+ * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * 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.
+ */
+/* Run with ' csi scripts/TimeZones.csx' from freerdp checkout root */
+
+using System;
+using System.IO;
+using System.Globalization;
+using System.Collections.ObjectModel;
+
+struct SYSTEM_TIME_ENTRY
+{
+ public UInt16 wYear;
+ public UInt16 wMonth;
+ public UInt16 wDayOfWeek;
+ public UInt16 wDay;
+ public UInt16 wHour;
+ public UInt16 wMinute;
+ public UInt16 wSecond;
+ public UInt16 wMilliseconds;
+};
+
+struct TIME_ZONE_RULE_ENTRY
+{
+ public long TicksStart;
+ public long TicksEnd;
+ public Int32 DaylightDelta;
+ public SYSTEM_TIME_ENTRY StandardDate;
+ public SYSTEM_TIME_ENTRY DaylightDate;
+};
+
+struct TIME_ZONE_ENTRY
+{
+ public string Id;
+ public Int32 Bias;
+ public bool SupportsDST;
+ public string DisplayName;
+ public string StandardName;
+ public string DaylightName;
+ public string RuleTable;
+ public UInt32 RuleTableCount;
+};
+
+int i;
+UInt32 index;
+const string file = @"winpr/libwinpr/timezone/TimeZones.c";
+TimeZoneInfo.AdjustmentRule[] rules;
+StreamWriter stream = new StreamWriter(file, false);
+ReadOnlyCollection<TimeZoneInfo> timeZones = TimeZoneInfo.GetSystemTimeZones();
+
+Console.WriteLine("Updating " + file);
+stream.WriteLine("/* ");
+stream.WriteLine(" * Automatically generated with scripts/TimeZones.csx");
+stream.WriteLine(" */ ");
+stream.WriteLine();
+
+stream.WriteLine("#include \"TimeZones.h\"");
+stream.WriteLine();
+
+index = 0;
+
+foreach (TimeZoneInfo timeZone in timeZones)
+{
+ rules = timeZone.GetAdjustmentRules();
+
+ if ((!timeZone.SupportsDaylightSavingTime) || (rules.Length < 1))
+ {
+ index++;
+ continue;
+ }
+
+ stream.WriteLine("static const TIME_ZONE_RULE_ENTRY TimeZoneRuleTable_{0}[] =", index);
+ stream.WriteLine("{");
+
+ i = 0;
+ foreach (TimeZoneInfo.AdjustmentRule rule in rules)
+ {
+ DateTime time;
+ TIME_ZONE_RULE_ENTRY tzr;
+ TimeZoneInfo.TransitionTime transition;
+
+ tzr.TicksStart = rule.DateEnd.ToUniversalTime().Ticks;
+ tzr.TicksEnd = rule.DateStart.ToUniversalTime().Ticks;
+ tzr.DaylightDelta = (Int32)rule.DaylightDelta.TotalMinutes;
+
+ transition = rule.DaylightTransitionEnd;
+ time = transition.TimeOfDay;
+
+ tzr.StandardDate.wYear = (UInt16)0;
+ tzr.StandardDate.wMonth = (UInt16)transition.Month;
+ tzr.StandardDate.wDayOfWeek = (UInt16)transition.DayOfWeek;
+ tzr.StandardDate.wDay = (UInt16)transition.Week;
+ tzr.StandardDate.wHour = (UInt16)time.Hour;
+ tzr.StandardDate.wMinute = (UInt16)time.Minute;
+ tzr.StandardDate.wSecond = (UInt16)time.Second;
+ tzr.StandardDate.wMilliseconds = (UInt16)time.Millisecond;
+
+ transition = rule.DaylightTransitionStart;
+ time = transition.TimeOfDay;
+
+ tzr.DaylightDate.wYear = (UInt16)0;
+ tzr.DaylightDate.wMonth = (UInt16)transition.Month;
+ tzr.DaylightDate.wDayOfWeek = (UInt16)transition.DayOfWeek;
+ tzr.DaylightDate.wDay = (UInt16)transition.Week;
+ tzr.DaylightDate.wHour = (UInt16)time.Hour;
+ tzr.DaylightDate.wMinute = (UInt16)time.Minute;
+ tzr.DaylightDate.wSecond = (UInt16)time.Second;
+ tzr.DaylightDate.wMilliseconds = (UInt16)time.Millisecond;
+
+ stream.Write("\t{");
+ stream.Write(" {0}ULL, {1}ULL, {2},", tzr.TicksStart, tzr.TicksEnd, tzr.DaylightDelta);
+
+ stream.Write(" { ");
+ stream.Write("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}",
+ tzr.StandardDate.wYear, tzr.StandardDate.wMonth, tzr.StandardDate.wDayOfWeek,
+ tzr.StandardDate.wDay, tzr.StandardDate.wHour, tzr.StandardDate.wMinute,
+ tzr.StandardDate.wSecond, tzr.StandardDate.wMilliseconds);
+ stream.Write(" }, ");
+
+ stream.Write("{ ");
+ stream.Write("{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}",
+ tzr.DaylightDate.wYear, tzr.DaylightDate.wMonth, tzr.DaylightDate.wDayOfWeek,
+ tzr.DaylightDate.wDay, tzr.DaylightDate.wHour, tzr.DaylightDate.wMinute,
+ tzr.DaylightDate.wSecond, tzr.DaylightDate.wMilliseconds);
+ stream.Write(" },");
+
+ if (++i < rules.Length)
+ stream.WriteLine(" },");
+ else
+ stream.WriteLine(" }");
+ }
+
+ stream.WriteLine("};");
+ stream.WriteLine();
+ index++;
+}
+
+index = 0;
+stream.WriteLine("const TIME_ZONE_ENTRY TimeZoneTable[] =");
+stream.WriteLine("{");
+
+foreach (TimeZoneInfo timeZone in timeZones)
+{
+ TIME_ZONE_ENTRY tz;
+ TimeSpan offset = timeZone.BaseUtcOffset;
+
+ rules = timeZone.GetAdjustmentRules();
+
+ tz.Id = timeZone.Id;
+ tz.Bias = -(Int32)offset.TotalMinutes;
+
+ tz.SupportsDST = timeZone.SupportsDaylightSavingTime;
+
+ tz.DisplayName = timeZone.DisplayName;
+ tz.StandardName = timeZone.StandardName;
+ tz.DaylightName = timeZone.DaylightName;
+
+ if ((!tz.SupportsDST) || (rules.Length < 1))
+ {
+ tz.RuleTableCount = 0;
+ tz.RuleTable = "NULL";
+ }
+ else
+ {
+ tz.RuleTableCount = (UInt32)rules.Length;
+ tz.RuleTable = "TimeZoneRuleTable_" + index;
+ }
+
+ stream.WriteLine("\t{");
+
+ stream.WriteLine("\t\t\"{0}\", {1}, {2}, \"{3}\",",
+ tz.Id, tz.Bias, tz.SupportsDST ? "TRUE" : "FALSE", tz.DisplayName);
+
+ stream.WriteLine("\t\t\"{0}\", \"{1}\",", tz.StandardName, tz.DaylightName);
+ stream.WriteLine("\t\t{0}, {1}", tz.RuleTable, tz.RuleTableCount);
+
+ index++;
+
+ if ((int)index < timeZones.Count)
+ stream.WriteLine("\t},");
+ else
+ stream.WriteLine("\t}");
+}
+stream.WriteLine("};");
+stream.WriteLine();
+stream.WriteLine("const size_t TimeZoneTableNrElements = ARRAYSIZE(TimeZoneTable);");
+stream.WriteLine();
+
+stream.Close();
+
diff --git a/scripts/blacklist-address-sanitizer.txt b/scripts/blacklist-address-sanitizer.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/scripts/blacklist-address-sanitizer.txt
diff --git a/scripts/blacklist-memory-sanitizer.txt b/scripts/blacklist-memory-sanitizer.txt
new file mode 100644
index 0000000..9a05abb
--- /dev/null
+++ b/scripts/blacklist-memory-sanitizer.txt
@@ -0,0 +1 @@
+fun:RAND*
diff --git a/scripts/blacklist-thread-sanitizer.txt b/scripts/blacklist-thread-sanitizer.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/scripts/blacklist-thread-sanitizer.txt
diff --git a/scripts/bundle-mac-os.sh b/scripts/bundle-mac-os.sh
new file mode 100755
index 0000000..8bb1986
--- /dev/null
+++ b/scripts/bundle-mac-os.sh
@@ -0,0 +1,298 @@
+#!/bin/bash -xe
+SCRIPT_PATH="$(dirname -- "${BASH_SOURCE[0]}")" # relative
+SCRIPT_PATH="$(cd -- "$SCRIPT_PATH" && pwd)" # absolutized and normalized
+
+BASE=$(pwd)
+SRC="$BASE/src"
+BUILD="$BASE/build"
+INSTALL="$BASE/install/MacFreeRDP.app/Contents"
+
+BINDIR=MacOS
+LIBDIR=Frameworks
+DATADIR=Resources
+
+DEPLOYMENT_ARCH='arm64 x86_64'
+DEPLOYMENT_TARGET=12
+
+usage () {
+ echo "${BASH_SOURCE[0]} [-a|--arch 'arch1 arch2 ...'] [-t|--target target][-h|--help]"
+ echo ""
+ echo "default options:"
+ echo "arch [$DEPLOYMENT_ARCH]"
+ echo "target [$DEPLOYMENT_TARGET]"
+}
+
+while [[ $# -gt 0 ]]; do
+ case $1 in
+ -a|--arch)
+ DEPLOYMENT_ARCH="$2"
+ shift # past argument
+ shift # past value
+ ;;
+ -t|--target)
+ DEPLOYMENT_TARGET="$2"
+ shift # past argument
+ shift # past value
+ ;;
+ -t|--target)
+ usage
+ exit 0
+ ;;
+ -*|--*)
+ usage
+ exit 1
+ ;;
+ *)
+ usage
+ exit 1
+ ;;
+ esac
+done
+
+fix_rpath() {
+ SEARCH_PATH=$1
+ FIX_PATH=$1
+ EXT=".dylib"
+ if [ "$#" -gt 1 ];
+ then
+ FIX_PATH=$2
+ fi
+ if [ "$#" -gt 2 ];
+ then
+ EXT=$3
+ fi
+
+ # some build systems do not handle @rpath on mac os correctly.
+ # do check that and fix it.
+ DYLIB_ABS_NAMES=$(find $SEARCH_PATH -type f -name "*$EXT")
+ for DYLIB_ABS in $DYLIB_ABS_NAMES;
+ do
+ DYLIB_NAME=$(basename $DYLIB_ABS)
+ install_name_tool -id @rpath/$DYLIB_NAME $DYLIB_ABS
+
+ for DYLIB_DEP in $(otool -L $DYLIB_ABS | grep "$FIX_PATH" | cut -d' ' -f1);
+ do
+ if [[ $DYLIB_DEP == $DYLIB_ABS ]];
+ then
+ continue
+ elif [[ $DYLIB_DEP == $FIX_PATH/* ]];
+ then
+ DEP_BASE=$(basename $DYLIB_DEP)
+ install_name_tool -change $DYLIB_DEP @rpath/$DEP_BASE $DYLIB_ABS
+ fi
+ done
+ done
+}
+
+replace_rpath() {
+ FILE=$1
+ for PTH in $(otool -l $FILE | grep -A2 LC_RPATH | grep path | xargs -J ' ' | cut -d ' ' -f2);
+ do
+ install_name_tool -delete_rpath $PTH $FILE
+ done
+ install_name_tool -add_rpath @loader_path/../$LIBDIR $FILE
+}
+
+CMAKE_ARCHS=
+OSSL_FLAGS="-mmacosx-version-min=$DEPLOYMENT_TARGET"
+for ARCH in $DEPLOYMENT_ARCH;
+do
+ OSSL_FLAGS="$OSSL_FLAGS -arch $ARCH"
+ CMAKE_ARCHS="$ARCH;$CMAKE_ARCHS"
+done
+
+echo "build arch [$DEPLOYMENT_ARCH]"
+echo "build target [$DEPLOYMENT_TARGET]"
+
+CMAKE_ARGS="-DCMAKE_SKIP_INSTALL_ALL_DEPENDENCY=ON \
+ -DCMAKE_VERBOSE_MAKEFILE=ON \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DWITH_MANPAGES=OFF \
+ -DBUILD_SHARED_LIBS=ON \
+ -DCMAKE_OSX_ARCHITECTURES=$CMAKE_ARCHS \
+ -DCMAKE_OSX_DEPLOYMENT_TARGET=$DEPLOYMENT_TARGET \
+ -DCMAKE_INSTALL_PREFIX='$INSTALL' \
+ -DCMAKE_INSTALL_LIBDIR='lib' \
+ -DCMAKE_INSTALL_BINDIR='bin' \
+ -DCMAKE_INSTALL_DATADIR='$DATADIR' \
+ -DINSTALL_LIB_DIR='$INSTALL/lib' \
+ -DINSTALL_BIN_DIR='$INSTALL/bin' \
+ -DCMAKE_PREFIX_PATH='$INSTALL;$INSTALL/lib;$INSTALL/lib/cmake' \
+ -DCMAKE_IGNORE_PATH='/opt/local;/usr/local;/opt/homebrew;/Library;~/Library'
+ "
+
+if [ ! -d $SRC ];
+then
+ mkdir -p $SRC
+ cd $SRC
+ git clone -b openssl-3.2.0 https://github.com/openssl/openssl.git
+ git clone --depth 1 -b v1.3 https://github.com/madler/zlib.git
+ git clone --depth 1 -b uriparser-0.9.7 https://github.com/uriparser/uriparser.git
+ git clone --depth 1 -b v1.7.16 https://github.com/DaveGamble/cJSON.git
+ git clone --depth 1 -b release-2.28.1 https://github.com/libsdl-org/SDL.git
+ git clone --depth 1 --shallow-submodules --recurse-submodules -b release-2.20.2 https://github.com/libsdl-org/SDL_ttf.git
+ git clone --depth 1 --shallow-submodules --recurse-submodules -b release-2.8.1 https://github.com/libsdl-org/SDL_image.git
+ git clone --depth 1 --shallow-submodules --recurse-submodules -b v1.0.26 https://github.com/libusb/libusb-cmake.git
+ git clone --depth 1 -b n6.0 https://github.com/FFmpeg/FFmpeg.git
+ git clone --depth 1 -b v2.4.0 https://github.com/cisco/openh264.git
+ git clone --depth 1 -b v1.4 https://gitlab.xiph.org/xiph/opus.git
+ git clone --depth 1 -b 2.11.1 https://github.com/knik0/faad2.git
+ git clone --depth 1 -b 1.18.0 https://gitlab.freedesktop.org/cairo/cairo.git
+ git clone --depth 1 -b 1_30 https://github.com/knik0/faac.git
+ cd faac
+ ./bootstrap
+fi
+
+if [ -d $INSTALL ];
+then
+ rm -rf $INSTALL
+fi
+
+if [ -d $BUILD ];
+then
+ rm -rf $BUILD
+fi
+
+mkdir -p $BUILD
+cd $BUILD
+
+cmake -GNinja -Bzlib -S$SRC/zlib $CMAKE_ARGS
+cmake --build zlib
+cmake --install zlib
+
+cmake -GNinja -Buriparser -S$SRC/uriparser $CMAKE_ARGS -DURIPARSER_BUILD_DOCS=OFF -DURIPARSER_BUILD_TESTS=OFF \
+ -DURIPARSER_BUILD_TOOLS=OFF
+cmake --build uriparser
+cmake --install uriparser
+
+cmake -GNinja -BcJSON -S$SRC/cJSON $CMAKE_ARGS -DENABLE_CJSON_TEST=OFF -DBUILD_SHARED_AND_STATIC_LIBS=OFF
+cmake --build cJSON
+cmake --install cJSON
+
+cmake -GNinja -Bopus -S$SRC/opus $CMAKE_ARGS -DOPUS_BUILD_SHARED_LIBRARY=ON
+cmake --build opus
+cmake --install opus
+
+cmake -GNinja -Bfaad2 -S$SRC/faad2 $CMAKE_ARGS
+cmake --build faad2
+cmake --install faad2
+
+cmake -GNinja -BSDL -S$SRC/SDL $CMAKE_ARGS -DSDL_TEST=OFF -DSDL_TESTS=OFF -DSDL_STATIC_PIC=ON
+cmake --build SDL
+cmake --install SDL
+
+cmake -GNinja -BSDL_ttf -S$SRC/SDL_ttf $CMAKE_ARGS -DSDL2TTF_HARFBUZZ=ON -DSDL2TTF_FREETYPE=ON -DSDL2TTF_VENDORED=ON \
+ -DFT_DISABLE_ZLIB=OFF -DSDL2TTF_SAMPLES=OFF
+cmake --build SDL_ttf
+cmake --install SDL_ttf
+
+cmake -GNinja -BSDL_image -S$SRC/SDL_image $CMAKE_ARGS -DSDL2IMAGE_SAMPLES=OFF -DSDL2IMAGE_DEPS_SHARED=OFF
+cmake --build SDL_image
+cmake --install SDL_image
+
+cmake -GNinja -Blibusb-cmake -S$SRC/libusb-cmake $CMAKE_ARGS -DLIBUSB_BUILD_EXAMPLES=OFF -DLIBUSB_BUILD_TESTING=OFF \
+ -DLIBUSB_ENABLE_DEBUG_LOGGING=OFF -DLIBUSB_BUILD_SHARED_LIBS=ON
+cmake --build libusb-cmake
+cmake --install libusb-cmake
+
+mkdir -p openssl
+cd openssl
+
+CFLAGS=$OSSL_FLAGS LDFLAGS=$OSSL_FLAGS $SRC/openssl/config --prefix=$INSTALL --libdir=lib no-asm no-tests no-docs no-apps zlib
+CFLAGS=$OSSL_FLAGS LDFLAGS=$OSSL_FLAGS make -j build_sw
+CFLAGS=$OSSL_FLAGS LDFLAGS=$OSSL_FLAGS make -j install_sw
+
+cd $BUILD
+mkdir -p faac
+cd faac
+# undefine __SSE2__, symbol clashes with universal build
+CFLAGS="$OSSL_FLAGS -U__SSE2__" LDFLAGS=$OSSL_FLAGS $SRC/faac/configure --prefix=$INSTALL --libdir="$INSTALL/lib" \
+ --enable-shared --disable-static
+CFLAGS="$OSSL_FLAGS -U__SSE2__" LDFLAGS=$OSSL_FLAGS make -j
+CFLAGS="$OSSL_FLAGS -U__SSE2__" LDFLAGS=$OSSL_FLAGS make -j install
+
+cd $BUILD
+
+meson setup --prefix="$INSTALL" -Doptimization=3 -Db_lto=true -Db_pie=true -Dc_args="$OSSL_FLAGS" -Dc_link_args="$OSSL_FLAGS" \
+ -Dcpp_args="$OSSL_FLAGS" -Dcpp_link_args="$OSSL_FLAGS" -Dpkgconfig.relocatable=true -Dtests=disabled \
+ -Dlibdir=lib openh264 $SRC/openh264
+ninja -C openh264 install
+
+for ARCH in $DEPLOYMENT_ARCH;
+do
+ mkdir -p $BUILD/FFmpeg/$ARCH
+ cd $BUILD/FFmpeg/$ARCH
+ FFCFLAGS="-arch $ARCH -mmacosx-version-min=$DEPLOYMENT_TARGET"
+ FINSTPATH=$BUILD/FFmpeg/install/$ARCH
+ CFLAGS=$FFCFLAGS LDFLAGS=$FFCFLAGS $SRC/FFmpeg/configure --prefix=$FINSTPATH --disable-all \
+ --enable-shared --disable-static --enable-swscale --disable-asm --disable-libxcb \
+ --disable-securetransport --disable-xlib --enable-cross-compile
+ CFLAGS=$FFCFLAGS LDFLAGS=$FFCFLAGS make -j
+ CFLAGS=$FFCFLAGS LDFLAGS=$FFCFLAGS make -j install
+ fix_rpath "$FINSTPATH/lib"
+done
+
+BASE_ARCH="${DEPLOYMENT_ARCH%% *}"
+
+cd $BUILD/FFmpeg/install/$ARCH
+cp -r include/* $INSTALL/include/
+find lib -type l -exec cp -P {} $INSTALL/lib/ \;
+BASE_LIBS=$(find lib -type f -name "*.dylib" -exec basename {} \;)
+
+cd $BUILD/FFmpeg/install
+for LIB in $BASE_LIBS;
+do
+ LIBS=$(find . -name $LIB)
+ lipo $LIBS -output $INSTALL/lib/$LIB -create
+done
+
+cd $BUILD
+cmake -GNinja -Bfreerdp -S"$SCRIPT_PATH/.." \
+ $CMAKE_ARGS \
+ -DWITH_PLATFORM_SERVER=OFF \
+ -DWITH_NEON=OFF \
+ -DWITH_SSE=OFF \
+ -DWITH_FFMPEG=OFF \
+ -DWITH_SWSCALE=ON \
+ -DWITH_OPUS=ON \
+ -DWITH_WEBVIEW=OFF \
+ -DWITH_FAAD2=ON \
+ -DWITH_FAAC=ON \
+ -DWITH_INTERNAL_RC4=ON \
+ -DWITH_INTERNAL_MD4=ON \
+ -DWITH_INTERNAL_MD5=ON
+cmake --build freerdp
+cmake --install freerdp
+
+# remove unused stuff from bin
+find "$INSTALL" -name "*.a" -exec rm -f {} \;
+find "$INSTALL" -name "*.la" -exec rm -f {} \;
+find "$INSTALL" -name sdl2-config -exec rm -f {} \;
+
+fix_rpath "$INSTALL/lib"
+fix_rpath "$INSTALL/bin" "$INSTALL/lib" ""
+
+# move files in place
+cd $INSTALL
+mv lib $LIBDIR
+mv bin $BINDIR
+
+# update RPATH
+for LIB in $(find $LIBDIR -type f -name "*.dylib");
+do
+ replace_rpath $LIB
+done
+
+for BIN in $(find $BINDIR -type f);
+do
+ replace_rpath $BIN
+done
+
+# clean up unused data
+rm -rf "$INSTALL/include"
+rm -rf "$INSTALL/share"
+rm -rf "$INSTALL/bin"
+rm -rf "$INSTALL/$LIBDIR/cmake"
+rm -rf "$INSTALL/$LIBDIR/pkgconfig"
+
+# TODO: Create remaining files required
diff --git a/scripts/create_release_tarball.sh b/scripts/create_release_tarball.sh
new file mode 100755
index 0000000..2ad9ca7
--- /dev/null
+++ b/scripts/create_release_tarball.sh
@@ -0,0 +1,65 @@
+#!/bin/bash -e
+
+function run {
+ "$@"
+ RES=$?
+ if [[ $RES -ne 0 ]];
+ then
+ echo "[ERROR] $@ returned $RES" >&2
+ exit 1
+ fi
+}
+
+if [ -z ${TAG:-} ];then
+ echo "No TAG set - trying to detect"
+ TAG=$(git describe --tags)
+ echo "Is the TAG ${TAG} ok (YES|NO)?"
+ read answ
+ case "$answ" in
+ YES):
+ ;;
+ *)
+ echo 'stopping here'
+ exit 1
+ esac
+fi
+
+function create_hash {
+ NAME=$1
+ run md5sum ${NAME} > ${NAME}.md5
+ run sha1sum ${NAME} > ${NAME}.sha1
+ run sha256sum ${NAME} > ${NAME}.sha256
+ run sha512sum ${NAME} > ${NAME}.sha512
+}
+
+function create_tar {
+ ARGS=$1
+ EXT=$2
+ TAG=$3
+
+ NAME=freerdp-${TAG}${EXT}
+ run tar $ARGS ${NAME} freerdp-${TAG}
+ create_hash ${NAME}
+}
+
+TMPDIR=$(mktemp -d -t release-${TAG}-XXXXXXXXXX)
+
+run git archive --prefix=freerdp-${TAG}/ --format=tar.gz -o ${TMPDIR}/freerdp-${TAG}.tar.gz ${TAG}
+run tar xzvf ${TMPDIR}/freerdp-${TAG}.tar.gz -C ${TMPDIR}
+run echo ${TAG} > ${TMPDIR}/freerdp-${TAG}/.source_version
+
+pushd .
+cd $TMPDIR
+create_tar czf .tar.gz ${TAG}
+create_tar cvjSf .tar.bz2 ${TAG}
+create_tar cfJ .tar.xz ${TAG}
+
+ZIPNAME=freerdp-${TAG}.zip
+run zip -r ${ZIPNAME} freerdp-${TAG}
+create_hash ${ZIPNAME}
+popd
+
+run mv ${TMPDIR}/freerdp-${TAG}.tar* .
+run mv ${TMPDIR}/freerdp-${TAG}.zip* .
+run rm -rf ${TMPDIR}
+exit 0
diff --git a/scripts/fetch_language_identifiers.py b/scripts/fetch_language_identifiers.py
new file mode 100755
index 0000000..a6c6adf
--- /dev/null
+++ b/scripts/fetch_language_identifiers.py
@@ -0,0 +1,129 @@
+#!/bin/env python3
+#
+# This is a helper script that fetches the current language and keyboard tables
+# and writes the result to a C compatible struct.
+#
+import os
+import sys
+import requests
+import numpy as np
+import traceback
+from bs4 import BeautifulSoup
+from bs4 import element
+
+intro = '''/* This file is auto generated from
+ *
+ * https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings
+ *
+ * please do not edit but use ./scripts/fetch_language_identifiers.py to regenerate!
+ */
+
+'''
+
+def parse_html(text):
+ soup = BeautifulSoup(text, 'html.parser')
+ table = soup.find("table")
+ head = table.find('thead').find('tr')
+ headers = []
+ for th in head:
+ if type(th) == element.Tag:
+ headers += th
+
+ body = table.find('tbody')
+ languages = []
+
+ for tr in body:
+ if type(tr) == element.Tag:
+ entry = []
+ for th in tr:
+ if type(th) == element.Tag:
+ if th.string:
+ entry += [th.string]
+ else:
+ entry += ['']
+ languages += [entry]
+ return [headers, languages]
+
+def is_base(num, base):
+ try:
+ v = int(num, base)
+ return True
+ except ValueError:
+ return False
+
+def padhexa(v):
+ s = hex(v)
+ return '0x' + s[2:].zfill(8)
+
+def write_struct(fp, struct, name, url, base, inv = False, typemap = None):
+ li = requests.get(url)
+ if li.status_code != requests.codes.ok:
+ print('Could not fetch ' + str(url) + ', reponse code ' + str(li.status_code))
+ sys.exit(1)
+ headers, languages = parse_html(li.text)
+
+ fp.write('const ' + str(struct) + ' ' + str(name) + '[] =\n')
+ fp.write('{\n')
+ fp.write('/* ')
+ for h in headers:
+ fp.write('\t[')
+ fp.write(h)
+ fp.write(']\t')
+ fp.write('*/\n')
+ last = [None] * 32
+ for language in languages:
+ fp.write('\t{ ')
+ line = ''
+ pos = 0
+ for e in language:
+ try:
+ v = int(e, base=base)
+ switcher = {
+ 0: padhexa(v),
+ 2: bin(v),
+ 8: oct(v),
+ 10: str(v),
+ 16: padhexa(v)
+ }
+ h = str(switcher.get(base))
+ if h != "None":
+ last[pos] = h
+ if inv:
+ line = h + ', ' + line
+ else:
+ line += h + ', '
+ except ValueError:
+ if typemap and typemap[pos] != str:
+ line += str(last[pos]) + ',\t'
+ else:
+ if e == "":
+ line += '"' + str(last[pos]) + '",\t'
+ else:
+ line += '"' + e + '",\t'
+ if e != "None":
+ last[pos] = str(e)
+ pos = pos + 1
+ fp.write(line[:-2] + '},\n')
+ fp.write('};\n')
+ fp.write('\n')
+
+def update_lang_identifiers(fp):
+# [Language identifier] [Primary language] [Prim. lang. identifier] [Prim. lang. symbol] [Sublanguage] [Sublang. identifier] [Sublang. symbol]
+ write_struct(fp, 'LanguageIdentifier', 'language_identifiers', 'https://docs.microsoft.com/en-us/windows/win32/intl/language-identifier-constants-and-strings', 16, False, [int, str, int, str, str, int, str])
+
+def update_code_pages(fp):
+ write_struct(fp, 'CodePage', 'code_pages', 'https://docs.microsoft.com/en-us/windows/win32/intl/code-page-identifiers', 10)
+
+def update_input_locales(fp):
+ write_struct(fp, 'KeyboardIdentifier', 'keyboard_identifiers', 'https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-vista/cc766503(v=ws.10)', 0)
+ write_struct(fp, 'RDP_KEYBOARD_LAYOUT', 'RDP_KEYBOARD_LAYOUT_TABLE', 'https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-language-pack-default-values', 16, True)
+
+try:
+ with open('language_identifiers.c', 'w') as fp:
+ fp.write(intro)
+ update_lang_identifiers(fp)
+ update_code_pages(fp)
+ update_input_locales(fp)
+except:
+ print('exception cought')
+ traceback.print_exc()
diff --git a/scripts/gprof_generate.sh.cmake b/scripts/gprof_generate.sh.cmake
new file mode 100755
index 0000000..848989f
--- /dev/null
+++ b/scripts/gprof_generate.sh.cmake
@@ -0,0 +1,56 @@
+#!/bin/bash
+#
+# This script tries to pull gprof profiling information generated by aFreeRDP
+# from the target using adb and generating human readable profiling data from
+# it.
+#
+# Any arguments supplied to the script will be appended to adb.
+#
+# Requirements:
+# - ANDROID_SDK is set to the android SDK directory or adb is in path.
+#
+
+if [ -d $ANDROID_SDK ]; then
+ ADB=$ANDROID_SDK/platform-tools/adb
+else
+ ADB=`which adb`
+fi
+
+GCC=@CMAKE_C_COMPILER@
+GPROF=${GCC/gcc/gprof}
+LIB=@PROJECT_BINARY_DIR@/client/Android/FreeRDPCore/jni/armeabi-v7a/libfreerdp-android.so
+
+if [ ! -f $LIB ]; then
+ echo "Missing libfreerdp-android.so"
+ echo "Please build the project first."
+ exit -1
+fi
+
+if [ ! -f $GPROF ]; then
+ echo "gprof could not be found at $GPROF."
+ echo "Please assure, that you are using a GCC based android toolchain."
+ exit -2
+fi
+
+if [ ! -f $ADB ] || [ ! -x $ADB ]; then
+ echo "adb could not be found."
+ echo "assure, that either ANDROID_SDK is set to the path of your android SDK"
+ echo "or that adb is in path."
+ exit -3
+fi
+
+# Do the acutal work in a temporary directory.
+SRC=`mktemp -d`
+cd $SRC
+$ADB $@ pull /sdcard/gmon.out
+if [ ! -f gmon.out ]; then
+ echo "Could not pull profiling information from device!"
+ RC=-4
+else
+ echo "Pulled profiling information from device, starting conversion..."
+ $GPROF $LIB -PprofCount -QprofCount -P__gnu_mcount_nc -Q__gnu_mcount_nc
+ RC=0
+fi
+rm -rf $SRC
+
+exit $RC
diff --git a/scripts/specBytesToCode.py b/scripts/specBytesToCode.py
new file mode 100644
index 0000000..cee7437
--- /dev/null
+++ b/scripts/specBytesToCode.py
@@ -0,0 +1,69 @@
+#!/usr/bin/python
+#
+# A script to convert blob from the MS spec to array of byte to use in unitary tests
+#
+# 00000000 c7 01 00 01 20 54 e2
+# 00000008 c7 01 00 01 20 54 e2
+# taken from the spec, will give:
+# 0xc7, 0x01, 0x00, 0x01, 0x20, 0x54, 0xe2,
+# 0xc7, 0x01, 0x00, 0x01, 0x20, 0x54, 0xe2,
+#
+# Notes:
+# * the script reads the two first lines to detect the number of items per lines, so you need a blob with at least 2 lines
+# * the script detects if items are hex values by searching for + or -
+#
+# sample usage:
+# $ python scripts/specBytesToCode.py < image.txt > image.c
+# then go edit image.c and paste that in your code
+import sys
+
+
+def getOffset(l):
+ token = l.split(' ')[0]
+ return int(token, 16)
+
+def isHex(l):
+ return l.find('+') == -1 and l.find('-') == -1
+
+if __name__ == '__main__':
+
+ lines = []
+ itemPerLine = 16
+ doHex = True
+
+ # parse the offset to know how many items per line we have
+ l1 = sys.stdin.readline().strip()
+ l2 = sys.stdin.readline().strip()
+ itemsPerLine = getOffset(l2) - getOffset(l1)
+
+ #
+ doHex = isHex(l1)
+
+ for l in [l1, l2] + sys.stdin.readlines():
+ # 00000000 c7 01 00 01 20 54 e2 cc 00 jh.kjkjhkhk
+ l = l.strip() # in case we have spaces before the offset
+ pos = l.find(' ')
+ l = l[pos+1:]
+ items = []
+
+ tokens = l.strip().split(' ')
+ ntokens = 0
+ for t in tokens:
+ if not t: # empty token
+ continue
+
+ if ntokens == itemPerLine:
+ break
+
+ item = ''
+ if doHex:
+ item += '0x'
+ item += t
+
+ items.append(item)
+
+ ntokens += 1
+
+ lines.append(', '.join(items))
+
+ print(",\n".join(lines))
diff --git a/scripts/test-scard.cpp b/scripts/test-scard.cpp
new file mode 100644
index 0000000..d22fca9
--- /dev/null
+++ b/scripts/test-scard.cpp
@@ -0,0 +1,921 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Smartcard API test program
+ *
+ * This simple program can be used to trigger calls for (almost) the
+ * entire SCARD API.
+ * Compile on windows, connect with FreeRDP via RDP with smartcard
+ * redirection enabled and run this test program on the windows
+ * machine.
+ *
+ * Copyright 2020 Armin Novak <armin.novak@thincast.com>
+ * Copyright 2020 Thincast Technologies GmbH
+ *
+ * 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 <iostream>
+#include <string>
+#include <sstream>
+#include <locale>
+#include <codecvt>
+
+#include <comdef.h>
+#include <winscard.h>
+
+static const WCHAR* listW[] = { nullptr, L"SCard$AllReaders\000", L"SCard$DefaultReaders\000",
+ L"SCard$LocalReaders\000", L"SCard$SystemReaders\000" };
+static const char* listA[] = { nullptr, "SCard$AllReaders\000", "SCard$DefaultReaders\000",
+ "SCard$LocalReaders\000", "SCard$SystemReaders\000" };
+
+static std::string scope2str(DWORD scope)
+{
+ switch (scope)
+ {
+ case SCARD_SCOPE_USER:
+ return "SCARD_SCOPE_USER";
+ case SCARD_SCOPE_TERMINAL:
+ return "SCARD_SCOPE_TERMINAL";
+ case SCARD_SCOPE_SYSTEM:
+ return "SCARD_SCOPE_SYSTEM";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static std::string err2str(LONG code)
+{
+ switch (code)
+ {
+ case ERROR_BROKEN_PIPE:
+ return "ERROR_BROKEN_PIPE";
+ case SCARD_E_BAD_SEEK:
+ return "SCARD_E_BAD_SEEK";
+ case SCARD_E_CANCELLED:
+ return "SCARD_E_CANCELLED";
+ case SCARD_E_CANT_DISPOSE:
+ return "SCARD_E_CANT_DISPOSE";
+ case SCARD_E_CARD_UNSUPPORTED:
+ return "SCARD_E_CARD_UNSUPPORTED";
+ case SCARD_E_CERTIFICATE_UNAVAILABLE:
+ return "SCARD_E_CERTIFICATE_UNAVAILABLE";
+ case SCARD_E_COMM_DATA_LOST:
+ return "SCARD_E_COMM_DATA_LOST";
+ case SCARD_E_DIR_NOT_FOUND:
+ return "SCARD_E_DIR_NOT_FOUND";
+ case SCARD_E_DUPLICATE_READER:
+ return "SCARD_E_DUPLICATE_READER";
+ case SCARD_E_FILE_NOT_FOUND:
+ return "SCARD_E_FILE_NOT_FOUND";
+ case SCARD_E_ICC_CREATEORDER:
+ return "SCARD_E_ICC_CREATEORDER";
+ case SCARD_E_ICC_INSTALLATION:
+ return "SCARD_E_ICC_INSTALLATION";
+ case SCARD_E_INSUFFICIENT_BUFFER:
+ return "SCARD_E_INSUFFICIENT_BUFFER";
+ case SCARD_E_INVALID_ATR:
+ return "SCARD_E_INVALID_ATR";
+ case SCARD_E_INVALID_CHV:
+ return "SCARD_E_INVALID_CHV";
+ case SCARD_E_INVALID_HANDLE:
+ return "SCARD_E_INVALID_HANDLE";
+ case SCARD_E_INVALID_PARAMETER:
+ return "SCARD_E_INVALID_PARAMETER";
+ case SCARD_E_INVALID_TARGET:
+ return "SCARD_E_INVALID_TARGET";
+ case SCARD_E_INVALID_VALUE:
+ return "SCARD_E_INVALID_VALUE";
+ case SCARD_E_NO_ACCESS:
+ return "SCARD_E_NO_ACCESS";
+ case SCARD_E_NO_DIR:
+ return "SCARD_E_NO_DIR";
+ case SCARD_E_NO_FILE:
+ return "SCARD_E_NO_FILE";
+ case SCARD_E_NO_KEY_CONTAINER:
+ return "SCARD_E_NO_KEY_CONTAINER";
+ case SCARD_E_NO_MEMORY:
+ return "SCARD_E_NO_MEMORY";
+ case SCARD_E_NO_PIN_CACHE:
+ return "SCARD_E_NO_PIN_CACHE";
+ case SCARD_E_NO_READERS_AVAILABLE:
+ return "SCARD_E_NO_READERS_AVAILABLE";
+ case SCARD_E_NO_SERVICE:
+ return "SCARD_E_NO_SERVICE";
+ case SCARD_E_NO_SMARTCARD:
+ return "SCARD_E_NO_SMARTCARD";
+ case SCARD_E_NO_SUCH_CERTIFICATE:
+ return "SCARD_E_NO_SUCH_CERTIFICATE";
+ case SCARD_E_NOT_READY:
+ return "SCARD_E_NOT_READY";
+ case SCARD_E_NOT_TRANSACTED:
+ return "SCARD_E_NOT_TRANSACTED";
+ case SCARD_E_PCI_TOO_SMALL:
+ return "SCARD_E_PCI_TOO_SMALL";
+ case SCARD_E_PIN_CACHE_EXPIRED:
+ return "SCARD_E_PIN_CACHE_EXPIRED";
+ case SCARD_E_PROTO_MISMATCH:
+ return "SCARD_E_PROTO_MISMATCH";
+ case SCARD_E_READ_ONLY_CARD:
+ return "SCARD_E_READ_ONLY_CARD";
+ case SCARD_E_READER_UNAVAILABLE:
+ return "SCARD_E_READER_UNAVAILABLE";
+ case SCARD_E_READER_UNSUPPORTED:
+ return "SCARD_E_READER_UNSUPPORTED";
+ case SCARD_E_SERVER_TOO_BUSY:
+ return "SCARD_E_SERVER_TOO_BUSY";
+ case SCARD_E_SERVICE_STOPPED:
+ return "SCARD_E_SERVICE_STOPPED";
+ case SCARD_E_SHARING_VIOLATION:
+ return "SCARD_E_SHARING_VIOLATION";
+ case SCARD_E_SYSTEM_CANCELLED:
+ return "SCARD_E_SYSTEM_CANCELLED";
+ case SCARD_E_TIMEOUT:
+ return "SCARD_E_TIMEOUT";
+ case SCARD_E_UNEXPECTED:
+ return "SCARD_E_UNEXPECTED";
+ case SCARD_E_UNKNOWN_CARD:
+ return "SCARD_E_UNKNOWN_CARD";
+ case SCARD_E_UNKNOWN_READER:
+ return "SCARD_E_UNKNOWN_READER";
+ case SCARD_E_UNKNOWN_RES_MNG:
+ return "SCARD_E_UNKNOWN_RES_MNG";
+ case SCARD_E_UNSUPPORTED_FEATURE:
+ return "SCARD_E_UNSUPPORTED_FEATURE";
+ case SCARD_E_WRITE_TOO_MANY:
+ return "SCARD_E_WRITE_TOO_MANY";
+ case SCARD_F_COMM_ERROR:
+ return "SCARD_F_COMM_ERROR";
+ case SCARD_F_INTERNAL_ERROR:
+ return "SCARD_F_INTERNAL_ERROR";
+ case SCARD_F_UNKNOWN_ERROR:
+ return "SCARD_F_UNKNOWN_ERROR";
+ case SCARD_F_WAITED_TOO_LONG:
+ return "SCARD_F_WAITED_TOO_LONG";
+ case SCARD_P_SHUTDOWN:
+ return "SCARD_P_SHUTDOWN";
+ case SCARD_S_SUCCESS:
+ return "SCARD_S_SUCCESS";
+ case SCARD_W_CANCELLED_BY_USER:
+ return "SCARD_W_CANCELLED_BY_USER";
+ case SCARD_W_CACHE_ITEM_NOT_FOUND:
+ return "SCARD_W_CACHE_ITEM_NOT_FOUND";
+ case SCARD_W_CACHE_ITEM_STALE:
+ return "SCARD_W_CACHE_ITEM_STALE";
+ case SCARD_W_CACHE_ITEM_TOO_BIG:
+ return "SCARD_W_CACHE_ITEM_TOO_BIG";
+ case SCARD_W_CARD_NOT_AUTHENTICATED:
+ return "SCARD_W_CARD_NOT_AUTHENTICATED";
+ case SCARD_W_CHV_BLOCKED:
+ return "SCARD_W_CHV_BLOCKED";
+ case SCARD_W_EOF:
+ return "SCARD_W_EOF";
+ case SCARD_W_REMOVED_CARD:
+ return "SCARD_W_REMOVED_CARD";
+ case SCARD_W_RESET_CARD:
+ return "SCARD_W_RESET_CARD";
+ case SCARD_W_SECURITY_VIOLATION:
+ return "SCARD_W_SECURITY_VIOLATION";
+ case SCARD_W_UNPOWERED_CARD:
+ return "SCARD_W_UNPOWERED_CARD";
+ case SCARD_W_UNRESPONSIVE_CARD:
+ return "SCARD_W_UNRESPONSIVE_CARD";
+ case SCARD_W_UNSUPPORTED_CARD:
+ return "SCARD_W_UNSUPPORTED_CARD";
+ case SCARD_W_WRONG_CHV:
+ return "SCARD_W_WRONG_CHV";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static std::wstring err2wstr(LONG code)
+{
+ auto str = err2str(code);
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+ return converter.from_bytes(str);
+}
+
+#if 0
+static bool test_listreadergroups(SCARDCONTEXT hContext) {
+ auto rc = SCardListReaderGroupsA(hContext, &groups, &foobar);
+ rc = SCardListReaderGroupsW(hContext, &groups, &foobar);
+}
+#endif
+
+static bool test_valid(SCARDCONTEXT context)
+{
+ auto rc = SCardIsValidContext(context);
+ if (rc)
+ std::cerr << "SCardIsValidContext failed with " << err2str(rc) << std::endl;
+ return true;
+}
+
+static bool test_list_readers_a(SCARDCONTEXT context)
+{
+ for (auto cur : listA)
+ {
+ LPSTR mszReaders = nullptr;
+ DWORD chReaders = SCARD_AUTOALLOCATE;
+ auto rc = SCardListReadersA(context, cur, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
+ if (!cur)
+ {
+ cur = "NULL";
+ }
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardListReadersA [" << cur << "] failed with " << err2str(rc)
+ << std::endl;
+ }
+ else
+ {
+ auto start = mszReaders;
+ auto end = &mszReaders[chReaders];
+
+ std::cout << "SCardListReadersA [" << cur << "] " << chReaders << " [";
+ while (start < end)
+ {
+ std::cout << start << ", ";
+ start += strnlen(start, chReaders) + 2;
+ }
+ std::cout << "]" << std::endl;
+ }
+ SCardFreeMemory(context, mszReaders);
+ }
+
+ return true;
+}
+
+static bool test_list_readers_w(SCARDCONTEXT context)
+{
+ for (auto cur : listW)
+ {
+ LPWSTR mszReaders = nullptr;
+ DWORD chReaders = SCARD_AUTOALLOCATE;
+ auto rc =
+ SCardListReadersW(context, cur, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
+ if (!cur)
+ {
+ cur = L"NULL";
+ }
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::wcerr << L"SCardListReadersW [" << cur << L"] failed with " << err2wstr(rc)
+ << std::endl;
+ }
+ else
+ {
+ auto start = mszReaders;
+ auto end = &mszReaders[chReaders];
+
+ std::wcout << L"SCardListReadersW [" << cur << L"] " << chReaders << L" [";
+ while (start < end)
+ {
+ std::wcout << start << L", ";
+ start += wcsnlen(start, chReaders) + 2;
+ }
+ std::wcout << L"]" << std::endl;
+ }
+ SCardFreeMemory(context, mszReaders);
+ }
+
+ return true;
+}
+
+static bool test_list_reader_groups_a(SCARDCONTEXT context)
+{
+ LPSTR mszReaders = nullptr;
+ DWORD chReaders = SCARD_AUTOALLOCATE;
+ auto rc = SCardListReaderGroupsA(context, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardListReaderGroupsA failed with " << err2str(rc) << std::endl;
+ }
+ else
+ {
+ auto start = mszReaders;
+ auto end = &mszReaders[chReaders];
+
+ std::cout << "SCardListReaderGroupsA " << chReaders << " [";
+ while (start < end)
+ {
+ std::cout << start << ", ";
+ start += strnlen(start, chReaders) + 2;
+ }
+ std::cout << "]" << std::endl;
+ }
+ SCardFreeMemory(context, mszReaders);
+
+ return true;
+}
+
+static bool test_list_reader_groups_w(SCARDCONTEXT context)
+{
+ LPWSTR mszReaders = nullptr;
+ DWORD chReaders = SCARD_AUTOALLOCATE;
+ auto rc = SCardListReaderGroupsW(context, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::wcerr << L"SCardListReaderGroupsW failed with " << err2wstr(rc) << std::endl;
+ }
+ else
+ {
+ auto start = mszReaders;
+ auto end = &mszReaders[chReaders];
+
+ std::wcout << L"SCardListReaderGroupsW " << chReaders << L" [";
+ while (start < end)
+ {
+ std::wcout << start << L", ";
+ start += wcsnlen(start, chReaders) + 2;
+ }
+ std::wcout << L"]" << std::endl;
+ }
+ SCardFreeMemory(context, mszReaders);
+
+ return true;
+}
+
+static bool test_introduce_forget_reader_groups_a(SCARDCONTEXT context)
+{
+ LPSTR group = "somefancygroup";
+
+ auto rc = SCardIntroduceReaderGroupA(context, group);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardIntroduceReaderGroupA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ else
+ {
+ rc = SCardForgetReaderGroupA(context, group);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardForgetReaderGroupA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ return true;
+ }
+}
+
+static bool test_introduce_forget_reader_groups_w(SCARDCONTEXT context)
+{
+ LPWSTR group = L"somefancygroup";
+
+ auto rc = SCardIntroduceReaderGroupW(context, group);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardIntroduceReaderGroupW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ else
+ {
+ rc = SCardForgetReaderGroupW(context, group);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardForgetReaderGroupW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ return true;
+ }
+}
+
+static bool test_introduce_forget_reader_a(SCARDCONTEXT context)
+{
+ LPSTR reader = "somefancygroup";
+ LPSTR device = "otherfancy";
+
+ auto rc = SCardIntroduceReaderA(context, reader, device);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardIntroduceReaderA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ else
+ {
+ rc = SCardForgetReaderA(context, reader);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardForgetReaderA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ return true;
+ }
+}
+
+static bool test_introduce_forget_reader_w(SCARDCONTEXT context)
+{
+ LPWSTR reader = L"somefancygroup";
+ LPWSTR device = L"otherfancy";
+
+ auto rc = SCardIntroduceReaderW(context, reader, device);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardIntroduceReaderW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ else
+ {
+ rc = SCardForgetReaderW(context, reader);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardForgetReaderW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ return true;
+ }
+}
+
+static bool test_list_cards_a(SCARDCONTEXT context)
+{
+ DWORD chCards = SCARD_AUTOALLOCATE;
+ LPSTR mszCards = nullptr;
+ auto rc =
+ SCardListCardsA(context, nullptr, nullptr, 0, reinterpret_cast<LPSTR>(&mszCards), &chCards);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardListCardsA failed with " << err2str(rc) << std::endl;
+ }
+ else
+ {
+ auto start = mszCards;
+ auto end = &mszCards[chCards];
+ std::cout << "SCardListCardsA " << chCards << " [";
+ while (start < end)
+ {
+ std::cout << start << ", ";
+ start += strnlen(start, chCards) + 2;
+ }
+ std::cout << "]" << std::endl;
+ }
+ return true;
+}
+
+static bool test_list_cards_w(SCARDCONTEXT context)
+{
+ DWORD chCards = SCARD_AUTOALLOCATE;
+ LPWSTR mszCards = nullptr;
+ auto rc = SCardListCardsW(context, nullptr, nullptr, 0, reinterpret_cast<LPWSTR>(&mszCards),
+ &chCards);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardListCardsW failed with " << err2str(rc) << std::endl;
+ }
+ else
+ {
+ auto start = mszCards;
+ auto end = &mszCards[chCards];
+ std::cout << "SCardListCardsW " << chCards << " [";
+ while (start < end)
+ {
+ std::wcout << start << L", ";
+ start += wcsnlen(start, chCards) + 2;
+ }
+ std::cout << "]" << std::endl;
+ }
+ return true;
+}
+
+static bool test_cache_a(SCARDCONTEXT context)
+{
+ BYTE wdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ const DWORD wdatalen = sizeof(wdata);
+ BYTE data[32] = {};
+ DWORD datalen = sizeof(data);
+ LPSTR name = "testdata";
+ UUID id = {};
+
+ auto rc = SCardWriteCacheA(context, &id, 0, name, wdata, wdatalen);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardWriteCacheA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ rc = SCardReadCacheA(context, &id, 0, name, data, &datalen);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardReadCacheA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ if (wdatalen != datalen)
+ {
+ std::cerr << "SCardWriteCacheA wrote " << wdatalen << "bytes, SCardReadCacheA read "
+ << datalen << "bytes" << std::endl;
+ return false;
+ }
+
+ if (memcmp(wdata, data, wdatalen) != 0)
+ {
+ std::cerr << "SCardWriteCacheA / SCardReadCacheA data corruption detected" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_cache_w(SCARDCONTEXT context)
+{
+ BYTE wdata[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ const DWORD wdatalen = sizeof(wdata);
+ BYTE data[32] = {};
+ DWORD datalen = sizeof(data);
+ LPWSTR name = L"testdata";
+ UUID id = {};
+
+ auto rc = SCardWriteCacheW(context, &id, 0, name, wdata, wdatalen);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardWriteCacheW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ rc = SCardReadCacheW(context, &id, 0, name, data, &datalen);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardReadCacheW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ if (wdatalen != datalen)
+ {
+ std::cerr << "SCardReadCacheW wrote " << wdatalen << "bytes, SCardReadCacheW read "
+ << datalen << "bytes" << std::endl;
+ return false;
+ }
+
+ if (memcmp(wdata, data, wdatalen) != 0)
+ {
+ std::cerr << "SCardReadCacheW / SCardReadCacheW data corruption detected" << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_reader_icon_a(SCARDCONTEXT context)
+{
+ LPSTR name = "Gemalto PC Twin Reader 00 00\0\0";
+ LPBYTE pbIcon = nullptr;
+ DWORD cbIcon = SCARD_AUTOALLOCATE;
+
+ auto rc = SCardGetReaderIconA(context, name, reinterpret_cast<LPBYTE>(&pbIcon), &cbIcon);
+ SCardFreeMemory(context, pbIcon);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardGetReaderIconA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_reader_icon_w(SCARDCONTEXT context)
+{
+ LPWSTR name = L"Gemalto PC Twin Reader 00 00\0\0";
+ LPBYTE pbIcon = nullptr;
+ DWORD cbIcon = SCARD_AUTOALLOCATE;
+
+ auto rc = SCardGetReaderIconW(context, name, reinterpret_cast<LPBYTE>(&pbIcon), &cbIcon);
+ SCardFreeMemory(context, pbIcon);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardGetReaderIconW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_locate_cards_a(SCARDCONTEXT context)
+{
+ LPSTR name = "Gemalto PC Twin Reader 00 00\0\0";
+ SCARD_READERSTATEA rgReaderStates[16] = {};
+
+ auto rc = SCardLocateCardsA(context, name, rgReaderStates, ARRAYSIZE(rgReaderStates));
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardLocateCardsA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_locate_cards_w(SCARDCONTEXT context)
+{
+ LPWSTR name = L"Gemalto PC Twin Reader 00 00\0\0";
+ SCARD_READERSTATEW rgReaderStates[16] = {};
+
+ auto rc = SCardLocateCardsW(context, name, rgReaderStates, ARRAYSIZE(rgReaderStates));
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardLocateCardsW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_locate_cards_by_atr_a(SCARDCONTEXT context)
+{
+ SCARD_READERSTATEA rgReaderStates[16] = {};
+ SCARD_ATRMASK rgAtrMasks[16] = {};
+
+ auto rc = SCardLocateCardsByATRA(context, rgAtrMasks, ARRAYSIZE(rgAtrMasks), rgReaderStates,
+ ARRAYSIZE(rgReaderStates));
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardLocateCardsByATRA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_locate_cards_by_atr_w(SCARDCONTEXT context)
+{
+ SCARD_READERSTATEW rgReaderStates[16] = {};
+ SCARD_ATRMASK rgAtrMasks[16] = {};
+
+ auto rc = SCardLocateCardsByATRW(context, rgAtrMasks, ARRAYSIZE(rgAtrMasks), rgReaderStates,
+ ARRAYSIZE(rgReaderStates));
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardLocateCardsByATRW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_devicetype_id_a(SCARDCONTEXT context)
+{
+ BYTE data[32] = {};
+ LPSTR name = "testdata";
+ DWORD type;
+
+ auto rc = SCardGetDeviceTypeIdA(context, name, &type);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardGetDeviceTypeIdA failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_devicetype_id_w(SCARDCONTEXT context)
+{
+ BYTE data[32] = {};
+ LPWSTR name = L"testdata";
+ DWORD type;
+
+ auto rc = SCardGetDeviceTypeIdW(context, name, &type);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+
+ return true;
+}
+
+static bool test_transmitcount(SCARDHANDLE handle)
+{
+ BYTE data[32] = {};
+ LPWSTR name = L"testdata";
+ DWORD count;
+
+ auto rc = SCardGetTransmitCount(handle, &count);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardGetTransmitCount failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ std::cout << "SCardGetTransmitCount() " << count << std::endl;
+ return true;
+}
+
+static bool test_status_a(SCARDHANDLE handle)
+{
+ BYTE data[32] = {};
+ LPWSTR name = L"testdata";
+ DWORD count;
+ /*
+ auto rc = SCardStatusA(handle, names, len, &state, &protocol, attr, &attrlen);
+ if (rc != SCARD_S_SUCCESS) {
+ std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ */
+ return true;
+}
+
+static bool test_status_w(SCARDHANDLE handle)
+{
+ BYTE data[32] = {};
+ LPWSTR name = L"testdata";
+ DWORD count;
+ /*
+ auto rc = SCardStatusA(handle, names, len, &state, &protocol, attr, &attrlen);
+ if (rc != SCARD_S_SUCCESS) {
+ std::cerr << "SCardGetDeviceTypeIdW failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+*/
+ return true;
+}
+
+static bool test_get_attrib(SCARDCONTEXT context, SCARDHANDLE handle)
+{
+ DWORD attrlen = SCARD_AUTOALLOCATE;
+ LPBYTE attr = nullptr;
+
+ auto rc =
+ SCardGetAttrib(handle, SCARD_ATTR_ATR_STRING, reinterpret_cast<LPBYTE>(&attr), &attrlen);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardGetAttrib failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ std::cout << "SCardGetAttrib [" << attrlen << "]: " << (char*)attr << std::endl;
+ SCardFreeMemory(context, attr);
+
+ return true;
+}
+
+static bool test_set_attrib(SCARDCONTEXT context, SCARDHANDLE handle)
+{
+ DWORD attrlen = SCARD_AUTOALLOCATE;
+ BYTE attr[] = "0123456789";
+
+ auto rc = SCardSetAttrib(handle, SCARD_ATTR_SUPRESS_T1_IFS_REQUEST, attr, ARRAYSIZE(attr));
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardSetAttrib failed with " << err2str(rc) << std::endl;
+ return false;
+ }
+ std::cout << "SCardSetAttrib [" << attrlen << "]: " << (char*)attr << std::endl;
+ SCardFreeMemory(context, attr);
+
+ return true;
+}
+
+int main()
+{
+ std::cout << "Hello World!" << std::endl;
+ try
+ {
+ auto scopes = { SCARD_SCOPE_USER, SCARD_SCOPE_SYSTEM };
+ for (auto scope : scopes)
+ {
+ SCARDCONTEXT context;
+ auto rc = SCardEstablishContext(scope, nullptr, nullptr, &context);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardEstablishContext [" << scope2str(scope) << "] failed with "
+ << err2str(rc) << std::endl;
+ }
+ else
+ {
+ std::cerr << "SCardEstablishContext [" << scope2str(scope) << "] success"
+ << std::endl;
+
+ test_valid(context);
+
+ test_list_reader_groups_a(context);
+ test_list_reader_groups_w(context);
+
+ test_list_readers_a(context);
+ test_list_readers_w(context);
+
+ test_list_cards_a(context);
+ test_list_cards_w(context);
+
+ test_introduce_forget_reader_groups_a(context);
+ test_introduce_forget_reader_groups_w(context);
+
+ test_introduce_forget_reader_a(context);
+ test_introduce_forget_reader_w(context);
+
+ // TODO: Introduce/Remove reader to group
+ test_locate_cards_a(context);
+ test_locate_cards_w(context);
+
+ test_locate_cards_by_atr_a(context);
+ test_locate_cards_by_atr_w(context);
+
+ test_cache_a(context);
+ test_cache_w(context);
+
+ test_reader_icon_a(context);
+ test_reader_icon_w(context);
+
+ test_devicetype_id_a(context);
+ test_devicetype_id_w(context);
+
+ // TODO: statuschange
+ // TODO: begin/end transaction
+ // TODO: state
+ // TODO: transmit
+ // TODO: control
+
+ {
+ DWORD protocol;
+ SCARDHANDLE handle = 0;
+ LPSTR mszReaders;
+ DWORD chReaders = SCARD_AUTOALLOCATE;
+
+ LONG status = SCardListReadersA(
+ context, nullptr, reinterpret_cast<LPSTR>(&mszReaders), &chReaders);
+ if (status == SCARD_S_SUCCESS)
+ status = SCardConnectA(context, mszReaders, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 |
+ SCARD_PROTOCOL_Tx | SCARD_PROTOCOL_RAW,
+ &handle, &protocol);
+ SCardFreeMemory(context, mszReaders);
+ if (status != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardConnectA ["
+ << "] failed with " << err2str(status) << std::endl;
+ }
+ else
+ {
+ test_status_a(handle);
+ test_status_w(handle);
+ test_get_attrib(context, handle);
+ test_set_attrib(context, handle);
+ test_transmitcount(handle);
+
+ status = SCardDisconnect(handle, 0);
+ if (status)
+ {
+ std::cerr << "SCardDisconnect ["
+ << "] failed with " << err2str(status) << std::endl;
+ }
+ }
+ }
+ {
+ DWORD protocol;
+ SCARDHANDLE handle = 0;
+ LPWSTR mszReaders;
+ DWORD chReaders = SCARD_AUTOALLOCATE;
+
+ LONG status = SCardListReadersW(
+ context, nullptr, reinterpret_cast<LPWSTR>(&mszReaders), &chReaders);
+ if (status == SCARD_S_SUCCESS)
+ status = SCardConnectW(context, mszReaders, SCARD_SHARE_SHARED,
+ SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1 |
+ SCARD_PROTOCOL_Tx | SCARD_PROTOCOL_RAW,
+ &handle, &protocol);
+ SCardFreeMemory(context, mszReaders);
+
+ if (status != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardConnectW ["
+ << "] failed with " << err2str(status) << std::endl;
+ }
+ else
+ {
+ test_status_a(handle);
+ test_status_w(handle);
+ test_get_attrib(context, handle);
+ test_set_attrib(context, handle);
+ test_transmitcount(handle);
+
+ status = SCardDisconnect(handle, 0);
+ if (status)
+ {
+ std::cerr << "SCardDisconnect ["
+ << "] failed with " << err2str(status) << std::endl;
+ }
+ }
+ }
+
+ rc = SCardReleaseContext(context);
+ if (rc != SCARD_S_SUCCESS)
+ {
+ std::cerr << "SCardReleaseContext [" << scope2str(scope) << "] failed with "
+ << err2str(rc) << std::endl;
+ }
+ }
+ }
+ }
+ catch (...)
+ {
+ std::cerr << "exception!!!!" << std::endl;
+ }
+
+ return 0;
+}
diff --git a/scripts/toolchains_path.py b/scripts/toolchains_path.py
new file mode 100755
index 0000000..a85158a
--- /dev/null
+++ b/scripts/toolchains_path.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+"""
+ Get the toolchains path
+ https://proandroiddev.com/tutorial-compile-openssl-to-1-1-1-for-android-application-87137968fee
+"""
+import argparse
+import atexit
+import inspect
+import os
+import shutil
+import stat
+import sys
+import textwrap
+
+def get_host_tag_or_die():
+ """Return the host tag for this platform. Die if not supported."""
+ if sys.platform.startswith('linux'):
+ return 'linux-x86_64'
+ elif sys.platform == 'darwin':
+ return 'darwin-x86_64'
+ elif sys.platform == 'win32' or sys.platform == 'cygwin':
+ host_tag = 'windows-x86_64'
+ if not os.path.exists(os.path.join(NDK_DIR, 'prebuilt', host_tag)):
+ host_tag = 'windows'
+ return host_tag
+ sys.exit('Unsupported platform: ' + sys.platform)
+
+
+def get_toolchain_path_or_die(ndk, host_tag):
+ """Return the toolchain path or die."""
+ toolchain_path = os.path.join(ndk, 'toolchains/llvm/prebuilt',
+ host_tag, 'bin')
+ if not os.path.exists(toolchain_path):
+ sys.exit('Could not find toolchain: {}'.format(toolchain_path))
+ return toolchain_path
+
+def main():
+ """Program entry point."""
+ parser = argparse.ArgumentParser(description='Optional app description')
+ parser.add_argument('--ndk', required=True,
+ help='The NDK Home directory')
+ args = parser.parse_args()
+
+ host_tag = get_host_tag_or_die()
+ toolchain_path = get_toolchain_path_or_die(args.ndk, host_tag)
+ print(toolchain_path)
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/update-windows-zones.py b/scripts/update-windows-zones.py
new file mode 100755
index 0000000..49b96e6
--- /dev/null
+++ b/scripts/update-windows-zones.py
@@ -0,0 +1,41 @@
+#!/usr/bin/env python3
+
+import os
+import urllib.request
+import xml.etree.ElementTree as ET
+
+name = os.path.realpath(__file__)
+base = os.path.normpath(os.path.join(os.path.dirname(name), '..'))
+rname = os.path.relpath(name, base)
+zfile = os.path.join(base, 'winpr/libwinpr/timezone/WindowsZones.c')
+url = 'https://raw.githubusercontent.com/unicode-org/cldr/latest/common/supplemental/windowsZones.xml'
+
+try:
+ with urllib.request.urlopen(url) as response:
+ xml = response.read()
+ root = ET.fromstring(xml)
+ entries = []
+ for child in root.iter('mapZone'):
+ tzid = child.get('type')
+ windows = child.get('other')
+ entries += ['\t{ "' + windows + '", "' + tzid + '" },\n']
+ entries.sort()
+
+ with open(zfile, 'w') as f:
+ f.write('/*\n')
+ f.write(' * Automatically generated with ' + str(rname) + '\n')
+ f.write(' */\n')
+ f.write('\n')
+ f.write('#include "WindowsZones.h"\n')
+ f.write('\n')
+ f.write('const WINDOWS_TZID_ENTRY WindowsTimeZoneIdTable[] =\n')
+ f.write('{\n')
+ for entry in entries:
+ f.write(entry)
+ f.write('};\n')
+ f.write('\n');
+ f.write('const size_t WindowsTimeZoneIdTableNrElements = ARRAYSIZE(WindowsTimeZoneIdTable);\n')
+except Exception as e:
+ print('----------------------------------------------------')
+ print(str(e))
+ print('----------------------------------------------------')
diff --git a/scripts/xcode.sh b/scripts/xcode.sh
new file mode 100755
index 0000000..f86faa9
--- /dev/null
+++ b/scripts/xcode.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+# may now be legacy; 2 stage cmake no longer needed
+
+# Xcode generated files directory
+XCODE_PROJ_DIR=xcode
+# MacFreeRDP client directory
+CLIENT_MAC_DIR=./client/Mac/
+pushd .
+
+GEN='Xcode'
+
+# Build settings
+ARCH=-DCMAKE_OSX_ARCHITECTURES="${CMAKE_OSX_ARCHITECTURES:-i386;x86_64}"
+BUILDTYPE=-DCMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE:Debug}"
+MANPAGES=-DWITH_MANPAGES="${WITHMANPAGES:NO}"
+
+# Run cmake for FreeRDP and MacFreeRDP
+mkdir ${XCODE_PROJ_DIR} >/dev/null 2>&1
+pushd ${XCODE_PROJ_DIR}
+cmake ${BUILDTYPE} -G "$GEN" ${ARCH} ../
+popd
+mkdir ${CLIENT_MAC_DIR}/${XCODE_PROJ_DIR} >/dev/null 2>&1
+pushd ${CLIENT_MAC_DIR}/${XCODE_PROJ_DIR}
+cmake ${BUILDTYPE} -G "$GEN" ${ARCH} ../
+popd
+
+# Check for errors; otherwise, ask for compile.
+if [ "$?" -ne 0 ]; then
+ echo "CMake failed. Please check error messages"
+ popd > /dev/null
+ exit
+else
+ popd
+ while true
+ do
+ echo -n "Compile FreeRDP? (y or n) - (y recommended for MacFreeRDP compilation):"
+ read CONFIRM
+ case $CONFIRM in
+ y|Y|YES|yes|Yes)
+ pushd ./${XCODE_PROJ_DIR}
+ xcodebuild
+ popd
+ break ;;
+ n|N|no|NO|No)
+ echo OK - you entered $CONFIRM
+ break
+ ;;
+ *) echo Please enter only y or n
+ esac
+ done
+
+ echo "SUCCESS!"
+ while true
+ do
+ echo -n "Open Xcode projects now? (y or n):"
+ read CONFIRM
+ case $CONFIRM in
+ y|Y|YES|yes|Yes)
+ open ${CLIENT_MAC_DIR}/${XCODE_PROJ_DIR}/MacFreeRDP.xcodeproj
+ open ./${XCODE_PROJ_DIR}/FreeRDP.xcodeproj
+ break ;;
+ n|N|no|NO|No)
+ echo OK - $CONFIRM
+ break
+ ;;
+ *) echo Please enter only y or n
+ esac
+ done
+
+ echo -n "NOTE: Dragging FreeRDP project from finder onto the MacFreeRDP project in Xcode
+ will enable code stepping from MacFreeRDP into FreeRDP.
+"
+fi
diff --git a/scripts/xkb.pl b/scripts/xkb.pl
new file mode 100755
index 0000000..976ee3b
--- /dev/null
+++ b/scripts/xkb.pl
@@ -0,0 +1,303 @@
+#!/usr/bin/perl
+
+# FreeRDP: A Remote Desktop Protocol Implementation
+# XKB database conversion script
+
+# Copyright 2009 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+
+# 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.
+
+
+# Description:
+# Script to export XKB configuration files to keycode -> virtual key code keymaps that are
+# easy to use in FreeRDP. This makes keymap maintenance easier to make as all bugs can
+# simply be reported to the XKB Configuration Database project, and then this script can
+# be used to export newer (and fixed) version of the XKB Configuration Database.
+
+use Cwd;
+
+my %sym2virt = (
+ "AE00" => "VK_TILDE",
+ "AE01" => "VK_KEY_1",
+ "AE02" => "VK_KEY_2",
+ "AE03" => "VK_KEY_3",
+ "AE04" => "VK_KEY_4",
+ "AE05" => "VK_KEY_5",
+ "AE06" => "VK_KEY_6",
+ "AE07" => "VK_KEY_7",
+ "AE08" => "VK_KEY_8",
+ "AE09" => "VK_KEY_9",
+ "AE10" => "VK_KEY_0",
+ "AE11" => "VK_OEM_MINUS",
+ "AE12" => "VK_OEM_PLUS",
+
+ "AD01" => "VK_KEY_Q",
+ "AD02" => "VK_KEY_W",
+ "AD03" => "VK_KEY_E",
+ "AD04" => "VK_KEY_R",
+ "AD05" => "VK_KEY_T",
+ "AD06" => "VK_KEY_Y",
+ "AD07" => "VK_KEY_U",
+ "AD08" => "VK_KEY_I",
+ "AD09" => "VK_KEY_O",
+ "AD10" => "VK_KEY_P",
+ "AD11" => "VK_OEM_4",
+ "AD12" => "VK_OEM_6",
+
+ "AC01" => "VK_KEY_A",
+ "AC02" => "VK_KEY_S",
+ "AC03" => "VK_KEY_D",
+ "AC04" => "VK_KEY_F",
+ "AC05" => "VK_KEY_G",
+ "AC06" => "VK_KEY_H",
+ "AC07" => "VK_KEY_J",
+ "AC08" => "VK_KEY_K",
+ "AC09" => "VK_KEY_L",
+ "AC10" => "VK_OEM_1",
+ "AC11" => "VK_OEM_7",
+ "AC12" => "VK_OEM_5",
+
+ "AB00" => "VK_LSHIFT",
+ "AB01" => "VK_KEY_Z",
+ "AB02" => "VK_KEY_X",
+ "AB03" => "VK_KEY_C",
+ "AB04" => "VK_KEY_V",
+ "AB05" => "VK_KEY_B",
+ "AB06" => "VK_KEY_N",
+ "AB07" => "VK_KEY_M",
+ "AB08" => "VK_OEM_COMMA",
+ "AB09" => "VK_OEM_PERIOD",
+ "AB10" => "VK_OEM_2",
+ "AB11" => "VK_ABNT_C1",
+
+ "FK01" => "VK_F1",
+ "FK02" => "VK_F2",
+ "FK03" => "VK_F3",
+ "FK04" => "VK_F4",
+ "FK05" => "VK_F5",
+ "FK06" => "VK_F6",
+ "FK07" => "VK_F7",
+ "FK08" => "VK_F8",
+ "FK09" => "VK_F9",
+ "FK10" => "VK_F10",
+ "FK11" => "VK_F11",
+ "FK12" => "VK_F12",
+ "FK13" => "VK_F13",
+ "FK14" => "VK_F14",
+ "FK15" => "VK_F15",
+ "FK16" => "VK_F16",
+ "FK17" => "VK_F17",
+ "FK18" => "VK_F18",
+ "FK19" => "VK_F19",
+ "FK20" => "VK_F20",
+ "FK21" => "VK_F21",
+ "FK22" => "VK_F22",
+ "FK23" => "VK_F23",
+ "FK24" => "VK_F24",
+
+ "KP0" => "VK_NUMPAD0",
+ "KP1" => "VK_NUMPAD1",
+ "KP2" => "VK_NUMPAD2",
+ "KP3" => "VK_NUMPAD3",
+ "KP4" => "VK_NUMPAD4",
+ "KP5" => "VK_NUMPAD5",
+ "KP6" => "VK_NUMPAD6",
+ "KP7" => "VK_NUMPAD7",
+ "KP8" => "VK_NUMPAD8",
+ "KP9" => "VK_NUMPAD9",
+
+ "KPDV" => "VK_DIVIDE",
+ "KPMU" => "VK_MULTIPLY",
+ "KPSU" => "VK_SUBTRACT",
+ "KPAD" => "VK_ADD",
+ "KPDL" => "VK_DECIMAL",
+ "KPEN" => "VK_RETURN",
+
+ "RTRN" => "VK_RETURN",
+ "SPCE" => "VK_SPACE",
+ "BKSP" => "VK_BACK",
+ "BKSL" => "VK_OEM_5",
+ "LSGT" => "VK_OEM_102",
+ "ESC" => "VK_ESCAPE",
+ "TLDE" => "VK_OEM_3",
+ "CAPS" => "VK_CAPITAL",
+ "TAB" => "VK_TAB",
+ "LFSH" => "VK_LSHIFT",
+ "RTSH" => "VK_RSHIFT",
+ "LCTL" => "VK_LCONTROL",
+ "RCTL" => "VK_RCONTROL",
+ "LWIN" => "VK_LWIN",
+ "RWIN" => "VK_RWIN",
+ "LALT" => "VK_LMENU",
+ "RALT" => "VK_RMENU",
+ "COMP" => "VK_APPS",
+ "MENU" => "VK_APPS",
+ "UP" => "VK_UP",
+ "DOWN" => "VK_DOWN",
+ "LEFT" => "VK_LEFT",
+ "RGHT" => "VK_RIGHT",
+ "INS" => "VK_INSERT",
+ "DELE" => "VK_DELETE",
+ "PGUP" => "VK_PRIOR",
+ "PGDN" => "VK_NEXT",
+ "HOME" => "VK_HOME",
+ "END" => "VK_END",
+ "PAUS" => "VK_PAUSE",
+ "NMLK" => "VK_NUMLOCK",
+ "SCLK" => "VK_SCROLL",
+
+ # This page helps understanding the keys that follow:
+ # http://www.stanford.edu/class/cs140/projects/pintos/specs/kbd/scancodes-7.html
+
+ "KANJ" => "VK_KANJI",
+ "HANJ" => "VK_HANJA",
+ "MUHE" => "VK_NONCONVERT",
+ "HIRA" => "VK_KANA",
+ "PRSC" => "VK_SNAPSHOT",
+
+ "KPF1" => "VK_NUMLOCK",
+ "KPF2" => "VK_DIVIDE",
+ "KPF3" => "VK_MULTIPLY",
+ "KPF4" => "VK_SUBTRACT",
+ "KPCO" => "VK_ADD",
+
+ "HELP" => "VK_HELP",
+ "SELE" => "VK_SELECT",
+
+ # We can ignore LDM (Lock Down Modifier)
+ # What are LCMP/RCMP?
+ # DO, FIND?
+
+);
+
+my $inDir;
+my $outDir;
+
+if(@ARGV < 1) {
+ $inDir = getcwd() . "/";
+ $outDir = $inDir;
+} elsif(@ARGV == 1) {
+ $inDir = $ARGV[0];
+ $outDir = getcwd() . "/";
+} elsif(@ARGV == 2) {
+ $inDir = $ARGV[0];
+ $outDir = $ARGV[1];
+} else {
+ print "Error: Too many arguments\n" .
+ "Usage:\n" .
+ "perl xkb.pl <XKB Directory>\n" .
+ "perl xkb.pl <XKB Directory> <Output Directory>\n\n" .
+ "In Linux, the XKB directory usually is /usr/share/X11/xkb/\n" .
+ "The latest version of XKB can always be downloaded at:\n" .
+ "http://freedesktop.org/wiki/Software/XKeyboardConfig\n";
+ exit 0;
+}
+
+
+
+open("SPEC", $inDir . "xkeyboard-config.spec");
+
+$xkbVersion = "";
+while($line = <SPEC>) {
+ if($line =~ m/Version:\s+(.\..)/) {
+ $xkbVersion = "version $1";
+ }
+}
+
+# Create directory if it does not exists
+if(not -e $outDir) {
+ mkdir $outDir or die("Error: Can't create directory $outDir\n");
+}
+
+open("KCD", $inDir . "keycodes/keycodes.dir") or die("Error: Can't open $inDir" . "keycodes/keycodes.dir\n");
+
+$previousFile = "";
+while($line = <KCD>) {
+ if($line =~ m/........ -------- (.+)\((.+)\)/) {
+ if($1 ne $previousFile) {
+ push(@keymapFiles, $1);
+ $previousFile = $1;
+ }
+ }
+}
+close("KCD");
+
+foreach $keymapFile (@keymapFiles) {
+
+ print "File $keymapFile:\n";
+
+ @directories = split(/\//, $keymapFile);
+ splice(@directories, @directories - 1, 1);
+
+ if(@directories > 0) {
+ $directory = $outDir;
+ for($i = 0; $i < @directories; $i++) {
+ $directory .= $directories[$i] . "/";
+ if(not -e $directory) {
+ mkdir $directory or die("Can't create directory $directory\n");
+ }
+ }
+ }
+
+ open("IN", $inDir . "keycodes/" . $keymapFile);
+ open("OUT", ">" . "$outDir" . $keymapFile);
+
+ print OUT "# This file was generated with xkb.pl\n";
+ print OUT "# and is based on the X Keyboard Configuration Database $xkbVersion\n";
+ print OUT "# Please use xkb.pl to re-export newer versions of XKB\n";
+ print OUT "\n\n";
+
+ while($line = <IN>) {
+ if($line =~ m/xkb_keycodes \"(\w+)\"/) {
+
+ print "Exporting \"$1\"\n";
+ print OUT "keyboard \"$1\"";
+
+
+ while($line = <IN>) {
+ if($line =~ m/include\W+\"(.+)\"/) {
+ print OUT "\n: extends \"$1\"";
+ last;
+ } else {
+ last;
+ }
+ }
+ print OUT "\n{\n";
+
+ while($line = <IN>) {
+ if($line =~ m/<(\w{1,4})>\W+=\W+(\w+);/) {
+ if($sym2virt{$1} ne undef) {
+ $vkcode = $sym2virt{$1};
+ print OUT "\t$vkcode";
+
+ if(length($vkcode) < 8) {
+ print OUT "\t";
+ }
+ print OUT "\t<$2>\n";
+ } else {
+ # If undef, then this symbolic key code is
+ # missing from the sym2virt hash table
+ # print "\t$1\t$2\n";
+ }
+ } elsif($line =~ m/};/) {
+ print OUT "};\n\n";
+ last;
+ }
+ }
+ }
+ }
+
+ close("IN");
+ close("OUT");
+}
+