3

Windows 10 S is a special Windows edition which is streamlined for security and superior performance. Basically you can only install apps from Microsoft Store.

You can deliver normal desktop apps through desktop bridge to the Store so that itself is not a big problem. However Windows 10 S imposes additional limitations on Store apps, which might cause them to crash during startup.

I have received this feedback from Store Application Review Results.

App Policies: 10.1.2.1 Inaccurate Functionality: Windows 10S

Notes To Developer:

Your app doesn't work on Windows 10 S and the application terminates without notice to the user. Apps that don’t work on Windows 10 S must support graceful shutdown.

Steps to reproduce: 1. Launch the app on Windows 10S. 2. Notice that your app doesn't work on Windows 10 S and the application terminates without notice to the user.

Please be sure to test your app for Windows 10 S: https://learn.microsoft.com/windows/uwp/porting/desktop-to-uwp-test-windows-s Tested Devices: Windows 10 Desktop

So basically what I need to do is to detect Windows 10 S and notify the user that it's not supported.

Pawel Troka
  • 853
  • 2
  • 12
  • 33
  • Check [this](https://stackoverflow.com/q/4405761/8918893) question. – Klooven Nov 18 '17 at 17:10
  • 1
    I've also added the value for the N Edition without WMP becasue you are from Poland and may run into such the issue to detect such edition. – magicandre1981 Nov 19 '17 at 15:17
  • 2
    Out of curiosity, do you know what your app does that is crashing? – Peter Torr - MSFT Nov 20 '17 at 01:26
  • 1
    @PeterTorr-MSFT I think it's because I'm using `System.Diagnostics.Process.Start` to start processes other than my app. Also this is what `package sanity test` suggests: https://github.com/PawelTroka/Computator.NET/issues/129 – Pawel Troka Nov 20 '17 at 11:00
  • Ah yes, you can't run CMD or PowerShell scripts on 10 S. Thanks! – Peter Torr - MSFT Nov 20 '17 at 13:11
  • @PeterTorr-MSFT Well AFAIK I don't run CMD nor PowerShell in my code (my libraries might of course, although I don't know what for). I do run however fontview.exe (Process.Start on font files) , explorer (Process.Start on directory path) and web browser (Process.Start on url). – Pawel Troka Nov 20 '17 at 15:19

4 Answers4

7

Use GetProductInfo Win32 API call and check for return value PRODUCT_CLOUD (0x000000B2) and PRODUCT_CLOUDN (0x000000B3). That 2 values are the SKU detection codes for Windows 10 S.

