From 84b2226f6910687a961bf45c2f8d8d4f8f4a5502 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Sep 2025 19:59:18 +0200 Subject: [PATCH 1/4] fix(windows.subsystem rule) use Xlinker instead of -Wl when using clang to allow pass the system version --- xmake/rules/platform/windows/subsystem/xmake.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xmake/rules/platform/windows/subsystem/xmake.lua b/xmake/rules/platform/windows/subsystem/xmake.lua index 6ee96324ac..2f580e4e1b 100644 --- a/xmake/rules/platform/windows/subsystem/xmake.lua +++ b/xmake/rules/platform/windows/subsystem/xmake.lua @@ -39,7 +39,7 @@ rule("platform.windows.subsystem") assert(valid, "Invalid subsystem " .. subsystem) if target:has_tool("ld", "clang", "clangxx", "clang_cl") then - target:add("ldflags", "-Wl,-subsystem:" .. subsystem, { force = true }) + target:add("ldflags", "-Xlinker", "-subsystem:" .. subsystem, { force = true }) elseif target:has_tool("ld", "link", "lld-link") then target:add("ldflags", "/SUBSYSTEM:" .. subsystem:upper(), { force = true }) elseif target:has_tool("ld", "gcc", "gxx") then From c6bccc83599b6b48a22ee34be70b9a84cdbb70ce Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Sep 2025 20:00:20 +0200 Subject: [PATCH 2/4] nfc(wdk rule) simplify wdk/env/load.lua --- xmake/rules/wdk/env/load.lua | 78 +++++++++--------------------------- 1 file changed, 20 insertions(+), 58 deletions(-) diff --git a/xmake/rules/wdk/env/load.lua b/xmake/rules/wdk/env/load.lua index 3e9681e61b..962eeb6167 100644 --- a/xmake/rules/wdk/env/load.lua +++ b/xmake/rules/wdk/env/load.lua @@ -38,8 +38,7 @@ function _winver_libdir(winver) return vervals[winver] end --- load for umdf environment -function umdf(target) +function _base(target, mode) -- get wdk local wdk = target:data("wdk") @@ -48,7 +47,8 @@ function umdf(target) local arch = config.arch() -- add definitions - local umdfver = wdk.umdfver:split('%.') + local ver = mode == "um" and wdk.umdfver or wdk.kmdfver + local ver_split = ver:split('%.') if arch == "x64" then target:add("defines", "_WIN64", "_AMD64_", "AMD64") else @@ -57,16 +57,24 @@ function umdf(target) target:add("defines", "STD_CALL") target:add("cxflags", "-Gz", {force = true}) end - target:add("defines", "UMDF_VERSION_MAJOR=" .. umdfver[1], "UMDF_VERSION_MINOR=" .. umdfver[2], "UMDF_USING_NTSTATUS") + + local prefix = mode == "um" and "UM" or "KM" + target:add("defines", prefix .. "DF_VERSION_MAJOR=" .. ver_split[1], prefix .. "DF_VERSION_MINOR=" .. ver_split[2], prefix .. "DF_USING_NTSTATUS") target:add("defines", "WIN32_LEAN_AND_MEAN=1", "WINNT=1", "_WINDLL") -- add include directories - target:add("includedirs", path.join(wdk.includedir, wdk.sdkver, "um")) - target:add("includedirs", path.join(wdk.includedir, "wdf", "umdf", wdk.umdfver)) + target:add("sysincludedirs", path.join(wdk.includedir, wdk.sdkver, mode)) + target:add("sysincludedirs", path.join(wdk.includedir, "wdf", mode .. "df", ver)) -- add link directories - target:add("linkdirs", path.join(wdk.libdir, wdk.sdkver, "um", arch)) - target:add("linkdirs", path.join(wdk.libdir, "wdf", "umdf", arch, wdk.umdfver)) + target:add("linkdirs", path.join(wdk.libdir, wdk.sdkver, mode, arch)) + target:add("linkdirs", path.join(wdk.libdir, "wdf", mode .. "df", arch, ver)) +end + +-- load for umdf environment +function umdf(target) + + _base(target, "um") end -- load for kmdf environment @@ -80,69 +88,23 @@ function kmdf(target) -- add definitions local winver = target:values("wdk.env.winver") or config.get("wdk_winver") - local kmdfver = wdk.kmdfver:split('%.') - if arch == "x64" then - target:add("defines", "_WIN64", "_AMD64_", "AMD64") - else - target:add("defines", "_X86_=1", "i386=1") - target:add("defines", "DEPRECATE_DDK_FUNCTIONS=1", "MSC_NOOPT", "_ATL_NO_WIN_SUPPORT") - target:add("defines", "STD_CALL") - target:add("cxflags", "-Gz", {force = true}) - end - target:add("defines", "KMDF_VERSION_MAJOR=" .. kmdfver[1], "KMDF_VERSION_MINOR=" .. kmdfver[2], "KMDF_USING_NTSTATUS") - target:add("defines", "WIN32_LEAN_AND_MEAN=1", "WINNT=1", "_WINDLL") + + _base(target, "km") -- add include directories - target:add("includedirs", path.join(wdk.includedir, wdk.sdkver, "km")) if target:rule("wdk.driver") then - target:add("includedirs", path.join(wdk.includedir, wdk.sdkver, "km", "crt")) + target:add("sysincludedirs", path.join(wdk.includedir, wdk.sdkver, "km", "crt")) end - target:add("includedirs", path.join(wdk.includedir, "wdf", "kmdf", wdk.kmdfver)) -- add link directories local libdirver = _winver_libdir(winver) if libdirver then target:add("linkdirs", path.join(wdk.libdir, libdirver, "km", arch)) end - target:add("linkdirs", path.join(wdk.libdir, wdk.sdkver, "km", arch)) - target:add("linkdirs", path.join(wdk.libdir, "wdf", "kmdf", arch, wdk.kmdfver)) end -- load for wdm environment function wdm(target) - -- get wdk - local wdk = target:data("wdk") - - -- get arch - local arch = config.arch() - - -- add definitions - local winver = target:values("wdk.env.winver") or config.get("wdk_winver") - local kmdfver = wdk.kmdfver:split('%.') - if arch == "x64" then - target:add("defines", "_WIN64", "_AMD64_", "AMD64") - else - target:add("defines", "_X86_=1", "i386=1") - target:add("defines", "DEPRECATE_DDK_FUNCTIONS=1", "MSC_NOOPT", "_ATL_NO_WIN_SUPPORT") - target:add("defines", "STD_CALL") - target:add("cxflags", "-Gz", {force = true}) - end - target:add("defines", "KMDF_VERSION_MAJOR=" .. kmdfver[1], "KMDF_VERSION_MINOR=" .. kmdfver[2], "KMDF_USING_NTSTATUS") - target:add("defines", "WIN32_LEAN_AND_MEAN=1", "WINNT=1", "_WINDLL") - - -- add include directories - target:add("includedirs", path.join(wdk.includedir, wdk.sdkver, "km")) - if target:rule("wdk.driver") then - target:add("includedirs", path.join(wdk.includedir, wdk.sdkver, "km", "crt")) - end - target:add("includedirs", path.join(wdk.includedir, "wdf", "kmdf", wdk.kmdfver)) - - -- add link directories - local libdirver = _winver_libdir(winver) - if libdirver then - target:add("linkdirs", path.join(wdk.libdir, libdirver, "km", arch)) - end - target:add("linkdirs", path.join(wdk.libdir, wdk.sdkver, "km", arch)) - target:add("linkdirs", path.join(wdk.libdir, "wdf", "kmdf", arch, wdk.kmdfver)) + kmdf(target) end From 0ca151ca12093530d8770929a5e236da55d7693c Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Tue, 9 Sep 2025 21:38:20 +0200 Subject: [PATCH 3/4] feat(wdk rules) support clang / llvm toolchains --- xmake/rules/wdk/env/load.lua | 5 +- xmake/rules/wdk/load.lua | 101 +++++++++++++++++----------------- xmake/rules/wdk/man/xmake.lua | 7 +++ xmake/rules/wdk/xmake.lua | 4 +- 4 files changed, 63 insertions(+), 54 deletions(-) diff --git a/xmake/rules/wdk/env/load.lua b/xmake/rules/wdk/env/load.lua index 962eeb6167..fa682c207a 100644 --- a/xmake/rules/wdk/env/load.lua +++ b/xmake/rules/wdk/env/load.lua @@ -68,7 +68,10 @@ function _base(target, mode) -- add link directories target:add("linkdirs", path.join(wdk.libdir, wdk.sdkver, mode, arch)) - target:add("linkdirs", path.join(wdk.libdir, "wdf", mode .. "df", arch, ver)) + local p = path.join(wdk.libdir, "wdf", mode .. "df", arch, ver) + if os.isdir(p) then + target:add("linkdirs", p) + end end -- load for umdf environment diff --git a/xmake/rules/wdk/load.lua b/xmake/rules/wdk/load.lua index 9886d45e07..637ea9f80f 100644 --- a/xmake/rules/wdk/load.lua +++ b/xmake/rules/wdk/load.lua @@ -20,8 +20,29 @@ -- imports import("core.project.config") +import("core.base.semver") import("os.winver", {alias = "os_winver"}) +function _add_linkflags(target, t, ...) + local args = table.pack(...) + if target:has_tool("ld", "clang", "clangxx") then + for i, flag in ipairs(args) do + if type(flag) == "string" then + args[i] = "-Wl," .. flag + end + end + end + target:add(t, table.unpack(args)) +end + +function _add_ldflags(target, ...) + _add_linkflags(target, "ldflags", ...) +end + +function _add_shflags(target, ...) + _add_linkflags(target, "shflags", ...) +end + -- load for umdf driver function driver_umdf(target) @@ -30,10 +51,10 @@ function driver_umdf(target) -- add links target:add("links", "ntdll", "OneCoreUAP", "mincore", "ucrt") - target:add("shflags", "-NODEFAULTLIB:kernel32.lib", "-NODEFAULTLIB:user32.lib", "-NODEFAULTLIB:libucrt.lib", {force = true}) + + _add_shflags(target, "-NODEFAULTLIB:kernel32.lib", "-NODEFAULTLIB:user32.lib", "-NODEFAULTLIB:libucrt.lib", {force = true}) -- add subsystem - local winver = target:values("wdk.env.winver") or config.get("wdk_winver") if not target:values("windows.subsystem") then target:values_set("windows.subsystem", "windows," .. os_winver.subsystem(winver)) end @@ -47,13 +68,15 @@ function driver_umdf(target) break end end - if not entry then + + -- get wdk + local wdk = target:data("wdk") + if not entry and semver.compare(wdk.umdfver, "2.0") >= 0 then target:add("links", "WdfDriverStubUm") end end --- load for kmdf driver -function driver_kmdf(target) +function _kernel_driver_base(target, default_entrypoint) -- set kind target:set("kind", "binary") @@ -68,12 +91,17 @@ function driver_kmdf(target) else target:add("links", "BufferOverflowK") end - target:add("links", "ntoskrnl", "hal", "wmilib", "WdfLdr", "ntstrsafe", "wdmsec") -- compile as kernel driver - target:add("cxflags", "-kernel", {force = true}) - target:add("ldflags", "-kernel", "-driver", {force = true}) - target:add("ldflags", "-nodefaultlib", {force = true}) + if not target:has_tool("cc", "clang", "clangxx") then + target:add("cxflags", "-kernel", {force = true}) + else + -- emulate kernel mode https://learn.microsoft.com/en-us/cpp/build/reference/kernel-create-kernel-mode-binary?view=msvc-170 + target:add("cxxflags", "-fno-exceptions", "-fno-rtti") + target:add("defines", "_KERNEL_MODE=1") + end + + _add_ldflags(target, "-kernel", "-driver", "-nodefaultlib", {force = true}) -- add subsystem if not target:values("windows.subsystem") then @@ -81,63 +109,34 @@ function driver_kmdf(target) end -- set default driver entry if does not exist - local entry = false + local has_entry = false for _, ldflag in ipairs(target:get("ldflags")) do if type(ldflag) == "string" then ldflag = ldflag:lower() if ldflag:find("[/%-]entry:") then - entry = true + has_entry = true break end end end - if not entry then - target:add("links", "WdfDriverEntry") - target:add("ldflags", "-entry:FxDriverEntry" .. (is_arch("x86") and "@8" or ""), {force = true}) + if not has_entry then + local arch = (target:is_arch("x86") and "@8" or "") target:add("links", "WdfDriverEntry") + _add_ldflags(target, "-entry:" .. default_entrypoint .. arch, {force = true}) end end --- load for wdm driver -function driver_wdm(target) +-- load for kmdf driver +function driver_kmdf(target) - -- set kind - target:set("kind", "binary") + target:add("links", "ntoskrnl", "hal", "wmilib", "WdfLdr", "ntstrsafe", "wdmsec") - -- set filename: xxx.sys - target:set("filename", target:basename() .. ".sys") + _kernel_driver_base(target, "FxDriverEntry") +end - -- add links - local winver = target:values("wdk.env.winver") or config.get("wdk_winver") - if winver and os_winver.version(winver) >= os_winver.version("win8") then - target:add("links", "BufferOverflowFastFailK") - else - target:add("links", "BufferOverflowK") - end +-- load for wdm driver +function driver_wdm(target) target:add("links", "ntoskrnl", "hal", "wmilib", "ntstrsafe") - -- compile as kernel driver - target:add("cxflags", "-kernel", {force = true}) - target:add("ldflags", "-kernel", "-driver", {force = true}) - target:add("ldflags", "-nodefaultlib", {force = true}) - - -- add subsystem - if not target:values("windows.subsystem") then - target:values_set("windows.subsystem", "native," .. os_winver.subsystem(winver)) - end - - -- set default driver entry if does not exist - local entry = false - for _, ldflag in ipairs(target:get("ldflags")) do - if type(ldflag) == "string" then - ldflag = ldflag:lower() - if ldflag:find("[/%-]entry:") then - entry = true - break - end - end - end - if not entry then - target:add("ldflags", "-entry:GsDriverEntry" .. (is_arch("x86") and "@8" or ""), {force = true}) - end + _kernel_driver_base(target, "GsDriverEntry") end diff --git a/xmake/rules/wdk/man/xmake.lua b/xmake/rules/wdk/man/xmake.lua index 53063cc49e..ab817ae6e1 100644 --- a/xmake/rules/wdk/man/xmake.lua +++ b/xmake/rules/wdk/man/xmake.lua @@ -124,6 +124,13 @@ rule("wdk.man") end os.vrunv(ctrpp, args) + if target:has_tool("cxx", "clang", "clangxx") then + if resourcefile and os.isfile(resourcefile) then + local content = io.readfile(resourcefile) + io.writefile(resourcefile, content, {encoding = "utf8"}) + end + end + -- update files and values to the dependent file dependinfo.files = {sourcefile} dependinfo.values = args diff --git a/xmake/rules/wdk/xmake.lua b/xmake/rules/wdk/xmake.lua index 114e0e6756..d94b51fce6 100644 --- a/xmake/rules/wdk/xmake.lua +++ b/xmake/rules/wdk/xmake.lua @@ -24,8 +24,8 @@ rule("wdk.driver") -- add rules add_deps("wdk.inf", "wdk.man", "wdk.mc", "wdk.mof", "wdk.tracewpp", "wdk.sign", "wdk.package.cab") - -- after load - after_load(function (target) + -- on config + on_config(function (target) -- load environment if target:rule("wdk.env.umdf") then From 2f16b3d37c421f975852fec05a69d35041677368 Mon Sep 17 00:00:00 2001 From: Arthur LAURENT Date: Wed, 10 Sep 2025 16:14:33 +0200 Subject: [PATCH 4/4] fix(wdk tests) fix wdk tests to make them build with clang --- tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c | 2 +- tests/projects/windows/driver/umdf/skeleton/xmake.lua | 10 ++++++++-- tests/projects/windows/driver/wdm/msdsm/intrface.c | 5 ++++- tests/projects/windows/driver/wdm/msdsm/msdsm.h | 2 +- tests/projects/windows/driver/wdm/msdsm/prototypes.h | 2 +- tests/projects/windows/driver/wdm/perfcounters/kcs.c | 3 +++ 6 files changed, 18 insertions(+), 6 deletions(-) diff --git a/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c b/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c index 6ec41747e8..640c4a3384 100644 --- a/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c +++ b/tests/projects/windows/driver/kmdf/ioctl/exe/testapp.c @@ -213,7 +213,7 @@ GetCoinstallerVersion( VOID __cdecl main( - _In_ ULONG argc, + _In_ INT argc, _In_reads_(argc) PCHAR argv[] ) { diff --git a/tests/projects/windows/driver/umdf/skeleton/xmake.lua b/tests/projects/windows/driver/umdf/skeleton/xmake.lua index ee8ed00b54..547ad376ba 100644 --- a/tests/projects/windows/driver/umdf/skeleton/xmake.lua +++ b/tests/projects/windows/driver/umdf/skeleton/xmake.lua @@ -8,6 +8,12 @@ target("UMDFSkeleton") add_files("*.cpp", {rules = "wdk.tracewpp"}) add_files("*.rc", "*.inx") set_values("wdk.umdf.sdkver", "1.9") - add_shflags("/DEF:exports.def", {force = true}) - add_shflags("/ENTRY:_DllMainCRTStartup" .. (is_arch("x86") and "@12" or ""), {force = true}) + add_files("exports.def") + on_config(function(target) + if target:has_tool("sh", "clang", "clangxx") then + target:add("shflags", "-Wl,/ENTRY:_DllMainCRTStartup" .. (is_arch("x86") and "@12" or ""), {force = true}) + else + target:add("shflags", "/ENTRY:_DllMainCRTStartup" .. (is_arch("x86") and "@12" or ""), {force = true}) + end + end) diff --git a/tests/projects/windows/driver/wdm/msdsm/intrface.c b/tests/projects/windows/driver/wdm/msdsm/intrface.c index 4a390c212c..4266beba73 100644 --- a/tests/projects/windows/driver/wdm/msdsm/intrface.c +++ b/tests/projects/windows/driver/wdm/msdsm/intrface.c @@ -32,6 +32,7 @@ Module Name: #pragma warning (disable:4305) +DSM_INIT_DATA gDsmInitData; // // Flag to indicate whether to NT_ASSERT or ignore a particular condition. @@ -3430,7 +3431,7 @@ Return Value: NTSTATUS DsmRemovePath( - _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PVOID _DsmContext, _In_ IN PVOID PathId ) /*++ @@ -3456,6 +3457,8 @@ Return Value: PDSM_FAILOVER_GROUP failGroup; KIRQL irql; + PDSM_CONTEXT DsmContext = (PDSM_CONTEXT)_DsmContext; + TracePrint((TRACE_LEVEL_VERBOSE, TRACE_FLAG_PNP, "DsmRemovePath (PathId %p): Entering function.\n", diff --git a/tests/projects/windows/driver/wdm/msdsm/msdsm.h b/tests/projects/windows/driver/wdm/msdsm/msdsm.h index 982ed7ffc3..9962b0f801 100644 --- a/tests/projects/windows/driver/wdm/msdsm/msdsm.h +++ b/tests/projects/windows/driver/wdm/msdsm/msdsm.h @@ -115,7 +115,7 @@ Module Name: // // Initialization data structure that needs to be filled in for MPIO // -DSM_INIT_DATA gDsmInitData; +extern DSM_INIT_DATA gDsmInitData; // // Macro used to round of a number to the nearest 8 byte aligned one. diff --git a/tests/projects/windows/driver/wdm/msdsm/prototypes.h b/tests/projects/windows/driver/wdm/msdsm/prototypes.h index c72c22cb41..08eb5ba0d2 100644 --- a/tests/projects/windows/driver/wdm/msdsm/prototypes.h +++ b/tests/projects/windows/driver/wdm/msdsm/prototypes.h @@ -206,7 +206,7 @@ DsmRemoveDevice( NTSTATUS DsmRemovePath( - _In_ IN PDSM_CONTEXT DsmContext, + _In_ IN PVOID DsmContext, _In_ IN PVOID PathId ); diff --git a/tests/projects/windows/driver/wdm/perfcounters/kcs.c b/tests/projects/windows/driver/wdm/perfcounters/kcs.c index 67ca0e3286..610cb88e05 100644 --- a/tests/projects/windows/driver/wdm/perfcounters/kcs.c +++ b/tests/projects/windows/driver/wdm/perfcounters/kcs.c @@ -27,6 +27,9 @@ Module Name: #include "kcs.h" #include "kcsCounters.h" +#include +#include + #pragma code_seg("PAGE") DRIVER_INITIALIZE DriverEntry;