github.com/containers/podman/v4@v4.9.4/contrib/win-installer/podman-msihooks/check.c (about) 1 #include <windows.h> 2 #include <MsiQuery.h> 3 4 BOOL isWSLEnabled(); 5 LPCWSTR boolToNStr(BOOL bool); 6 7 /** 8 * CheckWSL is a custom action loaded by the Podman Windows installer 9 * to determine whether the system already has WSL installed. 10 * 11 * The intention is that this action is compiled for x86_64, which 12 * can be ran on both Intel and Arm based systems (the latter through 13 * emulation). While the code should build fine on MSVC and clang, the 14 * intended usage is MingW-W64 (cross-compiling gcc targeting Windows). 15 * 16 * Previously this was implemented as a Golang c-shared cgo library, 17 * however, the WoW x86_64 emulation layer struggled with dynamic 18 * hot-loaded transformation of the goruntime into an existing process 19 * (required by MSI custom actions). In the future this could be 20 * converted back, should the emulation issue be resolved. 21 */ 22 23 __declspec(dllexport) UINT __cdecl CheckWSL(MSIHANDLE hInstall) { 24 BOOL hasWSL = isWSLEnabled(); 25 // Set a property with the WSL state for the installer to operate on 26 MsiSetPropertyW(hInstall, L"HAS_WSLFEATURE", boolToNStr(hasWSL)); 27 28 return 0; 29 } 30 31 LPCWSTR boolToNStr(BOOL bool) { 32 return bool ? L"1" : L"0"; 33 } 34 35 BOOL isWSLEnabled() { 36 /* 37 * The simplest, and most reliable check across all variants and versions 38 * of WSL appears to be changing the default version to WSL 2 and check 39 * for errors, which we need to do anyway. 40 */ 41 STARTUPINFOW startup; 42 PROCESS_INFORMATION process; 43 44 ZeroMemory(&startup, sizeof(STARTUPINFOW)); 45 startup.cb = sizeof(STARTUPINFOW); 46 47 // These settings hide the console window, so there is no annoying flash 48 startup.dwFlags = STARTF_USESHOWWINDOW; 49 startup.wShowWindow = SW_HIDE; 50 51 // CreateProcessW requires lpCommandLine to be mutable 52 wchar_t cmd[] = L"wsl --set-default-version 2"; 53 if (! CreateProcessW(NULL, cmd, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, 54 NULL, NULL, &startup, &process)) { 55 56 return FALSE; 57 } 58 59 DWORD exitCode; 60 WaitForSingleObject(process.hProcess, INFINITE); 61 if (! GetExitCodeProcess(process.hProcess, &exitCode)) { 62 return FALSE; 63 } 64 65 return exitCode == 0; 66 }