magicandre1981
  • 27,895
  • 5
  • 86
  • 127
  • This approach may stop working soon, as Microsoft has declared their intention to make 10S a mode instead of a separate product. If they do that, then the SKU will presumably remain the same when the user toggles that option. – jbcarpen Mar 12 '18 at 23:52
  • @jbcarpen we have to wait for the final product and SDK to see how Microsoft implements this S mode for all SKUs. – magicandre1981 Mar 13 '18 at 08:22
  • I'm curious if this still works? (I can't try it right away without having my Store app pass certification.) – c00000fd Mar 24 '18 at 22:20
  • @c00000fd as I already commented we have to wait for the final product and SDK to see how Microsoft implements this S mode. MS released first build without watermark, so it can't take long when RTM gets build. When 1803 RTM + SDK is out, I'll take a look at it. – magicandre1981 Mar 25 '18 at 14:46
  • @magicandre1981: There's no such thing as RTM anymore. You can download it now as part of the [Media creation tool](https://www.microsoft.com/en-us/software-download/windows10) or [buy a computer with Windows 10S installed](https://www.amazon.com/Microsoft-Surface-Laptop-Intel-128GB/dp/B072L7KKYQ/ref=sr_1_2?ie=UTF8&qid=1521999857&sr=8-2&keywords=windows+10s&dpID=41erPQLRs5L&preST=_SX300_QL70_&dpSrc=srch) on it. – c00000fd Mar 25 '18 at 17:45
  • @c00000fd there is still RTM. Build 15063 (RS2) is RTM for Creators update, 16299.15 (RS3) is RTM for Fall Creators Update and 17133 (or any other 171xx Build) could be RTM for Spring Creators Update (RS4). In RS4 every edition can have S Mode (Home in S Mode, Pro in S Mode): Here we need to see the RS4 SDK on how to detect this S Mode. – magicandre1981 Mar 26 '18 at 13:51
  • 1
    Yes, I can confirm, the `pdwReturnedProductType` I just got from a test on `Win10 S` machine is `0xB2`. – c00000fd Apr 07 '18 at 08:37
  • 1
    @c00000fd this is expected. For 1803 (17133.1) you can turn any edition to S mode by creating a new DWORD named **WindowsLockdownTrialMode** under **HKLM\System\CurrentControlSet\Control\CI\Policy**. so to detect this mode query the value. – magicandre1981 Apr 07 '18 at 15:31
  • @magicandre1981: Hmm, I never tried it. Thanks. But [here's a documented way](https://learn.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-test-windows-s). – c00000fd Apr 07 '18 at 21:05
  • This answer does not work on Windows 10 1803 and newer. For more information, see: https://stackoverflow.com/a/58685975/2134110 – Frank Lesniak Nov 04 '19 at 00:51
2

Inspired by magicandre1981's solution of checking the SKU I implemented it as a concrete solution. It contains a workaround to GetVersionEx() being deprecated in Windows 10 and it contains a check for Windows 10 S Dev Mode in order allow proper testing.

One disclaimer is that this check works as intended in my environment (both real 10 S and Dev Mode). But an end-user has reported that the check is not reliable, I have not been able to validate if the end-user actually run 10 S or just think he does. It passed the review process at Microsoft though.

Example console application in C++ that runs the checks:

// Windows10SCheck.cpp : This file contains the 'main' function. Program execution begins and ends there.
//

#include "pch.h"
#include <iostream>
#include <Windows.h>

// Function to get the OS version number
//
// Uses RtlGetVersion() is available, otherwise falls back to GetVersionEx()
//
// Returns false if the check fails, true if success
bool GetOSVersion(OSVERSIONINFOEX* osversion) {
    NTSTATUS(WINAPI *RtlGetVersion)(LPOSVERSIONINFOEX);
    *(FARPROC*)&RtlGetVersion = GetProcAddress(GetModuleHandleA("ntdll"), "RtlGetVersion");

    if (RtlGetVersion != NULL)
    {
        // RtlGetVersion uses 0 (STATUS_SUCCESS)
        // as return value when succeeding
        return RtlGetVersion(osversion) == 0;
    }
    else {
        // GetVersionEx was deprecated in Windows 10
        // Only use it as fallback
#pragma warning(suppress : 4996)
        return GetVersionEx((LPOSVERSIONINFO)osversion);
    }
}

// Function to check if the product type is Windows 10 S
//
// The product type values are from: https://stackoverflow.com/a/47368738/959140
//
// Output parameter bool iswin10s indicates if running 10 S or not
//
// Returns false if the check fails, true if success
bool IsWindows10S(bool *iswin10s) {
    OSVERSIONINFOEX osinfo;
    osinfo.dwOSVersionInfoSize = sizeof(osinfo);
    osinfo.szCSDVersion[0] = L'\0';

    if (!GetOSVersion(&osinfo)) {
        return false;
    }

    DWORD dwReturnedProductType = 0;

    if (!GetProductInfo(osinfo.dwMajorVersion, osinfo.dwMinorVersion, 0, 0, &dwReturnedProductType)) {
        return false;
    }

    *iswin10s = dwReturnedProductType == PRODUCT_CLOUD || dwReturnedProductType == PRODUCT_CLOUDN;

    return true;
}

bool IsWindows10SDevMode() {
    // Checks for the policy file mentioned in the docs:
    // https://learn.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-test-windows-s
    struct stat buffer;

    // x64 applications
    std::string filePathName64 = "C:\\Windows\\system32\\CodeIntegrity\\SIPolicy.P7B";
    if (stat(filePathName64.c_str(), &buffer) == 0) {
        return true;
    }

    // x86 applications
    std::string filePathName86 = "C:\\Windows\\sysnative\\CodeIntegrity\\SIPolicy.P7B";
    if (stat(filePathName86.c_str(), &buffer) == 0) {
        return true;
    }


    return false;
}

int main() {
    bool is10s = false;
    if (!IsWindows10S(&is10s)) {
        std::cout << "Windows 10 S check failed";
    }

    std::cout << "\nIs 10 S: " << (is10s ? "true" : "false");
    std::cout << "\nIs 10 S Dev Mode: " << (IsWindows10SDevMode() ? "true" : "false");
}
Robin Andersson
  • 5,150
  • 3
  • 25
  • 44
2

If Windows 10 1803 or newer, check for the following DWORD registry value:

  • Registry Key (Path): HKLM\System\CurrentControlSet\Control\CI\Policy
  • Registry Value Name: SkuPolicyRequired
  • Registry Value (DWORD): 1

(source: https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/unattend/microsoft-windows-codeintegrity-skupolicyrequired)

On versions of Windows 10 prior to 1803, Windows 10 S (and Windows 10 S N) were their own SKUs. To check this, query the following with WMI: Win32_OperatingSystem -> OperatingSystemSKU and look for an integer value of 178 (Windows 10 S) or 179 (Windows 10 S N).

Regardless of which version of Windows 10 is running, querying for S Mode / Windows 10 S / Windows 10 S N is tricky because common tools like cmd, powershell, regedit, reg, wmic, and wbemtest are going to be blocked. To enable these tools, the device needs to be put into Manufacturing Mode by placing a registry key in place (offline using WinPE), then booting up the computer. For reference, see: https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-10-s-manufacturing-mode

Assuming the device is in Manufacturing Mode and you have access to the command prompt, here are a couple ways to query for S Mode / Windows 10 S / Windows 10 S N:

For Windows 10 1803 and newer, an easy way to query for S Mode is to type the following at the command prompt:

reg query HKLM\SYSTEM\CurrentControlSet\Control\CI\Policy /v SkuPolicyRequired

(if you receive a message that the system was unable to find the specified registry key or value, or if you receive a result of a REG_DWORD other than 0x1, then S Mode is not enabled)

For Windows 10 versions prior to 1803, an easy way to query this at the command prompt is to type:

wmic os get operatingsystemsku

Frank Lesniak
  • 560
  • 1
  • 5
  • 18
1

I'm just throwing it out there, as an alternative idea. This is entirely undocumented!

I learned purely by chance that if you try to ShellExecuteEx one of the Windows default applications that are not allowed in 10 S, such as %WinDir%\System32\cmd.exe, it will fail with the error code ERROR_SYSTEM_NEEDS_REMEDIATION (or 15623) that I haven't seen returned from any other calls.

c00000fd
  • 20,994
  • 29
  • 177
  • 400