2

I am using the optional Windows 10 feature "Unified Write Filter" (uwfmgr.exe) to protect kiosk machines from unwanted changes. Now in order to deploy custom updates, it includes a Servicing User under which changes to the protected volumes can be performed.

To execute these custom updates, the script at C:\Windows\system32\UwfServicingMasterScript.cmd is supposed to be edited. (official Documentation)

Now I am unable to edit this file since it is owned by the "TrustedInstaller" user for which not even Administrators have permissions.

enter image description here

What am I missing here? Am I supposed to change the owner of this file?

clamp
  • 1,282

2 Answers2

0

My own understanding of the subject is incomplete, but I believe that you are supposed to use a certain procedure when doing these kind of updates, and specifically you are not supposed to take ownership of Windows files.

The process is better described in the article Overview of Microsoft UWF (Unified Write Filter), of which here is a short summary:

  • With UWF enabled, create a new text file, say C:\TestPersist

  • Add it to UWF with the command:

      uwfmgr file add-exclusion c:\testpersist
    
  • Enable UWF with the command : uwfmgr filter enable

  • To check UWF settings use : uwfmgr.exe get-config

References:

Note: You might find useful the new Windows 10 feature of Windows Sandbox.

harrymc
  • 498,455
0

I may be a little late to the party, but I just found this post, because I ran into the same problems.

With the use of @vomit-it-chunky-mess-style their comment I came to the following C# code, which works for replacing the cmd file with my own. Hopefully this helps the next person to land here.

using System.Diagnostics;

var masterScriptLocation = @"C:\Windows\System32\UwfServicingMasterScript.cmd"; var newMasterScript = """ REM servicing of the device with UWF installed. The script will REM call UWF manager application to update the system with the REM latest available updates. REM The script will detect whether the update operation REM ended successfully or requires a reboot. REM REM The script will change the "SERVICING" state of the device REM only when the update operation results in a "SUCCESS". REM A state change of the device requires a reboot. REM REM If the update operation requires a "REBOOT" the script will REM reboot device without changing the "SERVICING" state. The REM Will then run again on the following reboot until REM the update operation either return a "SUCCESS" or a "ERROR" REM REM Any third-party script that needs to run before the state REM change should run in the UPDATE_SUCCESS block REM REM Environment : REM It is expected that UWF is turned "OFF", "SERVICING" mode REM enabled and all other preconditions REM for servicing are in place. REM REM REM

echo UpdateAgent starting.
uwfmgr servicing update-windows
if ERRORLEVEL 3010 goto UPDATE_REBOOT
if ERRORLEVEL 0 goto UPDATE_SUCCESS
echo UpdateAgent returned error =%ERRORLEVEL%

:UPDATE_ERROR
uwfmgr servicing disable
echo Restarting system
goto UPDATE_EXIT

:UPDATE_REBOOT
echo UpdateAgent requires a reboot.
echo UpdateAgent restarting system
goto UPDATE_EXIT

:UPDATE_SUCCESS
echo UpdateAgent returned success.
REM
REM echo UpdateAgent executing OEM script
REM OEM can call their custom scripts
REM at this point through a "call".
REM
REM The OEM script should hand control
REM back to this script once it is done.
REM
REM Any error recovery for OEM script
REM should be handled outside of this script
REM post a reboot.
REM
uwfmgr servicing disable
echo Restarting system
goto UPDATE_EXIT

:UPDATE_EXIT
echo UpdateAgent exiting.
shutdown -r -t 5
EXIT /B
""";

using (Process myProcess = new()) { myProcess.StartInfo.UseShellExecute = false; myProcess.StartInfo.FileName = "takeown.exe"; myProcess.StartInfo.Arguments = $"""/a /f "{masterScriptLocation}" """; myProcess.StartInfo.CreateNoWindow = true; myProcess.StartInfo.RedirectStandardOutput = true; myProcess.Start(); myProcess.WaitForExit(); string output = myProcess.StandardOutput.ReadToEnd(); Console.WriteLine(output); }

using (Process myProcess = new()) { myProcess.StartInfo.UseShellExecute = false; myProcess.StartInfo.FileName = "icacls"; myProcess.StartInfo.Arguments = $""" "{masterScriptLocation}" /grant everyone:F /t"""; myProcess.StartInfo.CreateNoWindow = true; myProcess.StartInfo.RedirectStandardOutput = true; myProcess.Start(); myProcess.WaitForExit(); string output = myProcess.StandardOutput.ReadToEnd(); Console.WriteLine(output); }

File.Delete(masterScriptLocation);

File.WriteAllText(masterScriptLocation,newMasterScript);

Foitn
  • 103