Add new job to test building for UWP (aka `CURL_WINDOWS_APP`).
Fix fallouts when building for UWP:
- rand: do not use `BCryptGenRandom()`.
- cmake: disable using win32 LDAP.
- cmake: disable telnet.
- version_win32: fix code before declaration.
- schannel: disable `HAS_MANUAL_VERIFY_API`.
- schannel: disable `SSLSUPP_PINNEDPUBKEY`
and make `schannel_checksum()` a stub.
Ref:
e178fbd40a896f2098278ae61e1166c88e7b31d0 #1429
- schannel: make `cert_get_name_string()` a failing stub.
- system_win32: make `Curl_win32_impersonating()` a failing stub.
- system_win32: try to fix `Curl_win32_init()` (untested).
- threads: fix to use `CreateThread()`.
- src: disable searching `PATH` for the CA bundle.
- src: disable bold text support and capability detection.
- src: disable `getfiletime()`/`setfiletime()`.
- tests: make `win32_load_system_library()` a failing stub.
- tests/server/util: make it compile.
- tests/server/sockfilt: make it compile.
- tests/lib3026: fix to use `CreateThread()`.
See individual commits for build error details.
Some of these fixes may have better solutions, and some may not work
as expected. The goal of this patch is to make curl build for UWP.
Closes #13870
cmake --build bld --config '${{ matrix.type }}' --target test-ci
msys2:
- name: 'msys2 (${{ matrix.build }}, ${{ matrix.sys }}, ${{ matrix.env }}, ${{ matrix.config }})'
+ name: 'msys2 (${{ matrix.build }}, ${{ matrix.sys }}, ${{ matrix.env }}, ${{ matrix.config }}, ${{ matrix.test }})'
runs-on: windows-latest
timeout-minutes: 45
strategy:
- { build: 'cmake' , sys: 'mingw64', env: 'x86_64' , tflags: '~2301 ~2302' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON', type: 'Debug' }
- { build: 'cmake' , sys: 'ucrt64' , env: 'ucrt-x86_64' , tflags: 'skiprun' , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DENABLE_CURLDEBUG=ON', type: 'Release' }
- { build: 'cmake' , sys: 'clang64', env: 'clang-x86_64', tflags: 'skiprun' , config: '-DENABLE_DEBUG=ON -DBUILD_SHARED_LIBS=OFF -DCURL_USE_OPENSSL=ON -DENABLE_UNICODE=OFF', type: 'Release' }
+ - { build: 'cmake' , sys: 'mingw64', env: 'x86_64' , tflags: 'skiprun' , config: '-DENABLE_DEBUG=OFF -DBUILD_SHARED_LIBS=ON -DCURL_USE_SCHANNEL=ON -DENABLE_UNICODE=ON -DBUILD_EXAMPLES=OFF', type: 'Release', test: 'uwp' }
fail-fast: false
steps:
- run: git config --global core.autocrlf input
pacman --noconfirm --ask 20 --noprogressbar --sync --needed 'mingw-w64-${{ matrix.env }}-winstorecompat-git'
specs="$(realpath gcc-specs-uwp)"
gcc -dumpspecs | sed -e 's/-lmingwex/-lwindowsapp -lmingwex -lwindowsapp -lwindowsappcompat/' -e 's/-lmsvcrt/-lmsvcr120_app/' > "${specs}"
- cflags+=" -specs=${specs} -DWINSTORECOMPAT -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
+ cflags+=" -specs=$(cygpath -w "${specs}") -DWINSTORECOMPAT -DWINAPI_FAMILY=WINAPI_FAMILY_APP"
# CMake (as of v3.26.4) gets confused and applies the MSVC rc.exe command-line
# template to windres. Reset it to the windres template manually:
rcopts='<CMAKE_RC_COMPILER> -O coff <DEFINES> <INCLUDES> <FLAGS> <SOURCE> <OBJECT>'
cmake --build bld --config '${{ matrix.type }}' --parallel 5
[[ '${{ matrix.config }}' != *'BUILD_SHARED_LIBS=OFF'* ]] && cp -f -p bld/lib/*.dll bld/src/
find . -name '*.exe' -o -name '*.dll'
- bld/src/curl.exe --disable --version
+ if [ '${{ matrix.test }}' != 'uwp' ]; then # UWP missing 'msvcr120_app.dll', fails with exit code 0xc0000135
+ bld/src/curl.exe --disable --version
+ fi
- name: 'cmake build tests'
if: ${{ matrix.build == 'cmake' && matrix.tflags != 'skipall' }}
set(CURL_DISABLE_TFTP ON)
endif()
+if(WINDOWS_STORE)
+ set(CURL_DISABLE_TELNET ON) # telnet code needs fixing to compile for UWP.
+endif()
+
option(ENABLE_IPV6 "Define if you want to enable IPv6 support" ON)
mark_as_advanced(ENABLE_IPV6)
if(ENABLE_IPV6 AND NOT WIN32)
endif()
if(NOT CURL_DISABLE_LDAP)
- if(WIN32)
+ if(WIN32 AND NOT WINDOWS_STORE)
option(USE_WIN32_LDAP "Use Windows LDAP implementation" ON)
if(USE_WIN32_LDAP)
list(APPEND CURL_LIBS "wldap32")
* and wait on it.
*/
static
-#if defined(_WIN32_WCE)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
DWORD
#else
unsigned int
* gethostbyname_thread() resolves a name and then exits.
*/
static
-#if defined(_WIN32_WCE)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
DWORD
#else
unsigned int
#elif defined(USE_THREADS_WIN32)
curl_thread_t Curl_thread_create(
-#if defined(_WIN32_WCE)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
DWORD
#else
unsigned int
(CURL_STDCALL *func) (void *),
void *arg)
{
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
typedef HANDLE curl_win_thread_handle_t;
#else
typedef uintptr_t curl_win_thread_handle_t;
#endif
curl_thread_t t;
curl_win_thread_handle_t thread_handle;
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
thread_handle = CreateThread(NULL, 0, func, arg, 0, NULL);
#else
thread_handle = _beginthreadex(NULL, 0, func, arg, 0, NULL);
#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32)
curl_thread_t Curl_thread_create(
-#if defined(_WIN32_WCE)
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
DWORD
#else
unsigned int
#ifdef _WIN32
-#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600
+#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x600 && \
+ !defined(CURL_WINDOWS_APP)
# define HAVE_WIN_BCRYPTGENRANDOM
# include <bcrypt.h>
# ifdef _MSC_VER
}
#ifdef USE_WINSOCK
+#ifdef CURL_WINDOWS_APP
+ ws2_32Dll = Curl_load_library(TEXT("ws2_32.dll"));
+#else
ws2_32Dll = GetModuleHandleA("ws2_32");
+#endif
if(ws2_32Dll) {
Curl_FreeAddrInfoExW = CURLX_FUNCTION_CAST(FREEADDRINFOEXW_FN,
GetProcAddress(ws2_32Dll, "FreeAddrInfoExW"));
bool Curl_win32_impersonating(void)
{
+#ifndef CURL_WINDOWS_APP
HANDLE token = NULL;
if(OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &token)) {
CloseHandle(token);
return TRUE;
}
+#endif
return FALSE;
}
bool matched = FALSE;
#if defined(CURL_WINDOWS_APP)
- (void)buildVersion;
-
/* We have no way to determine the Windows version from Windows apps,
so let's assume we're running on the target Windows version. */
const WORD fullVersion = MAKEWORD(minorVersion, majorVersion);
const WORD targetVersion = (WORD)_WIN32_WINNT;
+ (void)buildVersion;
+
switch(condition) {
case VERSION_LESS_THAN:
matched = targetVersion < fullVersion;
DWORD provType,
const unsigned int algId)
{
+#ifdef CURL_WINDOWS_APP
+ (void)input;
+ (void)inputlen;
+ (void)provType;
+ (void)algId;
+ memset(checksum, 0, checksumlen);
+#else
HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;
DWORD cbHashSize = 0;
if(hProv)
CryptReleaseContext(hProv, 0);
+#endif
}
static CURLcode schannel_sha256sum(const unsigned char *input,
#ifdef HAS_MANUAL_VERIFY_API
SSLSUPP_CAINFO_BLOB |
#endif
+#ifndef CURL_WINDOWS_APP
SSLSUPP_PINNEDPUBKEY |
+#endif
SSLSUPP_TLS13_CIPHERSUITES |
SSLSUPP_CA_CACHE |
SSLSUPP_HTTPS_PROXY,
#ifdef USE_SCHANNEL
-#if defined(__MINGW32__) || defined(CERT_CHAIN_REVOCATION_CHECK_CHAIN)
+#if (defined(__MINGW32__) || defined(CERT_CHAIN_REVOCATION_CHECK_CHAIN)) \
+ && !defined(CURL_WINDOWS_APP)
#define HAS_MANUAL_VERIFY_API
#endif
DWORD length)
{
DWORD actual_length = 0;
+#if defined(CURL_WINDOWS_APP)
+ (void)data;
+ (void)cert_context;
+ (void)host_names;
+ (void)length;
+#else
BOOL compute_content = FALSE;
CERT_INFO *cert_info = NULL;
CERT_EXTENSION *extension = NULL;
/* Last string has double null-terminator. */
*current_pos = '\0';
}
+#endif
return actual_length;
}
struct winsize ts;
if(!ioctl(STDIN_FILENO, TIOCGWINSZ, &ts))
cols = (int)ts.ws_col;
-#elif defined(_WIN32)
+#elif defined(_WIN32) && !defined(CURL_WINDOWS_APP)
{
HANDLE stderr_hnd = GetStdHandle(STD_ERROR_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO console_info;
{
CURLcode result = CURLE_OK;
+#ifdef CURL_WINDOWS_APP
+ (void)config;
+ (void)backend;
+ (void)bundle_file;
+#else
/* Search and set cert file only if libcurl supports SSL.
*
* If Schannel is the selected SSL backend then these locations are
result = CURLE_OUT_OF_MEMORY;
}
}
+#endif
return result;
}
return slist;
}
+bool tool_term_has_bold;
+
+#ifndef CURL_WINDOWS_APP
/* The terminal settings to restore on exit */
static struct TerminalSettings {
HANDLE hStdOut;
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
-bool tool_term_has_bold;
-
static void restore_terminal(void)
{
if(InterlockedExchange(&TerminalSettings.valid, (LONG)FALSE))
}
}
}
+#endif
LARGE_INTEGER tool_freq;
bool tool_isVistaOrGreater;
QueryPerformanceFrequency(&tool_freq);
+#ifndef CURL_WINDOWS_APP
init_terminal();
+#endif
return CURLE_OK;
}
/* Windows stat() may attempt to adjust the unix GMT file time by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass stat and get the times directly. */
-#if defined(_WIN32)
+#if defined(_WIN32) && !defined(CURL_WINDOWS_APP)
HANDLE hfile;
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
/* Windows utime() may attempt to adjust the unix GMT file time by a daylight
saving time offset and since it's GMT that is bad behavior. When we have
access to a 64-bit type we can bypass utime and set the times directly. */
-#if defined(_WIN32)
+#if defined(_WIN32) && !defined(CURL_WINDOWS_APP)
HANDLE hfile;
TCHAR *tchar_filename = curlx_convert_UTF8_to_tchar((char *)filename);
#define NUM_THREADS 100
#ifdef _WIN32
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
static DWORD WINAPI run_thread(LPVOID ptr)
#else
#include <process.h>
CURLcode test(char *URL)
{
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
typedef HANDLE curl_win_thread_handle_t;
#else
typedef uintptr_t curl_win_thread_handle_t;
for(i = 0; i < tid_count; i++) {
curl_win_thread_handle_t th;
results[i] = CURL_LAST; /* initialize with invalid value */
-#ifdef _WIN32_WCE
+#if defined(_WIN32_WCE) || defined(CURL_WINDOWS_APP)
th = CreateThread(NULL, 0, run_thread, &results[i], 0, NULL);
#else
th = _beginthreadex(NULL, 0, run_thread, &results[i], 0, NULL);
#ifdef _WIN32
HMODULE win32_load_system_library(const TCHAR *filename)
{
+#ifdef CURL_WINDOWS_APP
+ (void)filename;
+ return NULL;
+#else
size_t filenamelen = _tcslen(filename);
size_t systemdirlen = GetSystemDirectory(NULL, 0);
size_t written;
_tcscpy(path + written, filename);
return LoadLibrary(path);
+#endif
}
#endif
ACTIVE_DISCONNECT /* as a client, disconnected from server */
};
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(CURL_WINDOWS_APP)
/*
* read-wrapper to support reading from stdin on Windows.
*/
}
-#ifdef USE_WINSOCK
+#if defined(USE_WINSOCK) && !defined(CURL_WINDOWS_APP)
/*
* WinSock select() does not support standard file descriptors,
* it can only check SOCKETs. The following function is an attempt
static SIGHANDLER_T old_sigbreak_handler = SIG_ERR;
#endif
-#ifdef _WIN32
+#if defined(_WIN32) && !defined(CURL_WINDOWS_APP)
#ifdef _WIN32_WCE
static DWORD thread_main_id = 0;
#else
}
return TRUE;
}
+#endif
+
+#if defined(_WIN32) && !defined(CURL_WINDOWS_APP)
/* Window message handler for Windows applications to add support
* for graceful process termination via taskkill (without /f) which
* sends WM_CLOSE to all Windows of a process (even hidden ones).
void install_signal_handlers(bool keep_sigalrm)
{
#ifdef _WIN32
-#ifdef _WIN32_WCE
- typedef HANDLE curl_win_thread_handle_t;
-#else
- typedef uintptr_t curl_win_thread_handle_t;
-#endif
- curl_win_thread_handle_t thread;
/* setup windows exit event before any signal can trigger */
exit_event = CreateEvent(NULL, TRUE, FALSE, NULL);
if(!exit_event)
#ifdef _WIN32
if(!SetConsoleCtrlHandler(ctrl_event_handler, TRUE))
logmsg("cannot install CTRL event handler");
+
+#ifndef CURL_WINDOWS_APP
+ {
#ifdef _WIN32_WCE
- thread = CreateThread(NULL, 0, &main_window_loop,
- (LPVOID)GetModuleHandle(NULL), 0, &thread_main_id);
+ typedef HANDLE curl_win_thread_handle_t;
#else
- thread = _beginthreadex(NULL, 0, &main_window_loop,
- (void *)GetModuleHandle(NULL), 0, &thread_main_id);
+ typedef uintptr_t curl_win_thread_handle_t;
+#endif
+ curl_win_thread_handle_t thread;
+#ifdef _WIN32_WCE
+ thread = CreateThread(NULL, 0, &main_window_loop,
+ (LPVOID)GetModuleHandle(NULL), 0, &thread_main_id);
+#else
+ thread = _beginthreadex(NULL, 0, &main_window_loop,
+ (void *)GetModuleHandle(NULL), 0, &thread_main_id);
+#endif
+ thread_main_window = (HANDLE)thread;
+ if(!thread_main_window || !thread_main_id)
+ logmsg("cannot start main window loop");
+ }
#endif
- thread_main_window = (HANDLE)thread;
- if(!thread_main_window || !thread_main_id)
- logmsg("cannot start main window loop");
#endif
}
#endif
#ifdef _WIN32
(void)SetConsoleCtrlHandler(ctrl_event_handler, FALSE);
+#ifndef CURL_WINDOWS_APP
if(thread_main_window && thread_main_id) {
if(PostThreadMessage(thread_main_id, WM_APP, 0, 0)) {
if(WaitForSingleObjectEx(thread_main_window, INFINITE, TRUE)) {
}
}
#endif
+#endif
}
#ifdef USE_UNIX_SOCKETS