From 4c227c0e0de6568446e61194e8aed1e6711b7dc7 Mon Sep 17 00:00:00 2001 From: GGRei Date: Fri, 24 Jul 2026 02:29:48 +0200 Subject: [PATCH] windows: restore CreateSymbolicLink declarations and conformance coverage --- .github/workflows/build-and-test.yml | 39 ++++++++++++++ 0003-win32-declare-CreateSymbolicLink.patch | 56 +++++++++++++++++++++ build.ps1 | 3 ++ include/winapi/winbase.h | 8 +++ lib/kernel32.def | 1 + tests/winapi_create_symbolic_link.c | 15 ++++++ 6 files changed, 122 insertions(+) create mode 100644 0003-win32-declare-CreateSymbolicLink.patch create mode 100644 tests/winapi_create_symbolic_link.c diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 4272752..bc56ec4 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -57,6 +57,45 @@ jobs: shell: pwsh run: work/thirdparty/tcc/build.ps1 + - name: validate WinAPI declarations with x64 and i386 TCC + shell: pwsh + run: | + $probe = "work/thirdparty/tcc/tests/winapi_create_symbolic_link.c" + $x64Ansi = "$env:RUNNER_TEMP/winapi_create_symbolic_link_x64_ansi.exe" + $x64Unicode = "$env:RUNNER_TEMP/winapi_create_symbolic_link_x64_unicode.exe" + $i386Ansi = "$env:RUNNER_TEMP/winapi_create_symbolic_link_i386_ansi.exe" + $i386Unicode = "$env:RUNNER_TEMP/winapi_create_symbolic_link_i386_unicode.exe" + + & work/thirdparty/tcc/tcc.exe ` + -Werror=implicit-function-declaration ` + -o $x64Ansi $probe + if ($LASTEXITCODE -ne 0) { + throw "x64 ANSI WinAPI conformance probe failed" + } + + & work/thirdparty/tcc/tcc.exe ` + -Werror=implicit-function-declaration ` + -DUNICODE -D_UNICODE ` + -o $x64Unicode $probe + if ($LASTEXITCODE -ne 0) { + throw "x64 Unicode WinAPI conformance probe failed" + } + + & work/thirdparty/tcc/i386-win32-tcc.exe ` + -Werror=implicit-function-declaration ` + -o $i386Ansi $probe + if ($LASTEXITCODE -ne 0) { + throw "i386 ANSI WinAPI conformance probe failed" + } + + & work/thirdparty/tcc/i386-win32-tcc.exe ` + -Werror=implicit-function-declaration ` + -DUNICODE -D_UNICODE ` + -o $i386Unicode $probe + if ($LASTEXITCODE -ne 0) { + throw "i386 Unicode WinAPI conformance probe failed" + } + - name: run shared conformance tests shell: pwsh run: | diff --git a/0003-win32-declare-CreateSymbolicLink.patch b/0003-win32-declare-CreateSymbolicLink.patch new file mode 100644 index 0000000..0ac8f55 --- /dev/null +++ b/0003-win32-declare-CreateSymbolicLink.patch @@ -0,0 +1,56 @@ +win32: declare and export CreateSymbolicLink APIs + +CreateSymbolicLinkA/W and their flags are part of the Windows API from +_WIN32_WINNT 0x0600 onward. Add the missing declarations to winbase.h so +strict implicit-function-declaration diagnostics retain the correct Windows +calling convention, including on i386. Add the standard UNICODE/ANSI alias +beside CreateHardLink, and add the missing ANSI entry to kernel32.def so both +declared variants can be linked. + +diff --git a/win32/include/winapi/winbase.h b/win32/include/winapi/winbase.h +--- a/win32/include/winapi/winbase.h ++++ b/win32/include/winapi/winbase.h +@@ -2252,7 +2252,8 @@ + #define MoveFileEx MoveFileExW + #define MoveFileWithProgress MoveFileWithProgressW + #define ReplaceFile ReplaceFileW + #define CreateHardLink CreateHardLinkW ++#define CreateSymbolicLink CreateSymbolicLinkW + #define CreateNamedPipe CreateNamedPipeW + #define GetNamedPipeHandleState GetNamedPipeHandleStateW + #define CallNamedPipe CallNamedPipeW +@@ -2306,7 +2307,8 @@ + #define MoveFileEx MoveFileExA + #define MoveFileWithProgress MoveFileWithProgressA + #define ReplaceFile ReplaceFileA + #define CreateHardLink CreateHardLinkA ++#define CreateSymbolicLink CreateSymbolicLinkA + #define CreateNamedPipe CreateNamedPipeA + #define GetNamedPipeHandleState GetNamedPipeHandleStateA + #define CallNamedPipe CallNamedPipeA +@@ -2384,6 +2386,12 @@ + WINBASEAPI WINBOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName,LPCWSTR lpBackupFileName,DWORD dwReplaceFlags,LPVOID lpExclude,LPVOID lpReserved); + WINBASEAPI WINBOOL WINAPI CreateHardLinkA(LPCSTR lpFileName,LPCSTR lpExistingFileName,LPSECURITY_ATTRIBUTES lpSecurityAttributes); + WINBASEAPI WINBOOL WINAPI CreateHardLinkW(LPCWSTR lpFileName,LPCWSTR lpExistingFileName,LPSECURITY_ATTRIBUTES lpSecurityAttributes); +- ++#if _WIN32_WINNT >= 0x0600 ++#define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 ++#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2 ++ WINBASEAPI BOOLEAN WINAPI CreateSymbolicLinkA(LPCSTR lpSymlinkFileName,LPCSTR lpTargetFileName,DWORD dwFlags); ++ WINBASEAPI BOOLEAN WINAPI CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName,LPCWSTR lpTargetFileName,DWORD dwFlags); ++#endif ++ + typedef enum _STREAM_INFO_LEVELS { + FindStreamInfoStandard,FindStreamInfoMaxInfoLevel + +diff --git a/win32/lib/kernel32.def b/win32/lib/kernel32.def +--- a/win32/lib/kernel32.def ++++ b/win32/lib/kernel32.def +@@ -87,5 +87,7 @@ CreateRemoteThread + CreateSemaphoreA + CreateSemaphoreW + CreateSocketHandle ++CreateSymbolicLinkA ++CreateSymbolicLinkW + CreateTapePartition + CreateThread diff --git a/build.ps1 b/build.ps1 index 4ed500e..4be0c74 100644 --- a/build.ps1 +++ b/build.ps1 @@ -24,6 +24,7 @@ if (-not (Test-Path (Join-Path $RepoRoot "vlib\v\compiler_errors_test.v"))) { $TccBaseCommit = "d9d02c56401e43be43760b63f7d82f771a7ed1f6" $TccPatch1 = Join-Path $PSScriptRoot "0001-tccpe-strip-quotes-and-default-.dll-extension-in-DEF.patch" $TccPatch2 = Join-Path $PSScriptRoot "0002-win32-don-t-treat-DBG_PRINTEXCEPTION_C-as-a-fatal-cr.patch" +$TccPatch3 = Join-Path $PSScriptRoot "0003-win32-declare-CreateSymbolicLink.patch" $GcPatch = Join-Path $PSScriptRoot "v-ae88ee5-tinycc-bdwgc.patch" $OutDir = $PSScriptRoot @@ -41,6 +42,8 @@ try { if ($LASTEXITCODE -ne 0) { throw "$TccPatch1 failed to apply" } git apply $TccPatch2 if ($LASTEXITCODE -ne 0) { throw "$TccPatch2 failed to apply" } + git apply $TccPatch3 + if ($LASTEXITCODE -ne 0) { throw "$TccPatch3 failed to apply" } Set-Location win32 & .\build-tcc.bat -clean diff --git a/include/winapi/winbase.h b/include/winapi/winbase.h index da3e17e..0cc2538 100644 --- a/include/winapi/winbase.h +++ b/include/winapi/winbase.h @@ -2253,6 +2253,7 @@ extern "C" { #define MoveFileWithProgress MoveFileWithProgressW #define ReplaceFile ReplaceFileW #define CreateHardLink CreateHardLinkW +#define CreateSymbolicLink CreateSymbolicLinkW #define CreateNamedPipe CreateNamedPipeW #define GetNamedPipeHandleState GetNamedPipeHandleStateW #define CallNamedPipe CallNamedPipeW @@ -2307,6 +2308,7 @@ extern "C" { #define MoveFileWithProgress MoveFileWithProgressA #define ReplaceFile ReplaceFileA #define CreateHardLink CreateHardLinkA +#define CreateSymbolicLink CreateSymbolicLinkA #define CreateNamedPipe CreateNamedPipeA #define GetNamedPipeHandleState GetNamedPipeHandleStateA #define CallNamedPipe CallNamedPipeA @@ -2384,6 +2386,12 @@ extern "C" { WINBASEAPI WINBOOL WINAPI ReplaceFileW(LPCWSTR lpReplacedFileName,LPCWSTR lpReplacementFileName,LPCWSTR lpBackupFileName,DWORD dwReplaceFlags,LPVOID lpExclude,LPVOID lpReserved); WINBASEAPI WINBOOL WINAPI CreateHardLinkA(LPCSTR lpFileName,LPCSTR lpExistingFileName,LPSECURITY_ATTRIBUTES lpSecurityAttributes); WINBASEAPI WINBOOL WINAPI CreateHardLinkW(LPCWSTR lpFileName,LPCWSTR lpExistingFileName,LPSECURITY_ATTRIBUTES lpSecurityAttributes); +#if _WIN32_WINNT >= 0x0600 +#define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1 +#define SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE 0x2 + WINBASEAPI BOOLEAN WINAPI CreateSymbolicLinkA(LPCSTR lpSymlinkFileName,LPCSTR lpTargetFileName,DWORD dwFlags); + WINBASEAPI BOOLEAN WINAPI CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName,LPCWSTR lpTargetFileName,DWORD dwFlags); +#endif typedef enum _STREAM_INFO_LEVELS { FindStreamInfoStandard,FindStreamInfoMaxInfoLevel diff --git a/lib/kernel32.def b/lib/kernel32.def index d3212be..611fc6d 100644 --- a/lib/kernel32.def +++ b/lib/kernel32.def @@ -90,6 +90,7 @@ CreateRemoteThread CreateSemaphoreA CreateSemaphoreW CreateSocketHandle +CreateSymbolicLinkA CreateSymbolicLinkW CreateTapePartition CreateThread diff --git a/tests/winapi_create_symbolic_link.c b/tests/winapi_create_symbolic_link.c new file mode 100644 index 0000000..8eadeb3 --- /dev/null +++ b/tests/winapi_create_symbolic_link.c @@ -0,0 +1,15 @@ +#define WINVER 0x0600 +#define _WIN32_WINNT 0x0600 +#include +#include + +int main(void) +{ + DWORD flags = SYMBOLIC_LINK_FLAG_DIRECTORY | + SYMBOLIC_LINK_FLAG_ALLOW_UNPRIVILEGED_CREATE; + (void)CreateSymbolicLinkA("tccbin-probe-link-a", "tccbin-probe-target-a", flags); + (void)CreateSymbolicLinkW(L"tccbin-probe-link-w", L"tccbin-probe-target-w", flags); + (void)CreateSymbolicLink(TEXT("tccbin-probe-link"), + _T("tccbin-probe-target"), flags); + return 0; +}