diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..01975d1 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +# The kept copy of the snapshot file is compared byte for byte, line endings included, so git has +# to hand it over exactly as it was committed on every machine and every CI runner. Without this a +# checkout with core.autocrlf would rewrite it and the test would fail on bytes nobody changed. +tests/Bws.Core.Tests/Golden/* -text diff --git a/CHANGELOG.md b/CHANGELOG.md index b559c82..166cc51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,18 @@ is not part of this repository. - When a plan touches several entries this machine does not work without, the sheet names them all in one sentence instead of one sentence each. On a plan over a whole scope those sentences used to push every step off the sheet. +- The plan for a large selection appears sooner. Working out what stopping or restarting it + involves asks Windows about each entry's dependents once instead of several times, and the + plan for stopping every service on the test machine appeared in about 100-170 ms instead of + about 185-275. + +### Fixed + +- A plan over a selection that includes an entry this machine does not work without - stopping + a whole scope, for example - asked for a name to be typed, and typing it changed nothing: the + button stayed off. Such a selection cannot be carried out, and the sheet now says so, with the + entries named above it and a sentence saying to deselect them or deal with each one on its own. + A plan for one such entry still asks for its name, as before. ## [0.3.0] - 2026-09-25 diff --git a/src/Bws.Core/Planning/BulkPlanBuilder.cs b/src/Bws.Core/Planning/BulkPlanBuilder.cs index cec8f1d..451eb4c 100644 --- a/src/Bws.Core/Planning/BulkPlanBuilder.cs +++ b/src/Bws.Core/Planning/BulkPlanBuilder.cs @@ -36,11 +36,14 @@ public BulkPlan Build(BulkAction action) // what somebody asked keeps its repeats, because it is a record. var asked = action.ServiceNames.Distinct(StringComparer.OrdinalIgnoreCase).ToList(); - var builder = new PlanBuilder(entries, catalog, processes); + // One answer per name for the whole of this build - the ordering and every plan below ask + // about the same names, and DependentsAskedOnce says what that cost before it was shared. + var asking = new DependentsAskedOnce(catalog); + var builder = new PlanBuilder(entries, asking, processes); var plans = new List(); var problems = new List(); - foreach (var name in InTheOrderTheyMustHappen(action, asked)) + foreach (var name in InTheOrderTheyMustHappen(action, asked, asking)) { var plan = builder.Build(new ServiceAction( action.Kind, name, action.IncludeDependents, action.To, AlsoStop: action.AlsoStop)); @@ -99,8 +102,8 @@ public BulkPlan Build(BulkAction action) /// to stop in the order a plain stop of both would use - or the first stop meets the second /// entry still running and the manager refuses it. /// - private List InTheOrderTheyMustHappen(BulkAction action, List asked) => + private static List InTheOrderTheyMustHappen(BulkAction action, List asked, IScmCatalog asking) => action.Kind is ActionKind.Start || (action.Kind == ActionKind.SetStartType && !action.AlsoStop) ? asked - : DependentsFirst.Order(catalog, asked); + : DependentsFirst.Order(asking, asked); } diff --git a/src/Bws.Core/Planning/CriticalEntries.cs b/src/Bws.Core/Planning/CriticalEntries.cs index 6265aa7..fb72f91 100644 --- a/src/Bws.Core/Planning/CriticalEntries.cs +++ b/src/Bws.Core/Planning/CriticalEntries.cs @@ -74,7 +74,7 @@ [.. affected.Where(entry => WithoutTheseTheMachineStops.Contains(entry.ServiceNa /// A warning rather than a refusal, on the owner's decision of 2026-09-06. An /// administrator has the right to manage their own machine, which is the line `R2` of the /// specification already draws. The window makes its own decision about how heavy a - /// confirmation to ask for - see Planned.NeedsTyping - and that is the window's, not + /// confirmation to ask for - see Planned.AsksHeavily - and that is the window's, not /// this. /// internal static void AddWarnings( diff --git a/src/Bws.Core/Planning/DependentsAskedOnce.cs b/src/Bws.Core/Planning/DependentsAskedOnce.cs new file mode 100644 index 0000000..e70bfb3 --- /dev/null +++ b/src/Bws.Core/Planning/DependentsAskedOnce.cs @@ -0,0 +1,46 @@ +namespace Bws.Core.Planning; + +/// +/// The catalogue, with "who depends on this name" put to the manager once for the whole of one +/// bulk plan. +/// +/// Why it exists, and what it was measured to save (S-7 of the performance report, built +/// 2026-09-29). A bulk plan asks the same question many times over. +/// asks once per selected name to put the selection in order, then each plan asks again about its +/// own target, and the cascades of neighbouring entries overlap. tools/plan-probe counted it on the +/// whole listing of 800 entries asked to stop: 1433 questions about 800 names, each one opening the +/// manager and then the service. +/// +/// One answer per name for one build, and no longer. A preview is a picture of one moment, so +/// a name that has answered once answers the same for the rest of that picture. That includes a +/// refusal - asked again a moment later it could come out differently and leave two plans in one +/// preview disagreeing about the same entry. It lives exactly as long as the build that made it and +/// is never handed on, so nothing it remembers can go stale between two presses. +/// +/// Names compared as written, not without case. The manager ignores case, so two spellings of +/// one name would at worst be asked twice, which costs one question. Folding them together would +/// instead be safe only because a real machine cannot hold two names that differ in case - the fake +/// catalogue deliberately does - and a rule that holds only while the input is real is the kind that +/// breaks where it is not. +/// +/// Not safe for two threads at once, and not asked to be: one build runs on one thread. +/// +internal sealed class DependentsAskedOnce(IScmCatalog catalog) : IScmCatalog +{ + private readonly Dictionary>> _answers = new(StringComparer.Ordinal); + + public IReadOnlyList ReadAll() => catalog.ReadAll(); + + public IReadOnlyList ReadStatuses() => catalog.ReadStatuses(); + + public Reading> ReadDependents(string serviceName) + { + if (!_answers.TryGetValue(serviceName, out var answer)) + { + answer = catalog.ReadDependents(serviceName); + _answers[serviceName] = answer; + } + + return answer; + } +} diff --git a/src/Bws.Core/Planning/PlanWarnings.cs b/src/Bws.Core/Planning/PlanWarnings.cs index d26d9f0..ed57648 100644 --- a/src/Bws.Core/Planning/PlanWarnings.cs +++ b/src/Bws.Core/Planning/PlanWarnings.cs @@ -97,7 +97,7 @@ public enum PlanWarningKind /// /// What the wording has to carry is the glossary's distinction `P1`: this is "you should /// not", which is a different sentence from "you cannot" and from "confirm that you mean it". - /// The window adds the third of those on its own - see Planned.NeedsTyping, owner's + /// The window adds the third of those on its own - see Planned.AsksHeavily, owner's /// decision of 2026-09-09 - and that is the window deciding how heavy a confirmation to ask /// for, not this warning changing what it says. /// diff --git a/src/Bws.Core/Snapshots/SnapshotJson.cs b/src/Bws.Core/Snapshots/SnapshotJson.cs index b8b4e81..84416e1 100644 --- a/src/Bws.Core/Snapshots/SnapshotJson.cs +++ b/src/Bws.Core/Snapshots/SnapshotJson.cs @@ -303,6 +303,12 @@ private static JsonNode Sorted(JsonNode node) return ordered; } - return node.DeepClone(); + // The leaf itself, not a copy of it. Both branches above take a child out of its old parent + // before handing it here, so it belongs to no tree and the new one can take it as it is. + // A copy of every value in the file is what this returned until 2026-09-29 (S-11 of the + // performance report). The kept copy in SnapshotGoldenTests is what says the bytes did + // not move - and a leaf that was still attached would throw on the first test, not + // write something wrong. + return node; } } diff --git a/src/Bws.Gui/PlanConfirmation.xaml b/src/Bws.Gui/PlanConfirmation.xaml new file mode 100644 index 0000000..85e05ff --- /dev/null +++ b/src/Bws.Gui/PlanConfirmation.xaml @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Bws.Gui/PlanConfirmation.xaml.cs b/src/Bws.Gui/PlanConfirmation.xaml.cs new file mode 100644 index 0000000..0668c15 --- /dev/null +++ b/src/Bws.Gui/PlanConfirmation.xaml.cs @@ -0,0 +1,28 @@ +using System.Windows; +using System.Windows.Controls; + +namespace Bws.Gui; + +/// +/// The heavy ask at the foot of a plan sheet: the sentence saying why, and the entry's name typed +/// back - or, on a selection, the refusal that stands where the box would. +/// +/// Everything it shows is decided by , as the footer around +/// it is. It left PlanFooter.xaml on 2026-09-29, when the refusal of backlog 475 needed room and +/// that file stood one line under the markup share the size ratchet calls near. What stays in this +/// class is what only a control can answer: which box to hand the keyboard, and whether it is there. +/// +public partial class PlanConfirmation : UserControl +{ + public PlanConfirmation() => InitializeComponent(); + + /// The box the entry's name is typed into. + internal TextBox Box => ConfirmBox; + + /// + /// Whether the box is on the screen - not the section. On a refused selection the section + /// stands with its reason and no box, and the keyboard has nowhere to go here. + /// + internal bool BoxShown => ConfirmSection.Visibility == Visibility.Visible + && TypingPart.Visibility == Visibility.Visible; +} diff --git a/src/Bws.Gui/PlanFooter.xaml b/src/Bws.Gui/PlanFooter.xaml index ae58d4e..3df4145 100644 --- a/src/Bws.Gui/PlanFooter.xaml +++ b/src/Bws.Gui/PlanFooter.xaml @@ -1,6 +1,7 @@ @@ -96,62 +97,11 @@ - - - - - - - - - - + + + + + diff --git a/tests/Bws.Core.Tests/Golden/snapshot-schema-4.json b/tests/Bws.Core.Tests/Golden/snapshot-schema-4.json new file mode 100644 index 0000000..d914ce5 --- /dev/null +++ b/tests/Bws.Core.Tests/Golden/snapshot-schema-4.json @@ -0,0 +1,1307 @@ +{ + "entries": [ + { + "account": null, + "binaryFile": "C:\\WINDOWS\\System32\\DriverStore\\FileRepository\\u0202073.inf_amd64_3c7f18bc022bf004\\B026184\\amdkmdag.sys", + "binaryHash": null, + "binaryOnDisk": false, + "binaryPath": "\\SystemRoot\\System32\\DriverStore\\FileRepository\\u0202073.inf_amd64_3c7f18bc022bf004\\B026184\\amdkmdag.sys", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": null, + "displayName": "amduw23g-202073-df09ebb6", + "entryType": "KernelDriver", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": null, + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)", + "serviceName": "amduw23g-202073-df09ebb6", + "sidType": null, + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Disabled", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Informacje o aplikacji", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1234, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "Appinfo", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Running", + "triggers": [ + { + "action": "Start", + "kind": "NetworkEndpoint" + }, + { + "action": "Start", + "kind": "NetworkEndpoint" + }, + { + "action": "Start", + "kind": "NetworkEndpoint" + }, + { + "action": "Start", + "kind": "NetworkEndpoint" + }, + { + "action": "Start", + "kind": "NetworkEndpoint" + }, + { + "action": "Start", + "kind": "NetworkEndpoint" + } + ] + }, + { + "account": null, + "binaryFile": "C:\\WINDOWS\\system32\\drivers\\AppvStrm.sys", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "\\SystemRoot\\system32\\drivers\\AppvStrm.sys", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "AppvStrm", + "entryType": "FileSystemDriver", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "AppvStrm", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "AsusUpdateCheck", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": null, + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)", + "serviceName": "AsusUpdateCheck", + "sidType": null, + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Stopped", + "triggers": null + }, + { + "account": null, + "binaryFile": "C:\\WINDOWS\\System32\\drivers\\Beep.sys", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": null, + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": null, + "displayName": "Beep", + "entryType": "KernelDriver", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": null, + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLOCRRC;;;IU)(A;;CCLCSWLOCRRC;;;SU)", + "serviceName": "Beep", + "sidType": null, + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "System", + "status": "Running", + "triggers": null + }, + { + "account": "NT AUTHORITY\\LocalService", + "binaryFile": "C:\\WINDOWS\\system32\\svchost.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\system32\\svchost.exe -k LocalServiceNoNetworkFirewall -p", + "delayedAuto": false, + "dependsOn": [ + "RpcSs" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Podstawowy aparat filtrowania", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 4296, + "requiredBy": null, + "requiredPrivileges": [ + "SeAuditPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCLORC;;;AU)(A;;CCDCLCSWRPLORCWDWO;;;SY)(A;;CCLCSWRPLORCWDWO;;;BA)(A;;CCLCLO;;;BU)", + "serviceName": "BFE", + "sidType": "Restricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": true, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Usługa inteligentnego transferu w tle", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 18044, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "BITS", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + }, + { + "account": null, + "binaryFile": "C:\\WINDOWS\\System32\\drivers\\bthmodem.sys", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "\\SystemRoot\\System32\\drivers\\bthmodem.sys", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Sterownik komunikacyjny modemu Bluetooth", + "entryType": "KernelDriver", + "errorControl": "Normal", + "fileVersion": null, + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "BTHMODEM", + "sidType": "Unrestricted", + "signature": { + "publisher": null, + "resultCode": -2146762496, + "status": "NotSigned" + }, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Usługa użytkownika platformy podłączonych urządzeń", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "Template", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "CDPUserSvc", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Stopped", + "triggers": null + }, + { + "account": null, + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Usługa użytkownika platformy podłączonych urządzeń_21aaa4", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "Instance", + "processId": 5984, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "CDPUserSvc_21aaa4", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "Keeps files, settings and mail in step between this device and the service.\r\nIf this service is stopped, anything that depends on it explicitly will fail to start, and content will stop being kept up to date until the service is started again. Stopping it does not remove anything already on this device.", + "displayName": "Contoso Sync Host", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1234, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "ContosoSyncHost", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\Program Files\\Contoso\\VPN\\v4.4.1\\ContosoVPN.TunnelService.exe", + "binaryHash": null, + "binaryOnDisk": false, + "binaryPath": "\"C:\\Program Files\\Contoso\\VPN\\v4.4.1\\ContosoVPN.TunnelService.exe\" \"C:\\Program Files\\Contoso\\VPN\\v4.4.1\\ServiceData\\Tunnel\\ContosoVPN.conf\" \"udp\"", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "ContosoVPN Tunnel", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "ContosoVPN Tunnel", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Program uruchamiający proces serwera DCOM", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1900, + "requiredBy": null, + "requiredPrivileges": [ + "SeAssignPrimaryTokenPrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeCreateGlobalPrivilege", + "SeDebugPrivilege", + "SeImpersonatePrivilege", + "SeIncreaseQuotaPrivilege", + "SeTcbPrivilege", + "SeBackupPrivilege", + "SeRestorePrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCLORC;;;AU)(A;;CCDCLCSWRPWPDTLORCWDWO;;;SY)(A;;CCLCSWRPWPDTLORCWDWO;;;BA)(A;;CCLCLO;;;BU)", + "serviceName": "DcomLaunch", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\Program Files (x86)\\Fabrikam\\Fabrikam Game Launcher Core\\GameElevationService.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\Program Files (x86)\\Fabrikam\\Fabrikam Game Launcher Core\\GameElevationService.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Fabrikam Game Elevation Service", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "GameElevationService", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Automatic, and nobody could tell whether it is delayed", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "HalfRead", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Stopped", + "triggers": null, + "unreadable": { + "delayedAuto": { + "errorCode": 5, + "message": "access denied" + } + } + }, + { + "account": null, + "binaryFile": null, + "binaryHash": null, + "binaryOnDisk": null, + "binaryPath": null, + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Nothing about this one could be read", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": null, + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": null, + "securityDescriptor": null, + "serviceName": "Locked", + "sidType": null, + "signature": null, + "startType": null, + "status": "Stopped", + "triggers": null, + "unreadable": { + "account": { + "errorCode": 5, + "message": "access denied" + }, + "binaryFile": { + "errorCode": 5, + "message": "access denied" + }, + "binaryOnDisk": { + "errorCode": 5, + "message": "access denied" + }, + "binaryPath": { + "errorCode": 5, + "message": "access denied" + }, + "delayedAuto": { + "errorCode": 5, + "message": "access denied" + }, + "requiredPrivileges": { + "errorCode": 5, + "message": "access denied" + }, + "securityDescriptor": { + "errorCode": 5, + "message": "access denied" + }, + "sidType": { + "errorCode": 5, + "message": "access denied" + }, + "signature": { + "errorCode": 5, + "message": "access denied" + }, + "startType": { + "errorCode": 5, + "message": "access denied" + } + } + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\system32\\svchost.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\system32\\svchost.exe -k DcomLaunch -p", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Menedżer sesji lokalnej", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1388, + "requiredBy": null, + "requiredPrivileges": null, + "securityDescriptor": null, + "serviceName": "LSM", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null, + "unreadable": { + "securityDescriptor": { + "errorCode": 5, + "message": "access denied" + } + } + }, + { + "account": "NT SERVICE\\McmSvc", + "binaryFile": "C:\\WINDOWS\\system32\\svchost.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\system32\\svchost.exe -k McmSvc -p -s McmSvc", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Usługa zarządzania łącznością mobilną", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": null, + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWRPWPDTLOCRRC;;;SY)(A;;CCDCLCSWRPWPDTLOCRRC;;;LS)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWLORC;;;IU)(A;;CCLCSWLOCRRC;;;SU)", + "serviceName": "McmSvc", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "NT SERVICE\\OpenVPNService", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "OpenVPNService", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "OpenVPNService", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Disabled", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": null, + "binaryHash": null, + "binaryOnDisk": null, + "binaryPath": null, + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Names no file at all", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": null, + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "PathLess", + "sidType": "Unrestricted", + "signature": null, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Plug and Play", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1900, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "PlugPlay", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Running", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": null, + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Nothing needs to be running first", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "PlugPlayNoDeps", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Running", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Usługa PushToInstall systemu Windows", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 17452, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "PushToInstall", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "StartPending", + "triggers": null + }, + { + "account": "localSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RpcSS", + "Bfe", + "RasMan", + "Http", + "+NetBIOSGroup" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Routing i dostęp zdalny", + "entryType": "SharedProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "RemoteAccess", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Disabled", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Bufor wydruku", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 4268, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "Spooler", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + }, + { + "account": "NT AUTHORITY\\NetworkService", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": true, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Ochrona oprogramowania", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "sppsvc", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Stopped", + "triggers": [ + { + "action": "Start", + "kind": "Custom" + }, + { + "action": "Start", + "kind": "CustomSystemStateChange" + } + ] + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": null, + "displayName": "Microsoft IPv6 Protocol Driver", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1234, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "Tcpip6", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null, + "unreadable": { + "description": { + "errorCode": 1332, + "message": "The resource could not be found." + } + } + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": null, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "Nobody asked yet", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "triggers", + "binaryHash" + ], + "perUserRole": "None", + "processId": null, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "TriggersUnknown", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Manual", + "status": "Stopped", + "triggers": null + }, + { + "account": "LocalSystem", + "binaryFile": "C:\\WINDOWS\\System32\\spoolsv.exe", + "binaryHash": null, + "binaryOnDisk": true, + "binaryPath": "C:\\WINDOWS\\System32\\spoolsv.exe", + "delayedAuto": false, + "dependsOn": [ + "RPCSS" + ], + "description": "This service spools print jobs and handles interaction with the printer. If you turn off this service, you won't be able to print or see your printers.", + "displayName": "First twin", + "entryType": "OwnProcess", + "errorControl": "Normal", + "fileVersion": "10.0.26100.1", + "loadOrderGroup": null, + "notRead": [ + "requiredBy", + "binaryHash" + ], + "perUserRole": "None", + "processId": 1234, + "requiredBy": null, + "requiredPrivileges": [ + "SeTcbPrivilege", + "SeImpersonatePrivilege", + "SeAuditPrivilege", + "SeChangeNotifyPrivilege", + "SeAssignPrimaryTokenPrivilege", + "SeLoadDriverPrivilege" + ], + "securityDescriptor": "O:SYG:SYD:(A;;CCLCSWLOCRRC;;;AU)(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)(A;;CCLCSWRPWPDTLOCRRC;;;SY)", + "serviceName": "Twin", + "sidType": "Unrestricted", + "signature": { + "publisher": "Microsoft Windows", + "resultCode": 0, + "status": "Trusted" + }, + "startType": "Automatic", + "status": "Running", + "triggers": null + } + ], + "metadata": { + "elevated": true, + "machine": "GOLDEN", + "note": "before the change", + "operatingSystem": "Microsoft Windows NT 10.0.26100.0", + "schemaVersion": 4, + "takenAt": "2026-09-29T12:00:00+02:00", + "takenBy": "EXAMPLE\\operator", + "tool": "0.3.0" + } +} diff --git a/tests/Bws.Core.Tests/SnapshotGoldenTests.cs b/tests/Bws.Core.Tests/SnapshotGoldenTests.cs new file mode 100644 index 0000000..d9f70bf --- /dev/null +++ b/tests/Bws.Core.Tests/SnapshotGoldenTests.cs @@ -0,0 +1,148 @@ +using System.Text; +using Bws.Core.Snapshots; +using Bws.Core.Tests.Fakes; + +namespace Bws.Core.Tests; + +/// +/// The snapshot file, byte for byte, against a copy kept beside this test. +/// +/// Every other test of the format asks one question of the text - are the keys in order, +/// is the measurement left out, does it end with a newline. None of them can see a change nobody +/// thought to ask about: a field renamed by a tidy-up, a null that stops being written, a +/// character that starts coming out escaped, a line ending that moves. Each of those leaves every +/// snapshot a person already keeps differing from the next one on hundreds of lines, and `ADR-6` +/// exists to prevent exactly that. The field names are a frozen contract in `docs/02` as well, so +/// a change here is a schema change and not a repair. +/// +/// Written 2026-09-29 for S-11 of the performance report, which found no such test, and +/// found the same day to be the precondition for NativeAOT: a trial AOT build printed an empty +/// object for every entry with exit code 0, and only a comparison of the bytes would have said +/// so - the text output of the same build was identical line for line. +/// +/// What the input is, and why it is not the machine. The whole specimen catalogue with +/// signatures read, so every nested object and every state of a field is in the file, plus a +/// memory reading so the file shows it being left out. The metadata is fixed here rather than +/// taken, because the real one carries the machine name, the account and the tool version, and +/// a kept copy that changes with the machine it runs on is not a kept copy. +/// +/// When this goes red on purpose - a new specimen, a field added with a schema bump - the +/// failure writes the new text beside the test binary and names the path. Copying it over the +/// kept one is the acceptance, and it is meant to be a deliberate act a reviewer sees in the diff. +/// +public sealed class SnapshotGoldenTests +{ + private const string Kept = "snapshot-schema-4.json"; + + [Fact] + public void The_file_is_written_byte_for_byte_as_the_kept_copy() + { + var written = SnapshotJson.Render(Frozen()); + var kept = KeptText(); + + if (string.Equals(written, kept, StringComparison.Ordinal)) + { + return; + } + + var actual = Path.Combine(AppContext.BaseDirectory, "snapshot-schema-4.actual.json"); + File.WriteAllText(actual, written, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); + + Assert.Fail( + "The snapshot file is no longer written the way it was. " + FirstDifference(kept, written) + + " The new text is at " + actual + " - if the change is meant, it is a schema change (docs/02) " + + "and the kept copy is replaced by hand in the same commit."); + } + + [Fact] + public void The_kept_copy_reads_back_and_is_written_again_unchanged() + { + // Reading loses nothing that writing produced. Without this the kept copy could hold a + // field the reader drops on the floor, and the comparison of two snapshots would never see it. + var kept = KeptText(); + + Assert.True(SnapshotJson.TryRead(kept, out var snapshot, out var failure), failure); + Assert.Equal(kept, SnapshotJson.Render(snapshot!)); + } + + [Fact] + public void The_kept_copy_is_of_the_schema_this_build_writes() + { + // A schema bump without a new kept copy would leave this test comparing a new format with + // an old file and calling the difference a fault. The file name carries the number so + // the bump has to touch both. + Assert.True( + Snapshot.CurrentSchemaVersion == 4, + $"The schema is now {Snapshot.CurrentSchemaVersion}. Keep a new copy named for it beside {Kept}."); + } + + // Without the second of the two names that differ only in case. The manager compares names + // without case, so no machine produces that pair, and the reader refuses a file holding it + // (Snapshot.BrokenEntries) - a kept copy with both would pin a state that cannot be read back. + // Their settled order is asserted on its own in SnapshotTests. + private static Snapshot Frozen() => + Snapshot.Of( + MemoryPass.Fill( + [.. Specimens.Inspected.Where(entry => entry.ServiceName != Specimens.CaseOnlyDifferenceSecond.ServiceName)], + new FakeProcessMemoryReader()), + note: null, + new FakeClock()) with + { + Metadata = new SnapshotMetadata + { + SchemaVersion = 4, + Machine = "GOLDEN", + OperatingSystem = "Microsoft Windows NT 10.0.26100.0", + TakenAt = new DateTimeOffset(2026, 9, 29, 12, 0, 0, TimeSpan.FromHours(2)), + TakenBy = @"EXAMPLE\operator", + Elevated = true, + Note = "before the change", + Tool = "0.3.0" + } + }; + + /// + /// The kept copy as its exact bytes, from inside the test assembly. + /// + /// Embedded rather than copied to the output folder, and read without looking for a byte + /// order mark: a mark that crept into the kept copy is a difference in the file a person + /// would get, so it has to fail here rather than be skipped over quietly. The line endings + /// survive a checkout because .gitattributes marks the folder as not text. + /// + private static string KeptText() + { + using var stream = typeof(SnapshotGoldenTests).Assembly.GetManifestResourceStream(Kept) + ?? throw new InvalidOperationException($"{Kept} is not embedded in the test assembly."); + using var reader = new StreamReader( + stream, + new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true), + detectEncodingFromByteOrderMarks: false); + + return reader.ReadToEnd(); + } + + private static string FirstDifference(string kept, string written) + { + var limit = Math.Min(kept.Length, written.Length); + var at = 0; + + while (at < limit && kept[at] == written[at]) + { + at++; + } + + var line = 1 + kept[..at].Count(character => character == '\n'); + + return $"First difference at character {at}, line {line}: kept [{Around(kept, at)}], written [{Around(written, at)}]."; + } + + // Twenty characters either side, with the line endings made visible, because a difference of + // one carriage return is otherwise two lines that look the same. + private static string Around(string text, int at) + { + var from = Math.Max(0, at - 20); + var to = Math.Min(text.Length, at + 20); + + return text[from..to].Replace("\r", "\\r", StringComparison.Ordinal).Replace("\n", "\\n", StringComparison.Ordinal); + } +} diff --git a/tests/Bws.Gui.Tests/ForcedStopGuards.cs b/tests/Bws.Gui.Tests/ForcedStopGuards.cs index ddc7564..6e48917 100644 --- a/tests/Bws.Gui.Tests/ForcedStopGuards.cs +++ b/tests/Bws.Gui.Tests/ForcedStopGuards.cs @@ -356,59 +356,8 @@ public void A_plan_that_has_been_carried_out_stops_asking_for_a_name() Assert.False(panel.NeedsTyping); } - /// - /// A plan asking about more than one entry can never be confirmed, because there is no single - /// name to type for it. - /// - /// Unreachable today and guarded anyway, which is the whole argument for the clause. - /// Section 15.6 of the analysis records that bulk forcing cannot be reached - the window opens - /// this sheet from one failure and the command line takes one name - so this is what happens if - /// that ever stops being true. Accepting one name for several processes would be somebody - /// agreeing to the first entry and getting all of them, which is the shape rule 5 of the - /// untouchable rules exists against: the preview and the press saying different things. - /// - [Fact] - public void A_plan_that_would_end_several_processes_can_never_be_confirmed() - { - var panel = new Planned { Elevated = true }; - - panel.Show(ForcingTwo()); - - Assert.True(panel.NeedsTyping); - Assert.False(panel.CanCarryOut); - - // NEITHER NAME LETS IT THROUGH, and nor does an empty box - which is the failure this - // clause was written against: TypeTheName answers with the first entry alone, so a plain - // comparison would have accepted one name for two processes. - foreach (var typed in new[] { "Spooler", "W32Time", string.Empty, " " }) - { - panel.Typed = typed; - - Assert.False(panel.CanCarryOut, typed); - } - } - - /// Two entries, each ending a process of its own. Nothing in this product builds one. - private static BulkPlan ForcingTwo() => new() - { - Action = new BulkAction(ActionKind.ForceStop, ["Spooler", "W32Time"]), - Plans = - [ - .. new[] { "Spooler", "W32Time" }.Select((name, at) => new OperationPlan - { - Action = new ServiceAction(ActionKind.ForceStop, name), - Steps = - [ - new PlanStep( - name, name, StepOperation.Terminate, - StepReason.Requested, ProcessId: 4812 + at) - ], - Warnings = [new PlanWarning(PlanWarningKind.TerminationTakesWithIt, name, ["Dnscache"])], - Problems = [] - }) - ], - Problems = [] - }; + // A plan ending several processes at once, which can never be confirmed, moved to + // PlanConfirmationGuards on 2026-09-29 - it is the refusal of a selection that file is about. /// A plan with one entry, asked for in the given words, with one stop step. private static BulkPlan Asking(ActionKind kind) => new() diff --git a/tests/Bws.Gui.Tests/ForcedStopViewGuards.cs b/tests/Bws.Gui.Tests/ForcedStopViewGuards.cs index 8bdbf69..626df28 100644 --- a/tests/Bws.Gui.Tests/ForcedStopViewGuards.cs +++ b/tests/Bws.Gui.Tests/ForcedStopViewGuards.cs @@ -152,11 +152,11 @@ public async Task The_reason_for_the_name_stands_over_the_box_in_the_danger_styl var window = await ForcedSheet(); var (shown, said, danger, warnings, style) = WpfHost.On(() => ( - window.PlanPanel.Footer.PlanDanger.Visibility, - window.PlanPanel.Footer.PlanDanger.Text, + window.PlanPanel.Footer.Confirmation.PlanDanger.Visibility, + window.PlanPanel.Footer.Confirmation.PlanDanger.Text, Sheeted(window).Danger, Sheeted(window).Warnings, - window.PlanPanel.Footer.PlanDanger.Style)); + window.PlanPanel.Footer.Confirmation.PlanDanger.Style)); Assert.Equal(Visibility.Visible, shown); Assert.NotEqual(string.Empty, danger); diff --git a/tests/Bws.Gui.Tests/PlanConfirmationGuards.cs b/tests/Bws.Gui.Tests/PlanConfirmationGuards.cs new file mode 100644 index 0000000..b60fd1a --- /dev/null +++ b/tests/Bws.Gui.Tests/PlanConfirmationGuards.cs @@ -0,0 +1,188 @@ +using System.Windows; +using Bws.Core.Planning; +using Bws.Gui.ViewModels; + +namespace Bws.Gui.Tests; + +/// +/// The heavy ask on a SELECTION, which is refused rather than asked about - backlog 475, the owner's +/// decision of 2026-09-29. +/// +/// What stood here before was a dead end that said it was a door. A stop over a whole scope +/// put the machine's critical entries in one plan, the box asked for the FIRST entry's name - an +/// entry the warning was not about - and the button refused every plan about more than one entry +/// anyway, so the name was typed and nothing changed. The refusal stays, and these hold the half +/// that was missing: that the screen says it is one. +/// +/// The model and the control are asserted apart. The model can be right while the markup +/// binds to a property it misspells, and a binding to nothing resolves in silence - so the second +/// half builds the control and reads what it drew. +/// +public sealed class PlanConfirmationGuards +{ + [Fact] + public void A_selection_holding_a_critical_entry_is_refused_rather_than_asked_for_a_name() + { + var panel = new Planned { Elevated = true }; + + panel.Show(Selection("AdobeARMservice", "RpcSs")); + + Assert.True(panel.RefusesSelection); + Assert.False(panel.NeedsTyping); + Assert.Equal(string.Empty, panel.TypeToConfirm); + Assert.Contains("RpcSs", panel.Danger, StringComparison.Ordinal); + + // No name opens it - neither the entry the box used to ask for nor the one the warning is + // about - because one name agreeing to several entries is what the refusal exists against. + foreach (var typed in new[] { "AdobeARMservice", "RpcSs", string.Empty }) + { + panel.Typed = typed; + + Assert.False(panel.CanCarryOut, typed); + } + + // And the button says the sentence the footer does, not "type a name in the box above". + Assert.Equal(Bws.Gui.Texts.Of("gui.plan.confirm.selection"), panel.CarryOutTip); + } + + [Fact] + public void A_selection_without_one_asks_for_nothing() + { + var panel = new Planned { Elevated = true }; + + panel.Show(Selection("AdobeARMservice", "Spooler")); + + Assert.False(panel.RefusesSelection); + Assert.False(panel.AsksHeavily); + Assert.True(panel.CanCarryOut); + } + + [Fact] + public void A_refused_selection_shows_its_sentence_where_the_box_would_stand_and_no_box() + { + var (refusal, boxShown, danger) = Drawn(Selection("AdobeARMservice", "RpcSs")); + + Assert.Equal(Visibility.Visible, refusal); + Assert.False(boxShown); + Assert.Contains("RpcSs", danger, StringComparison.Ordinal); + } + + [Fact] + public void One_critical_entry_shows_the_box_and_no_refusal() + { + var (refusal, boxShown, _) = Drawn(Selection("RpcSs")); + + Assert.True(boxShown); + Assert.Equal(Visibility.Collapsed, refusal); + } + + /// + /// `docs/10` trap 8: a UserControl is a ContentControl and arrives focusable and a Tab stop, so + /// the section carried out of the footer would put a silent stop in front of the box it holds. + /// + [Fact] + public void The_section_is_not_a_stop_on_the_way_to_the_box() + { + var (focusable, tabStop) = WpfHost.On(() => + { + var view = new PlanConfirmation(); + + return (view.Focusable, view.IsTabStop); + }); + + Assert.False(focusable); + Assert.False(tabStop); + } + + /// + /// A plan asking about more than one entry can never be confirmed, because there is no single + /// name to type for it - and since 2026-09-29 (backlog 475) it says so with a refusal rather + /// than a box asking for a name that would change nothing. Moved here from ForcedStopGuards + /// that day, because the refusal of a selection is what this file is about. + /// + /// Unreachable for a FORCING ask and guarded anyway, which is the whole argument for the + /// clause. Section 15.6 of the analysis records that bulk forcing cannot be reached - the + /// window opens this sheet from one failure and the command line takes one name - so this is + /// what happens if that ever stops being true. Accepting one name for several processes would be + /// somebody agreeing to the first entry and getting all of them, which is the shape rule 5 of + /// the untouchable rules exists against: the preview and the press saying different things. + /// + [Fact] + public void A_plan_that_would_end_several_processes_can_never_be_confirmed() + { + var panel = new Planned { Elevated = true }; + + panel.Show(ForcingTwo()); + + Assert.True(panel.RefusesSelection); + Assert.False(panel.NeedsTyping); + Assert.False(panel.CanCarryOut); + + // NEITHER NAME LETS IT THROUGH, and nor does an empty box - which is the failure this + // clause was written against: TypeTheName answers with the first entry alone, so a plain + // comparison would have accepted one name for two processes. + foreach (var typed in new[] { "Spooler", "W32Time", string.Empty, " " }) + { + panel.Typed = typed; + + Assert.False(panel.CanCarryOut, typed); + } + } + + /// Two entries, each ending a process of its own. Nothing in this product builds one. + private static BulkPlan ForcingTwo() => new() + { + Action = new BulkAction(ActionKind.ForceStop, ["Spooler", "W32Time"]), + Plans = + [ + .. new[] { "Spooler", "W32Time" }.Select((name, at) => new OperationPlan + { + Action = new ServiceAction(ActionKind.ForceStop, name), + Steps = + [ + new PlanStep( + name, name, StepOperation.Terminate, + StepReason.Requested, ProcessId: 4812 + at) + ], + Warnings = [new PlanWarning(PlanWarningKind.TerminationTakesWithIt, name, ["Dnscache"])], + Problems = [] + }) + ], + Problems = [] + }; + + private static (Visibility Refusal, bool BoxShown, string Danger) Drawn(BulkPlan plan) + { + var panel = new Planned { Elevated = true }; + + panel.Show(plan); + + var view = WpfHost.On(() => new PlanConfirmation { DataContext = panel }); + + // Settled between handing over the data and reading the control - a binding is evaluated + // by the dispatcher after the code that set the DataContext, ForcedStopFixture.OfferedBy. + WpfHost.Settled(); + + return WpfHost.On(() => (view.PlanRefusesSelection.Visibility, view.BoxShown, view.PlanDanger.Text)); + } + + /// + /// An ordinary stop of the names given, with RpcSs - one of the seven entries the machine does + /// not work without - carrying the warning the core raises about it, and nothing else carrying any. + /// + private static BulkPlan Selection(params string[] names) => new() + { + Action = new BulkAction(ActionKind.Stop, names), + Plans = + [ + .. names.Select(name => new OperationPlan + { + Action = new ServiceAction(ActionKind.Stop, name), + Steps = [new PlanStep(name, name, StepOperation.Stop, StepReason.Requested)], + Warnings = name == "RpcSs" ? [new PlanWarning(PlanWarningKind.CriticalService, name, [name])] : [], + Problems = [] + }) + ], + Problems = [] + }; +}