Skip to content

Commit

Permalink
Making EM RS5+. Limiting the tracking capability to Windows11+ (Spec) (
Browse files Browse the repository at this point in the history
…#2544)

* Updating spec

* Adressing comments

* More changes

Co-authored-by: Darren Hoehna <dahoehna@microsoft.com>
  • Loading branch information
dhoehna and Darren Hoehna committed Jun 10, 2022
1 parent ea92f45 commit 89b3bea
Showing 1 changed file with 20 additions and 73 deletions.
Expand Up @@ -10,11 +10,10 @@ Environment variables is one example, where there are several existing APIs
that provide partially overlapping functionality, and with some gaps. This spec
describes the Reunion support for environment variables.

Important Note: this feature relies on other platform features which are only
available from Windows summer 2021 onwards. Therefore this feature is also
only available from Windows summer 2021 onwards. An app can check the
IsSupported property to determine whether the current device supports the
feature.
Important Note: The EV tracking feature relies on other platform features which are only
available from Windows 21H1+ (i.e. version >=10.0.19043.0). An app can check the
IsChangeTrackingSupported property to determine whether Environment manager will track EV changes.


Note that there are existing Win32 and .NET APIs that cover much of the same
behaviors as the new APIs. The only _net_ _new_ behaviors are:
Expand Down Expand Up @@ -73,6 +72,7 @@ permissions section below).
system-wide scope.
- **static bool IsSupported { get; }** - readonly property that indicates whether this
API is supported on the current device/OS version.
- **bool IsChangeTrackingSupported { get;}** - readonly property that indicates whether the EV changes will be tracked.
- **IMapView<string, string> GetEnvironmentVariables** - gets a collection of
environment variables at the scope of the current EnvironmentManager.
- **string GetEnvironmentVariable(string)** - gets the value of the specified
Expand Down Expand Up @@ -280,21 +280,12 @@ There are 3 scopes for writing environment variables, **Process**, **User**, and
Setting a **User** or **System** variable will persist that variable beyond the
life of the process in the user profile or system profile.

Unpackaged apps can use the existing native Win32 Get/SetEnvironment and
registry APIs. They can also use the managed System.Environment class, and
specifically the methods GetEnvironmentVariable, GetEnvironmentVariables and
SetEnvironmentVariable. We are introducing the new API so that non-fulltrust
packaged apps can access some of the same functionality. Key existing behaviors
are listed in the table below:

| App Type | API Type | Process Vars | User Vars | Machine Vars |
| -------------- | -------- | ------------ | ----------- | ------------ |
| Unpackaged | Native | Read, Write | Read, Write | Read, Write |
| Unpackaged | Managed | Read, Write | Read, Write | Read, Write |
| Desktop Bridge | Native | Read, Write | Read, Write | Read, Write |
| Desktop Bridge | Managed | Read, Write | Read, Write | Read, Write |
| UWP | Native | Read, Write | Read | Read |
| UWP | Managed | Read, Write | Read | (none) |
Unpackaged apps can use the existing native Win32 [GetEnvironmentVariable](https://docs.microsoft.com/windows/win32/api/winbase/nf-winbase-getenvironmentvariable)/
[SetEnvironmentVariable](https://docs.microsoft.com/windows/win32/api/winbase/nf-winbase-setenvironmentvariable) and
registry APIs. Unpackaged .NET apps can use [System.Environment](https://docs.microsoft.com/dotnet/api/system.environment?view=net-6.0) class, and
specifically the methods [GetEnvironmentVariable](https://docs.microsoft.com/dotnet/api/system.environment.getenvironmentvariable?view=net-6.0),
[GetEnvironmentVariables](https://docs.microsoft.com/dotnet/api/system.environment.getenvironmentvariables?view=net-6.0)
and [SetEnvironmentVariable](https://docs.microsoft.com/dotnet/api/system.environment.setenvironmentvariable?view=net-6.0).

Environment variables are stored in the registry here:

Expand All @@ -303,57 +294,6 @@ Environment variables are stored in the registry here:
- Machine: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session
Manager\Environment

Packaging a Win32 app in an MSIX (and therefore a Helium container at runtime)
doesn't affect its ability to read Environment variables. For writing, an
unpackaged app can write to HKCU; but needs elevation to write to HKLM. When
packaged, writes to HKCU are virtualized, unless the app has the unvirtualizedResources
restricted capability and has suppressed registry write virtualization for HKCU.

An unpackaged or packaged Win32 (Desktop Bridge) app can write to HKLM if the
app is running elevated. A UWP app cannot run elevated. In the normal case,
where virtualization is not disabled, all writes to HKCU actually go to a
private hive file similar to:
%ProgramData%\Packages\<PackageFamilyName>\<Security ID>\SystemAppData\Helium

In a non-Desktop Bridge pure UWP app, using the existing System.Environment
class, you can get/set at the Process scope only: you can't get or set
environment variables for User or Machine. The calls are merely no-ops - there's
no exception, but the return is an empty string. The use of the
unvirtualizedResources feature in a pure UWP app makes no difference to this.
However, you can use the managed Registry APIs to read at User scope (but not at
Machine scope), and p/invoke to the native registry APIs to read at both User
and Machine scope.

Moving forward, the new APIs will enable the following behaviors:

| App Type | API Type | Process Vars | User Vars | Machine Vars |
| -------------- | -------- | ------------ | ----------- | ------------ |
| Unpackaged | Managed | Read, Write | Read, Write | Read, Write |
| Desktop Bridge | Managed | Read, Write | Read, Write | Read, Write |
| UWP | Managed | Read, Write | Read | Read |

Consistent with the existing System.Environment APIs, for the new APIs, reading
environment variables does not need any special security consideration. Writing
variables where the scope is the current process also does not pose any security
issues. However, writing variables where the scope is either User or Machine can
affect other apps:

- **User**: even though the calling app is running with the current user's
credentials and permissions, this does not mean that it is acceptable for one
app to change a variable that could affect other apps.

- **Machine**: changing a machine-wide variable can affect not only all apps on
the machine, but also all users on the machine.

Therefore, we will protect the use of User and Machine scope as follows:

- **User**: attempting to set a variable when the scope is User will fail unless
the calling app has fulltrust.

- **Machine**: attempting to set a variable when the scope is Machine will fail
unless the calling app is running elevated (which means it will only work for
unpackaged or Centennial apps and not for UWP apps).

Note: to update the user-scoped list of variables we need to write to the
registry and cause Shell to refresh its cache. This will be done using an
existing public WNF notification.
Expand Down Expand Up @@ -533,16 +473,23 @@ The new types are defined as follows:
```idl
namespace Microsoft.Windows.System
{
[contractversion(2)]
apicontract EnvironmentManagerContract{};
[contract(EnvironmentManagerContract, 1)]
runtimeclass EnvironmentManager
{
static EnvironmentManager GetForProcess();
static EnvironmentManager GetForCurrentUser();
static EnvironmentManager GetForMachine();
static bool IsSupported { get; }
[contract(EnvironmentManagerContract, 2]
bool IsChangeTrackingSupported {get; };
IMapView<String, String> GetEnvironmentVariables();
String GetEnvironmentVariable(String name);
void SetEnvironmentVariable(String name, String value);
void AppendToPath(String path);
void RemoveFromPath(String path);
Expand Down

0 comments on commit 89b3bea

Please sign in to comment.