├── .cargo ├── config.toml └── ms-toolchain-config.toml ├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── Bug_Report.yml │ ├── Feature_Request.yml │ └── config.yml ├── actions │ └── fix-environment │ │ └── action.yml ├── policies │ └── resourceManagement.yml └── workflows │ └── pr-build.yaml ├── .gitignore ├── .pipelines ├── OneBranch.Buddy.yml ├── OneBranch.Common.yml ├── PR.Pipeline.yml ├── Standard.Pipeline.yml ├── convert-resx-to-rc.ps1 ├── daily-loc-build.yml └── steps-fetch-and-prepare-localizations.yml ├── Building.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── NOTICE.md ├── README.md ├── SECURITY.md ├── SUPPORT.md ├── cpp ├── logging │ ├── EventViewerLogging.c │ ├── README.md │ └── instrumentation.man └── rpc │ ├── README.md │ ├── RpcClient.c │ ├── sudo_rpc.acf │ └── sudo_rpc.idl ├── docs ├── generate.bat ├── obsidian-callouts.lua ├── settings-app-toggle.png ├── sudo-conhost.png ├── sudo-terminal-multi.png ├── sudo-terminal-redirected.png ├── sudo-terminal-service.png ├── sudo-terminal-single.png ├── sudo.png └── versions.md ├── enable_sudo.cmd ├── img ├── Windows │ ├── AppList.scale-100.png │ ├── AppList.scale-100_altform-colorful_theme-light.png │ ├── AppList.scale-125.png │ ├── AppList.scale-125_altform-colorful_theme-light.png │ ├── AppList.scale-150.png │ ├── AppList.scale-150_altform-colorful_theme-light.png │ ├── AppList.scale-200.png │ ├── AppList.scale-200_altform-colorful_theme-light.png │ ├── AppList.scale-400.png │ ├── AppList.scale-400_altform-colorful_theme-light.png │ ├── AppList.targetsize-16.png │ ├── AppList.targetsize-16_altform-lightunplated.png │ ├── AppList.targetsize-16_altform-unplated.png │ ├── AppList.targetsize-20.png │ ├── AppList.targetsize-20_altform-lightunplated.png │ ├── AppList.targetsize-20_altform-unplated.png │ ├── AppList.targetsize-24.png │ ├── AppList.targetsize-24_altform-lightunplated.png │ ├── AppList.targetsize-24_altform-unplated.png │ ├── AppList.targetsize-256.png │ ├── AppList.targetsize-256_altform-lightunplated.png │ ├── AppList.targetsize-256_altform-unplated.png │ ├── AppList.targetsize-30.png │ ├── AppList.targetsize-30_altform-lightunplated.png │ ├── AppList.targetsize-30_altform-unplated.png │ ├── AppList.targetsize-32.png │ ├── AppList.targetsize-32_altform-lightunplated.png │ ├── AppList.targetsize-32_altform-unplated.png │ ├── AppList.targetsize-36.png │ ├── AppList.targetsize-36_altform-lightunplated.png │ ├── AppList.targetsize-36_altform-unplated.png │ ├── AppList.targetsize-40.png │ ├── AppList.targetsize-40_altform-lightunplated.png │ ├── AppList.targetsize-40_altform-unplated.png │ ├── AppList.targetsize-48.png │ ├── AppList.targetsize-48_altform-lightunplated.png │ ├── AppList.targetsize-48_altform-unplated.png │ ├── AppList.targetsize-56.png │ ├── AppList.targetsize-56_altform-lightunplated.png │ ├── AppList.targetsize-56_altform-unplated.png │ ├── AppList.targetsize-60.png │ ├── AppList.targetsize-60_altform-lightunplated.png │ ├── AppList.targetsize-60_altform-unplated.png │ ├── AppList.targetsize-64.png │ ├── AppList.targetsize-64_altform-lightunplated.png │ ├── AppList.targetsize-64_altform-unplated.png │ ├── AppList.targetsize-72.png │ ├── AppList.targetsize-72_altform-lightunplated.png │ ├── AppList.targetsize-72_altform-unplated.png │ ├── AppList.targetsize-80.png │ ├── AppList.targetsize-80_altform-lightunplated.png │ ├── AppList.targetsize-80_altform-unplated.png │ ├── AppList.targetsize-96.png │ ├── AppList.targetsize-96_altform-lightunplated.png │ ├── AppList.targetsize-96_altform-unplated.png │ ├── BadgeLogo.scale-100.png │ ├── BadgeLogo.scale-125.png │ ├── BadgeLogo.scale-150.png │ ├── BadgeLogo.scale-200.png │ ├── BadgeLogo.scale-400.png │ ├── LargeTile.scale-100.png │ ├── LargeTile.scale-100_altform-colorful_theme-light.png │ ├── LargeTile.scale-125.png │ ├── LargeTile.scale-125_altform-colorful_theme-light.png │ ├── LargeTile.scale-150.png │ ├── LargeTile.scale-150_altform-colorful_theme-light.png │ ├── LargeTile.scale-200.png │ ├── LargeTile.scale-200_altform-colorful_theme-light.png │ ├── LargeTile.scale-400.png │ ├── LargeTile.scale-400_altform-colorful_theme-light.png │ ├── MedTile.scale-100.png │ ├── MedTile.scale-100_altform-colorful_theme-light.png │ ├── MedTile.scale-125.png │ ├── MedTile.scale-125_altform-colorful_theme-light.png │ ├── MedTile.scale-150.png │ ├── MedTile.scale-150_altform-colorful_theme-light.png │ ├── MedTile.scale-200.png │ ├── MedTile.scale-200_altform-colorful_theme-light.png │ ├── MedTile.scale-400.png │ ├── MedTile.scale-400_altform-colorful_theme-light.png │ ├── SmallTile.scale-100.png │ ├── SmallTile.scale-100_altform-colorful_theme-light.png │ ├── SmallTile.scale-125.png │ ├── SmallTile.scale-125_altform-colorful_theme-light.png │ ├── SmallTile.scale-150.png │ ├── SmallTile.scale-150_altform-colorful_theme-light.png │ ├── SmallTile.scale-200.png │ ├── SmallTile.scale-200_altform-colorful_theme-light.png │ ├── SmallTile.scale-400.png │ ├── SmallTile.scale-400_altform-colorful_theme-light.png │ ├── SplashScreen.scale-100.png │ ├── SplashScreen.scale-100_altform-colorful_theme-dark.png │ ├── SplashScreen.scale-100_altform-colorful_theme-light.png │ ├── SplashScreen.scale-125.png │ ├── SplashScreen.scale-125_altform-colorful_theme-dark.png │ ├── SplashScreen.scale-125_altform-colorful_theme-light.png │ ├── SplashScreen.scale-150.png │ ├── SplashScreen.scale-150_altform-colorful_theme-dark.png │ ├── SplashScreen.scale-150_altform-colorful_theme-light.png │ ├── SplashScreen.scale-200.png │ ├── SplashScreen.scale-200_altform-colorful_theme-dark.png │ ├── SplashScreen.scale-200_altform-colorful_theme-light.png │ ├── SplashScreen.scale-400.png │ ├── SplashScreen.scale-400_altform-colorful_theme-dark.png │ ├── SplashScreen.scale-400_altform-colorful_theme-light.png │ ├── StoreDisplay-150.png │ ├── StoreDisplay-300.png │ ├── StoreDisplay-71.png │ ├── StoreLogo.scale-100.png │ ├── StoreLogo.scale-100_altform-colorful_theme-light.png │ ├── StoreLogo.scale-125.png │ ├── StoreLogo.scale-125_altform-colorful_theme-light.png │ ├── StoreLogo.scale-150.png │ ├── StoreLogo.scale-150_altform-colorful_theme-light.png │ ├── StoreLogo.scale-200.png │ ├── StoreLogo.scale-200_altform-colorful_theme-light.png │ ├── StoreLogo.scale-400.png │ ├── StoreLogo.scale-400_altform-colorful_theme-light.png │ ├── WideTile.scale-100.png │ ├── WideTile.scale-100_altform-colorful_theme-light.png │ ├── WideTile.scale-125.png │ ├── WideTile.scale-125_altform-colorful_theme-light.png │ ├── WideTile.scale-150.png │ ├── WideTile.scale-150_altform-colorful_theme-light.png │ ├── WideTile.scale-200.png │ ├── WideTile.scale-200_altform-colorful_theme-light.png │ ├── WideTile.scale-400.png │ └── WideTile.scale-400_altform-colorful_theme-light.png ├── ico │ ├── Sudo.ico │ ├── _16.png │ ├── _20.png │ ├── _24.png │ ├── _256.png │ ├── _32.png │ ├── _40.png │ ├── _48.png │ └── _64.png └── svg │ └── ic_fluent_Sudo.svg ├── owners.txt ├── scripts └── sudo.ps1 ├── sudo ├── Cargo.toml ├── Resources │ └── en-US │ │ └── Sudo.resw ├── build.rs ├── src │ ├── elevate_handler.rs │ ├── helpers.rs │ ├── logging_bindings.rs │ ├── main.rs │ ├── messages.rs │ ├── r.rs │ ├── rpc_bindings.rs │ ├── rpc_bindings_client.rs │ ├── rpc_bindings_server.rs │ ├── run_handler.rs │ ├── tests │ │ └── mod.rs │ └── tracing.rs ├── sudo.manifest └── sudo.rc ├── sudo_events ├── Cargo.toml ├── build.rs └── src │ ├── events_template.rs │ └── lib.rs ├── tools ├── gen-lang-codes.ps1 ├── sudo.tvpp └── tests.ipynb └── win32resources ├── Cargo.toml └── src └── lib.rs /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | # -Ccontrol-flow-guard: Enable Control Flow Guard, needed for OneBranch's post-build analysis (https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard). 2 | [target.'cfg(target_os = "windows")'] 3 | rustflags = [ 4 | "-Dwarnings", 5 | "-Ccontrol-flow-guard", 6 | "-Ctarget-feature=+crt-static", 7 | "-Clink-args=/DEFAULTLIB:ucrt.lib /NODEFAULTLIB:vcruntime.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libucrt.lib" 8 | ] 9 | 10 | # This fixes the following linker error on x86: 11 | # error LNK2019: unresolved external symbol _NdrClientCall4 referenced in function ... 12 | [target.'cfg(all(target_os = "windows", target_arch = "x86"))'] 13 | rustflags = ["-Clink-args=/DEFAULTLIB:rpcrt4.lib"] 14 | 15 | # -Clink-args=/DYNAMICBASE /CETCOMPAT: Enable "shadow stack" (https://learn.microsoft.com/en-us/cpp/build/reference/cetcompat) 16 | [target.'cfg(all(target_os = "windows", any(target_arch = "x86", target_arch = "x86_64")))'] 17 | rustflags = ["-Clink-args=/DYNAMICBASE /CETCOMPAT"] 18 | 19 | [registries] 20 | Sudo_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/shine-oss/sudo/_packaging/Sudo_PublicPackages/Cargo/index/" } 21 | [source.crates-io] 22 | replace-with = "Sudo_PublicPackages" 23 | -------------------------------------------------------------------------------- /.cargo/ms-toolchain-config.toml: -------------------------------------------------------------------------------- 1 | # -Cehcont_guard: Enable EH Continuation Metadata (https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-eh-continuation-metadata). 2 | # -Ccontrol-flow-guard: Enable Control Flow Guard, needed for OneBranch's post-build analysis (https://learn.microsoft.com/en-us/cpp/build/reference/guard-enable-control-flow-guard). 3 | [target.'cfg(target_os = "windows")'] 4 | rustflags = [ 5 | "-Cehcont_guard", 6 | "-Ccontrol-flow-guard", 7 | "-Ctarget-feature=+crt-static", 8 | "-Clink-args=/DEFAULTLIB:ucrt.lib /NODEFAULTLIB:vcruntime.lib /NODEFAULTLIB:msvcrt.lib /NODEFAULTLIB:libucrt.lib" 9 | ] 10 | 11 | # This fixes the following linker error on x86: 12 | # error LNK2019: unresolved external symbol _NdrClientCall4 referenced in function ... 13 | [target.'cfg(all(target_os = "windows", target_arch = "x86"))'] 14 | rustflags = ["-Clink-args=/DEFAULTLIB:rpcrt4.lib"] 15 | 16 | # -Clink-args=/DYNAMICBASE /CETCOMPAT: Enable "shadow stack" (https://learn.microsoft.com/en-us/cpp/build/reference/cetcompat) 17 | [target.'cfg(all(target_os = "windows", any(target_arch = "x86", target_arch = "x86_64")))'] 18 | rustflags = ["-Clink-args=/DYNAMICBASE /CETCOMPAT"] 19 | 20 | # Setup the ADO Artifacts feed as a Registry: you'll need to use your own feed in your project that upstreams from crates.io. 21 | # For more details see https://eng.ms/docs/cloud-ai-platform/devdiv/one-engineering-system-1es/1es-docs/azure-artifacts/cargo 22 | [registries] 23 | Sudo_PublicPackages = { index = "sparse+https://pkgs.dev.azure.com/shine-oss/sudo/_packaging/Sudo_PublicPackages/Cargo/index/" } 24 | [source.crates-io] 25 | replace-with = "Sudo_PublicPackages" 26 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | Language: Cpp 3 | BasedOnStyle: Microsoft 4 | AccessModifierOffset: -4 5 | AlignEscapedNewlines: Left 6 | AlignTrailingComments: false 7 | AllowAllParametersOfDeclarationOnNextLine: false 8 | AllowShortFunctionsOnASingleLine: All 9 | AlwaysBreakTemplateDeclarations: Yes 10 | BinPackArguments: false 11 | BinPackParameters: false 12 | BraceWrapping: 13 | AfterCaseLabel: true 14 | AfterUnion: true 15 | AfterExternBlock: false 16 | BreakBeforeTernaryOperators: false 17 | BreakConstructorInitializers: AfterColon 18 | BreakInheritanceList: AfterColon 19 | ColumnLimit: 0 20 | CommentPragmas: "suppress" 21 | ConstructorInitializerAllOnOneLineOrOnePerLine: true 22 | Cpp11BracedListStyle: false 23 | FixNamespaceComments: false 24 | IncludeBlocks: Regroup 25 | IncludeCategories: 26 | - Regex: '^.*(precomp|pch|stdafx)' 27 | Priority: -1 28 | - Regex: '^".*"' 29 | Priority: 1 30 | - Regex: '^<.*>' 31 | Priority: 2 32 | - Regex: '.*' 33 | Priority: 3 34 | KeepEmptyLinesAtTheStartOfBlocks: false 35 | MacroBlockBegin: "BEGIN_TEST_METHOD_PROPERTIES|BEGIN_MODULE|BEGIN_TEST_CLASS|BEGIN_TEST_METHOD" 36 | MacroBlockEnd: "END_TEST_METHOD_PROPERTIES|END_MODULE|END_TEST_CLASS|END_TEST_METHOD" 37 | NamespaceIndentation: All 38 | PointerAlignment: Left 39 | ReflowComments: false 40 | SortIncludes: false 41 | SpaceAfterTemplateKeyword: false 42 | SpacesInAngles: false 43 | SpacesInContainerLiterals: false 44 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Bug_Report.yml: -------------------------------------------------------------------------------- 1 | name: "Bug report 🐛" 2 | description: Report errors or unexpected behavior 3 | labels: [Issue-Bug, Needs-Triage] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | Please make sure to [search for existing issues](https://github.com/microsoft/sudo/issues) and [check the FAQ](https://github.com/microsoft/sudo/wiki/Frequently-Asked-Questions-(FAQ)) before filing a new one! 9 | If this is an application crash, please also provide a [Feedback Hub](https://aka.ms/sudo-feedback-hub) submission link so we can find your diagnostic data on the backend. Use the category "Apps > Windows Terminal" and choose "Share My Feedback" after submission to get the link. 10 | 11 | - type: input 12 | attributes: 13 | label: Sudo for Windows version 14 | placeholder: "1.0.0" 15 | description: | 16 | You can find this with `sudo.exe --version` on the command line. 17 | validations: 18 | required: true 19 | 20 | - type: input 21 | attributes: 22 | label: Windows build number 23 | placeholder: "10.0.26052.0" 24 | description: | 25 | Please run `ver` or `[Environment]::OSVersion`. Alternatively, the following command in PowerShell: 26 | Write-Host "Windows build: $((Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").BuildLabEx)" 27 | validations: 28 | required: true 29 | 30 | - type: textarea 31 | attributes: 32 | label: Other Software 33 | description: If you're reporting a bug about our interaction with other software, what software? What versions? 34 | placeholder: | 35 | vim 8.2 (inside WSL) 36 | OpenSSH_for_Windows_8.1p1 37 | My Cool Application v0.3 (include a code snippet if it would help!) 38 | validations: 39 | required: false 40 | 41 | - type: textarea 42 | attributes: 43 | label: Steps to reproduce 44 | placeholder: Tell us the steps required to trigger your bug. 45 | validations: 46 | required: true 47 | 48 | - type: textarea 49 | attributes: 50 | label: Expected Behavior 51 | description: If you want to include screenshots, paste them into the markdown editor below. 52 | placeholder: What were you expecting? 53 | validations: 54 | required: false 55 | 56 | - type: textarea 57 | attributes: 58 | label: Actual Behavior 59 | placeholder: What happened instead? 60 | validations: 61 | required: true 62 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_Request.yml: -------------------------------------------------------------------------------- 1 | name: "⭐ Feature or enhancement request" 2 | description: Propose something new. 3 | labels: [Issue-Feature, Needs-Triage] 4 | body: 5 | - type: textarea 6 | attributes: 7 | label: Description of the new feature / enhancement 8 | placeholder: What is the expected behavior of the proposed feature? 9 | validations: 10 | required: true 11 | - type: textarea 12 | attributes: 13 | label: Scenario when this would be used? 14 | placeholder: What is the scenario this would be used? Why is this important? 15 | validations: 16 | required: true 17 | - type: textarea 18 | attributes: 19 | label: Supporting information 20 | placeholder: "Having additional evidence, data, tweets, blog posts, research, ... anything is extremely helpful. This information provides context to the scenario that may otherwise be lost." 21 | validations: 22 | required: false 23 | - type: markdown 24 | attributes: 25 | value: Please limit one request per issue. 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: true 2 | 3 | contact_links: 4 | - name: Have a question? 🤔 5 | url: https://github.com/microsoft/sudo/discussions 6 | about: Have question about sudo you think we can answer? Try a discussion thread! 7 | - name: Microsoft Security Response Center 🔐 8 | url: https://msrc.microsoft.com/create-report 9 | about: Please report security vulnerabilities here. 10 | - name: Sudo for Windows Documentation issue 📄 11 | url: https://github.com/MicrosoftDocs/windows-dev-docs/hub/sudo 12 | about: Report issues with the documentation for Sudo for Windows (in https://learn.microsoft.com/windows/sudo) 13 | -------------------------------------------------------------------------------- /.github/actions/fix-environment/action.yml: -------------------------------------------------------------------------------- 1 | name: Fix environment 2 | description: GitHub VMs aren't configured correctly 3 | # Shamelessly borrowed from https://github.com/microsoft/windows-rs/blob/master/.github/actions/fix-environment/action.yml 4 | runs: 5 | using: "composite" 6 | steps: 7 | - name: Configure environment 8 | shell: pwsh 9 | run: | 10 | $vs_root = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" ` 11 | -latest -property installationPath -format value 12 | 13 | switch -Wildcard ("${{ matrix.target }}") 14 | { 15 | "*-pc-windows-gnu" 16 | { 17 | "C:\msys64\mingw64\bin;C:\msys64\mingw32\bin" >> $env:GITHUB_PATH 18 | } 19 | "i686*" 20 | { 21 | "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x86" >> $env:GITHUB_PATH 22 | ((Resolve-Path "$vs_root\VC\Tools\MSVC\*\bin\Hostx86\x86") 23 | | Sort-Object -Descending | Select -First 1).ToString() >> $env:GITHUB_PATH 24 | } 25 | "x86_64*" 26 | { 27 | "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x64" >> $env:GITHUB_PATH 28 | ((Resolve-Path "$vs_root\VC\Tools\MSVC\*\bin\Hostx64\x64") 29 | | Sort-Object -Descending | Select -First 1).ToString() >> $env:GITHUB_PATH 30 | } 31 | "aarch64*" 32 | { 33 | "${env:ProgramFiles(x86)}\Windows Kits\10\bin\10.0.22000.0\x64" >> $env:GITHUB_PATH 34 | ((Resolve-Path "$vs_root\VC\Tools\MSVC\*\bin\Hostx64\x64") 35 | | Sort-Object -Descending | Select -First 1).ToString() >> $env:GITHUB_PATH 36 | } 37 | "*" 38 | { 39 | (Join-Path $env:GITHUB_WORKSPACE "target\debug\deps").ToString() >> $env:GITHUB_PATH 40 | (Join-Path $env:GITHUB_WORKSPACE "target\test\debug\deps").ToString() >> $env:GITHUB_PATH 41 | "INCLUDE=${env:ProgramFiles(x86)}\Windows Kits\10\include\10.0.22000.0\winrt;${env:ProgramFiles(x86)}\Windows Kits\10\include\10.0.22000.0\cppwinrt" ` 42 | >> $env:GITHUB_ENV 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /.github/policies/resourceManagement.yml: -------------------------------------------------------------------------------- 1 | id: 2 | name: GitOps.PullRequestIssueManagement 3 | description: GitOps.PullRequestIssueManagement primitive 4 | owner: 5 | resource: repository 6 | disabled: false 7 | where: 8 | configuration: 9 | resourceManagementConfiguration: 10 | scheduledSearches: 11 | - description: 12 | frequencies: 13 | - hourly: 14 | hour: 3 15 | filters: 16 | - isIssue 17 | - isOpen 18 | - hasLabel: 19 | label: Needs-Author-Feedback 20 | - hasLabel: 21 | label: No-Recent-Activity 22 | - noActivitySince: 23 | days: 3 24 | actions: 25 | - closeIssue 26 | - description: 27 | frequencies: 28 | - hourly: 29 | hour: 3 30 | filters: 31 | - isIssue 32 | - isOpen 33 | - hasLabel: 34 | label: Needs-Author-Feedback 35 | - noActivitySince: 36 | days: 4 37 | - isNotLabeledWith: 38 | label: No-Recent-Activity 39 | actions: 40 | - addLabel: 41 | label: No-Recent-Activity 42 | - addReply: 43 | reply: This issue has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **4 days**. It will be closed if no further activity occurs **within 3 days of this comment**. 44 | - description: 45 | frequencies: 46 | - hourly: 47 | hour: 3 48 | filters: 49 | - isIssue 50 | - isOpen 51 | - hasLabel: 52 | label: Resolution-Duplicate 53 | - noActivitySince: 54 | days: 1 55 | actions: 56 | - addReply: 57 | reply: This issue has been marked as duplicate and has not had any activity for **1 day**. It will be closed for housekeeping purposes. 58 | - closeIssue 59 | - description: 60 | frequencies: 61 | - hourly: 62 | hour: 3 63 | filters: 64 | - isPullRequest 65 | - isOpen 66 | - hasLabel: 67 | label: Needs-Author-Feedback 68 | - hasLabel: 69 | label: No-Recent-Activity 70 | - noActivitySince: 71 | days: 7 72 | actions: 73 | - closeIssue 74 | - description: 75 | frequencies: 76 | - hourly: 77 | hour: 3 78 | filters: 79 | - isPullRequest 80 | - isOpen 81 | - hasLabel: 82 | label: Needs-Author-Feedback 83 | - noActivitySince: 84 | days: 7 85 | - isNotLabeledWith: 86 | label: No-Recent-Activity 87 | actions: 88 | - addLabel: 89 | label: No-Recent-Activity 90 | - addReply: 91 | reply: This pull request has been automatically marked as stale because it has been marked as requiring author feedback but has not had any activity for **7 days**. It will be closed if no further activity occurs **within 7 days of this comment**. 92 | eventResponderTasks: 93 | - if: 94 | - payloadType: Issues 95 | - or: 96 | - and: 97 | - isAction: 98 | action: Opened 99 | - not: 100 | hasLabel: 101 | label: ⛺ Reserved 102 | then: 103 | - addLabel: 104 | label: Needs-Triage 105 | description: 106 | - if: 107 | - payloadType: Issue_Comment 108 | - isAction: 109 | action: Created 110 | - isActivitySender: 111 | issueAuthor: True 112 | - hasLabel: 113 | label: Needs-Author-Feedback 114 | then: 115 | - addLabel: 116 | label: Needs-Attention 117 | - removeLabel: 118 | label: Needs-Author-Feedback 119 | description: 120 | - if: 121 | - payloadType: Issues 122 | - not: 123 | isAction: 124 | action: Closed 125 | - hasLabel: 126 | label: No-Recent-Activity 127 | then: 128 | - removeLabel: 129 | label: No-Recent-Activity 130 | description: 131 | - if: 132 | - payloadType: Issue_Comment 133 | - hasLabel: 134 | label: No-Recent-Activity 135 | then: 136 | - removeLabel: 137 | label: No-Recent-Activity 138 | description: 139 | - if: 140 | - payloadType: Pull_Request_Review 141 | - isAction: 142 | action: Submitted 143 | - isReviewState: 144 | reviewState: Changes_requested 145 | then: 146 | - addLabel: 147 | label: Needs-Author-Feedback 148 | description: 149 | - if: 150 | - payloadType: Pull_Request 151 | - isActivitySender: 152 | issueAuthor: True 153 | - not: 154 | isAction: 155 | action: Closed 156 | - hasLabel: 157 | label: Needs-Author-Feedback 158 | then: 159 | - removeLabel: 160 | label: Needs-Author-Feedback 161 | description: 162 | - if: 163 | - payloadType: Issue_Comment 164 | - isActivitySender: 165 | issueAuthor: True 166 | - hasLabel: 167 | label: Needs-Author-Feedback 168 | then: 169 | - removeLabel: 170 | label: Needs-Author-Feedback 171 | description: 172 | - if: 173 | - payloadType: Pull_Request_Review 174 | - isActivitySender: 175 | issueAuthor: True 176 | - hasLabel: 177 | label: Needs-Author-Feedback 178 | then: 179 | - removeLabel: 180 | label: Needs-Author-Feedback 181 | description: 182 | - if: 183 | - payloadType: Pull_Request 184 | - not: 185 | isAction: 186 | action: Closed 187 | - hasLabel: 188 | label: No-Recent-Activity 189 | then: 190 | - removeLabel: 191 | label: No-Recent-Activity 192 | description: 193 | - if: 194 | - payloadType: Issue_Comment 195 | - hasLabel: 196 | label: No-Recent-Activity 197 | then: 198 | - removeLabel: 199 | label: No-Recent-Activity 200 | description: 201 | - if: 202 | - payloadType: Pull_Request_Review 203 | - hasLabel: 204 | label: No-Recent-Activity 205 | then: 206 | - removeLabel: 207 | label: No-Recent-Activity 208 | description: 209 | - if: 210 | - payloadType: Pull_Request 211 | - hasLabel: 212 | label: AutoMerge 213 | then: 214 | - enableAutoMerge: 215 | mergeMethod: Squash 216 | description: 217 | - if: 218 | - payloadType: Pull_Request 219 | - labelRemoved: 220 | label: AutoMerge 221 | then: 222 | - disableAutoMerge 223 | description: 224 | - if: 225 | - payloadType: Pull_Request 226 | then: 227 | - inPrLabel: 228 | label: In-PR 229 | description: 230 | - if: 231 | - payloadType: Issues 232 | - hasLabel: 233 | label: Needs-Tag-Fix 234 | - hasLabel: 235 | label: Resolution-Duplicate 236 | then: 237 | - removeLabel: 238 | label: Needs-Tag-Fix 239 | description: 240 | - if: 241 | - payloadType: Issues 242 | - or: 243 | - titleContains: 244 | pattern: ^\s*Bug Report \(IF I DO NOT CHANGE THIS THE ISSUE WILL BE AUTO-CLOSED\)\s*$ 245 | isRegex: True 246 | - titleContains: 247 | pattern: ^\s*Bug Report\s*$ 248 | isRegex: True 249 | - or: 250 | - isAction: 251 | action: Opened 252 | - isAction: 253 | action: Reopened 254 | - not: 255 | activitySenderHasPermission: 256 | permission: Write 257 | - not: 258 | activitySenderHasPermission: 259 | permission: Admin 260 | then: 261 | - closeIssue 262 | - addLabel: 263 | label: Needs-Author-Feedback 264 | - addReply: 265 | reply: Hi! Thanks for attempting to open an issue. Unfortunately, your title wasn't changed from the original template which makes it very hard for us to track and triage. You are welcome to fix up the title and try again with a new issue. 266 | description: 267 | - if: 268 | - payloadType: Issues 269 | - or: 270 | - isAction: 271 | action: Opened 272 | - isAction: 273 | action: Reopened 274 | - or: 275 | - not: 276 | bodyContains: 277 | pattern: .+ 278 | isRegex: True 279 | then: 280 | - closeIssue 281 | - addLabel: 282 | label: Needs-Author-Feedback 283 | - addReply: 284 | reply: "Hi! Thanks for attempting to open an issue. Unfortunately, you didn't write anything in the body which makes it impossible to understand your concern. You are welcome to fix up the issue and try again by opening another issue with the body filled out. " 285 | description: 286 | - if: 287 | - payloadType: Pull_Request 288 | - isLabeled 289 | - hasLabel: 290 | label: Needs-Second 291 | - isOpen 292 | then: 293 | - requestReview: 294 | reviewer: zadjii-msft 295 | - requestReview: 296 | reviewer: joadoumie 297 | - requestReview: 298 | reviewer: dhowett 299 | - requestReview: 300 | reviewer: lhecker 301 | description: 302 | - if: 303 | - payloadType: Pull_Request_Review 304 | - not: isOpen 305 | - hasLabel: 306 | label: Needs-Second 307 | then: 308 | - removeLabel: 309 | label: Needs-Second 310 | description: 311 | - if: 312 | - payloadType: Issues 313 | - hasLabel: 314 | label: In-PR 315 | - hasLabel: 316 | label: Help Wanted 317 | - isLabeled 318 | then: 319 | - removeLabel: 320 | label: Help-Wanted 321 | description: 322 | - if: 323 | - payloadType: Issue_Comment 324 | - commentContains: 325 | pattern: '\/dup(licate|e)?(\s+of)?\s+\#[\d]+' 326 | isRegex: True 327 | - or: 328 | - activitySenderHasPermission: 329 | permission: Admin 330 | - activitySenderHasPermission: 331 | permission: Write 332 | then: 333 | - addReply: 334 | reply: Hi! We've identified this issue as a duplicate of another one that already exists on this Issue Tracker. This specific instance is being closed in favor of tracking the concern over on the referenced thread. Thanks for your report! 335 | - closeIssue 336 | - removeLabel: 337 | label: Needs-Triage 338 | - addLabel: 339 | label: Resolution-Duplicate 340 | - removeLabel: 341 | label: Needs-Tag-Fix 342 | - removeLabel: 343 | label: Needs-Attention 344 | - removeLabel: 345 | label: Needs-Author-Feedback 346 | - removeLabel: 347 | label: Needs-Repro 348 | - removeLabel: 349 | label: Needs-Second 350 | description: 351 | - if: 352 | - payloadType: Issue_Comment 353 | - commentContains: 354 | pattern: '\/feedback' 355 | isRegex: True 356 | - or: 357 | - activitySenderHasPermission: 358 | permission: Admin 359 | - activitySenderHasPermission: 360 | permission: Write 361 | then: 362 | - addReply: 363 | reply: >2- 364 | 365 | Hi there!

Can you please send us feedback with the [Feedback Hub](https://support.microsoft.com/en-us/windows/send-feedback-to-microsoft-with-the-feedback-hub-app-f59187f8-8739-22d6-ba93-f66612949332) with this issue? Make sure to click the "Start recording" button, then reproduce the issue before submitting the feedback. Once it's submitted, paste the link here so we can more easily find your crash information on the back end?

Thanks!

![image](https://user-images.githubusercontent.com/18356694/140811502-a068f78b-89d2-4587-925a-73e19652b830.png)

![image](https://user-images.githubusercontent.com/18356694/140811557-cdc22a0f-fa6a-4f6a-953e-73b51f5548a3.png)

![image](https://user-images.githubusercontent.com/18221333/62478649-6de55400-b760-11e9-806e-5aab7e085a9f.png) 366 | - addLabel: 367 | label: Needs-Author-Feedback 368 | description: 369 | - if: 370 | - payloadType: Issue_Comment 371 | then: 372 | - cleanEmailReply 373 | description: 374 | - if: 375 | - payloadType: Pull_Request 376 | then: 377 | - labelSync: 378 | pattern: Issue- 379 | - labelSync: 380 | pattern: Area- 381 | - labelSync: 382 | pattern: Priority- 383 | - labelSync: 384 | pattern: Product- 385 | - labelSync: 386 | pattern: Severity- 387 | - labelSync: 388 | pattern: Impact- 389 | description: 390 | - if: 391 | - payloadType: Issue_Comment 392 | - commentContains: 393 | pattern: '\/dup(licate|e)?(\s+of)?\s+https' 394 | isRegex: True 395 | - or: 396 | - activitySenderHasPermission: 397 | permission: Admin 398 | - activitySenderHasPermission: 399 | permission: Write 400 | then: 401 | - addReply: 402 | reply: Hi! We've identified this issue as a duplicate of one that exists on somebody else's Issue Tracker. Please make sure you subscribe to the referenced external issue for future updates. Thanks for your report! 403 | - closeIssue 404 | - removeLabel: 405 | label: Needs-Triage 406 | - addLabel: 407 | label: Resolution-External 408 | - removeLabel: 409 | label: Needs-Attention 410 | - removeLabel: 411 | label: Needs-Author-Feedback 412 | - removeLabel: 413 | label: Needs-Bisect 414 | - removeLabel: 415 | label: Needs-Repro 416 | - removeLabel: 417 | label: Needs-Second 418 | description: 419 | - if: 420 | - payloadType: Issue_Comment 421 | - commentContains: 422 | pattern: /? 423 | isRegex: False 424 | - or: 425 | - activitySenderHasPermission: 426 | permission: Admin 427 | - activitySenderHasPermission: 428 | permission: Write 429 | then: 430 | - removeLabel: 431 | label: Needs-Attention 432 | - addLabel: 433 | label: Needs-Author-Feedback 434 | description: 435 | onFailure: 436 | onSuccess: -------------------------------------------------------------------------------- /.github/workflows/pr-build.yaml: -------------------------------------------------------------------------------- 1 | name: PR Build & Test 2 | 3 | on: 4 | pull_request: 5 | push: 6 | paths-ignore: 7 | - '.github/ISSUE_TEMPLATE/**' 8 | branches: 9 | - main 10 | 11 | jobs: 12 | check: 13 | runs-on: windows-2022 14 | 15 | strategy: 16 | matrix: 17 | # Apparently ARM targets aren't usable in GH actions 18 | # target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc, aarch64-pc-windows-msvc] 19 | target: [x86_64-pc-windows-msvc, i686-pc-windows-msvc] 20 | branding: [Inbox, Stable, Dev] 21 | 22 | steps: 23 | - name: Checkout 24 | uses: actions/checkout@v4 25 | 26 | - name: Update toolchain 27 | run: rustup update --no-self-update stable && rustup default stable-${{ matrix.target }} 28 | 29 | - name: Add toolchain target 30 | run: rustup target add ${{ matrix.target }} 31 | 32 | - name: Install fmt 33 | run: rustup component add rustfmt 34 | 35 | - name: Install clippy 36 | run: rustup component add clippy 37 | 38 | - name: Fix environment 39 | uses: ./.github/actions/fix-environment 40 | 41 | - name: Clean 42 | run: cargo clean 43 | 44 | - name: Run fmt 45 | run: cargo fmt --all -- --check 46 | 47 | # Test will build the code, then also test it. 48 | - name: Test 49 | run: cargo test --no-default-features --features ${{matrix.branding}} --target ${{ matrix.target }} 50 | 51 | - name: Run clippy 52 | run: cargo clippy --no-default-features --features ${{matrix.branding}} --target ${{matrix.target}} 2>&1 53 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | ARM64/ 21 | bld/ 22 | [Bb]in/ 23 | [Oo]bj/ 24 | [Ll]og/ 25 | objfre/ 26 | objchk/ 27 | 28 | # Visual Studio 2015 cache/options directory 29 | .vs/ 30 | 31 | # Visual Studio Code cache/options directory 32 | .vscode/ 33 | 34 | # MSTest test Results 35 | [Tt]est[Rr]esult*/ 36 | [Bb]uild[Ll]og.* 37 | 38 | # NUNIT 39 | *.VisualState.xml 40 | TestResult.xml 41 | 42 | # Build Results of an ATL Project 43 | [Dd]ebugPS/ 44 | [Rr]eleasePS/ 45 | dlldata.c 46 | 47 | # DNX 48 | project.lock.json 49 | artifacts/ 50 | 51 | *_h.h 52 | *_i.c 53 | *_p.c 54 | *_i.h 55 | *.ilk 56 | *.meta 57 | *.obj 58 | *.pch 59 | *.pdb 60 | *.pgc 61 | *.pgd 62 | *.rsp 63 | *.sbr 64 | *.tlb 65 | *.tli 66 | *.tlh 67 | *.tmp 68 | *.tmp_proj 69 | *.log 70 | *.vspscc 71 | *.vssscc 72 | .builds 73 | *.pidb 74 | *.svclog 75 | *.scc 76 | 77 | # Chutzpah Test files 78 | _Chutzpah* 79 | 80 | # Visual C++ cache files 81 | ipch/ 82 | *.aps 83 | *.ncb 84 | *.opendb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | *.VC.db 89 | *.VC.VC.opendb 90 | 91 | # Visual Studio profiler 92 | *.psess 93 | *.vsp 94 | *.vspx 95 | *.sap 96 | 97 | # TFS 2012 Local Workspace 98 | $tf/ 99 | 100 | # Guidance Automation Toolkit 101 | *.gpState 102 | 103 | # ReSharper is a .NET coding add-in 104 | _ReSharper*/ 105 | *.[Rr]e[Ss]harper 106 | *.DotSettings.user 107 | 108 | # JustCode is a .NET coding add-in 109 | .JustCode 110 | 111 | # TeamCity is a build add-in 112 | _TeamCity* 113 | 114 | # DotCover is a Code Coverage Tool 115 | *.dotCover 116 | 117 | # NCrunch 118 | _NCrunch_* 119 | .*crunch*.local.xml 120 | nCrunchTemp_* 121 | 122 | # MightyMoose 123 | *.mm.* 124 | AutoTest.Net/ 125 | 126 | # Web workbench (sass) 127 | .sass-cache/ 128 | 129 | # Installshield output folder 130 | [Ee]xpress/ 131 | 132 | # DocProject is a documentation generator add-in 133 | DocProject/buildhelp/ 134 | DocProject/Help/*.HxT 135 | DocProject/Help/*.HxC 136 | DocProject/Help/*.hhc 137 | DocProject/Help/*.hhk 138 | DocProject/Help/*.hhp 139 | DocProject/Help/Html2 140 | DocProject/Help/html 141 | 142 | # Click-Once directory 143 | publish/ 144 | 145 | # Publish Web Output 146 | *.[Pp]ublish.xml 147 | *.azurePubxml 148 | # TODO: Comment the next line if you want to check in your web deploy settings 149 | # but database connection strings (with potential passwords) will be unencrypted 150 | *.pubxml 151 | *.publishproj 152 | 153 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 154 | # check in your Azure Web App publish settings, but sensitive information contained 155 | # in these scripts will be unencrypted 156 | PublishScripts/ 157 | 158 | # NuGet Packages 159 | *.nupkg 160 | # The packages folder can be ignored because of Package Restore 161 | **/packages/* 162 | # except build/, which is used as an MSBuild target. 163 | !**/packages/build/ 164 | # Uncomment if necessary however generally it will be regenerated when needed 165 | #!**/packages/repositories.config 166 | # NuGet v3's project.json files produces more ignorable files 167 | *.nuget.props 168 | *.nuget.targets 169 | 170 | # Microsoft Azure Build Output 171 | csx/ 172 | *.build.csdef 173 | 174 | # Microsoft Azure Emulator 175 | ecf/ 176 | rcf/ 177 | 178 | # Windows Store app package directories and files 179 | AppPackages/ 180 | BundleArtifacts/ 181 | Package.StoreAssociation.xml 182 | _pkginfo.txt 183 | 184 | # Visual Studio cache files 185 | # files ending in .cache can be ignored 186 | *.[Cc]ache 187 | # but keep track of directories ending in .cache 188 | !*.[Cc]ache/ 189 | 190 | # Others 191 | ClientBin/ 192 | [Ss]tyle[Cc]op.* 193 | ~$* 194 | *~ 195 | *.dbmdl 196 | *.dbproj.schemaview 197 | *.pfx 198 | *.publishsettings 199 | node_modules/ 200 | orleans.codegen.cs 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # Node.js Tools for Visual Studio 226 | .ntvs_analysis.dat 227 | 228 | # Visual Studio 6 build log 229 | *.plg 230 | 231 | # Visual Studio 6 workspace options file 232 | *.opt 233 | 234 | # Visual Studio LightSwitch build output 235 | **/*.HTMLClient/GeneratedArtifacts 236 | **/*.DesktopClient/GeneratedArtifacts 237 | **/*.DesktopClient/ModelManifest.xml 238 | **/*.Server/GeneratedArtifacts 239 | **/*.Server/ModelManifest.xml 240 | _Pvt_Extensions 241 | 242 | # Paket dependency manager 243 | .paket/paket.exe 244 | paket-files/ 245 | 246 | # FAKE - F# Make 247 | .fake/ 248 | 249 | # JetBrains Rider 250 | .idea/ 251 | *.sln.iml 252 | *.exe 253 | 254 | # Windows Build System files 255 | build*.dbb 256 | build*.err 257 | build*.evt 258 | build*.log 259 | build*.prf 260 | build*.trc 261 | build*.rec 262 | build*.wrn 263 | build*.metadata 264 | 265 | # MS Build binary logs 266 | *.binlog 267 | 268 | # .razzlerc.cmd file - used by dev environment 269 | tools/.razzlerc.* 270 | # .PowershellModules - if one needs a powershell module dependency, one 271 | # can save it here. used by tools/OpenConsole.psm1 272 | .PowershellModules 273 | # message compiler output 274 | MSG*.bin 275 | /*.exe 276 | 277 | # python 278 | *.pyc 279 | 280 | **/Generated Files/ 281 | **/Merged/* 282 | **/Unmerged/* 283 | profiles.json 284 | *.metaproj 285 | *.swp 286 | 287 | launchSettings.json 288 | package-lock.json 289 | draft-*.docx 290 | 291 | **/target/* 292 | # These are backup files generated by rustfmt 293 | **/*.rs.bk 294 | -------------------------------------------------------------------------------- /.pipelines/OneBranch.Buddy.yml: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | # OneBranch Pipelines - Buddy # 3 | # This pipeline was created by EasyStart from a sample located at: # 4 | # https://aka.ms/obpipelines/easystart/samples # 5 | # Documentation: https://aka.ms/obpipelines # 6 | # Yaml Schema: https://aka.ms/obpipelines/yaml/schema # 7 | # Retail Tasks: https://aka.ms/obpipelines/tasks # 8 | # Support: https://aka.ms/onebranchsup # 9 | ################################################################################# 10 | 11 | trigger: 12 | - master 13 | 14 | # Hourly builds: you may want to change these to nightly ("0 3 * * *" - run at 3am). 15 | schedules: 16 | - cron: 0 * * * * 17 | displayName: Hourly build 18 | branches: 19 | include: 20 | - master 21 | always: true 22 | 23 | variables: 24 | CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning 25 | LinuxContainerImage: 'mcr.microsoft.com/onebranch/cbl-mariner/build:2.0' # Docker image which is used to build the project https://aka.ms/obpipelines/containers 26 | WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' 27 | DEBIAN_FRONTEND: noninteractive 28 | 29 | resources: 30 | repositories: 31 | - repository: templates 32 | type: git 33 | name: OneBranch.Pipelines/GovernedTemplates 34 | ref: refs/heads/main 35 | 36 | extends: 37 | template: v2/OneBranch.NonOfficial.CrossPlat.yml@templates # https://aka.ms/obpipelines/templates 38 | parameters: 39 | cloudvault: # https://aka.ms/obpipelines/cloudvault 40 | enabled: false 41 | globalSdl: # https://aka.ms/obpipelines/sdl 42 | binskim: 43 | # Rust build scripts will not be built with spectre-mitigations enabled, so only scan the actual output binaries. 44 | scanOutputDirectoryOnly: true 45 | stages: 46 | - stage: Build 47 | jobs: 48 | - job: Linux 49 | pool: 50 | type: linux 51 | variables: 52 | ob_outputDirectory: '$(Build.SourcesDirectory)/out' # More settings at https://aka.ms/obpipelines/yaml/jobs 53 | additionalRustTargets: x86_64-unknown-linux-musl 54 | # Cargo's default target dir is $(Build.SourcesDirectory)/target but $(Build.BinariesDirectory)/target is more appropriate. 55 | cargo_target_dir: $(Build.BinariesDirectory)/target 56 | steps: 57 | - template: .pipelines/OneBranch.Common.yml@self 58 | 59 | - job: Windows 60 | pool: 61 | type: windows 62 | variables: 63 | ob_outputDirectory: '$(Build.SourcesDirectory)/out' # More settings at https://aka.ms/obpipelines/yaml/jobs 64 | additionalRustTargets: i686-pc-windows-msvc 65 | # For details on this cargo_target_dir setting, see https://eng.ms/docs/more/rust/topics/onebranch-workaround 66 | cargo_target_dir: C:\cargo_target_dir 67 | steps: 68 | - template: .pipelines/OneBranch.Common.yml@self 69 | -------------------------------------------------------------------------------- /.pipelines/OneBranch.Common.yml: -------------------------------------------------------------------------------- 1 | # Core build logic that is common to all OneBranch builds. 2 | parameters: # parameters are shown up in ADO UI in a build queue time 3 | - name: buildPlatforms 4 | type: object 5 | default: 6 | - x86_64-pc-windows-msvc # x64 7 | - i686-pc-windows-msvc # x86 8 | - aarch64-pc-windows-msvc # arm64 9 | # - # arm32? 10 | 11 | - name: brandings 12 | type: object 13 | default: 14 | - Inbox 15 | - Stable 16 | - Dev 17 | 18 | - name: tracingGuid 19 | type: string 20 | default: ffffffff-ffff-ffff-ffff-ffffffffffff 21 | 22 | steps: 23 | - task: RustInstaller@1 24 | inputs: 25 | # Can be any "MSRustup" version, such as ms-stable, ms-1.54 or ms-stable-20210513.5 - for more details see https://mscodehub.visualstudio.com/Rust/_git/rust.msrustup 26 | # For supported versions see https://mscodehub.visualstudio.com/Rust/_packaging?_a=package&feed=Rust&view=versions&package=rust.tools-x86_64-pc-windows-msvc&protocolType=NuGet 27 | # We recommend setting this to a specific numbered version such as `ms-1.68` -- we do not recommend 28 | # setting it to `ms-stable`. 29 | # For details on this, see https://eng.ms/docs/more/rust/topics/conventions#toolchain-usage 30 | rustVersion: ms-1.75 31 | 32 | # Space separated list of additional targets: only the host target is supported with the toolchain by default. 33 | # 34 | # This doesn't actually control what gets built - only which toolchains get installed on the build agent. 35 | # 36 | # Theoretically, I could somehow replace this with the buildPlatforms passed in as a parameter 37 | additionalTargets: i686-pc-windows-msvc aarch64-pc-windows-msvc x86_64-pc-windows-msvc 38 | 39 | # URL of an Azure Artifacts feed configured with a crates.io upstream. Must be within the current ADO collection. 40 | # NOTE: Azure Artifacts support for Rust is not yet public, but it is enabled for internal ADO organizations. 41 | # https://learn.microsoft.com/en-us/azure/devops/artifacts/how-to/set-up-upstream-sources?view=azure-devops 42 | cratesIoFeedOverride: sparse+https://pkgs.dev.azure.com/microsoft/Dart/_packaging/sudo_public_cargo/Cargo/index/ 43 | 44 | # URL of an Azure Artifacts NuGet feed configured with the mscodehub Rust feed as an upstream. 45 | # * The feed must be within the current ADO collection. 46 | # * The CI account, usually "Project Collection Build Service (org-name)", must have at least "Collaborator" permission. 47 | # When setting up the upstream NuGet feed, use following Azure Artifacts feed locator: 48 | # azure-feed://mscodehub/Rust/Rust@Release 49 | toolchainFeed: https://pkgs.dev.azure.com/microsoft/_packaging/RustTools/nuget/v3/index.json 50 | 51 | displayName: Install Rust toolchain 52 | 53 | # We recommend making a separate `cargo fetch` step, as some build systems 54 | # perform fetching entirely prior to the build, and perform the build with the 55 | # network disabled. 56 | - script: cargo fetch 57 | displayName: Fetch crates 58 | 59 | # First, build and test each branding. 60 | - ${{ each brand in parameters.brandings }}: 61 | - script: cargo build --config .cargo\ms-toolchain-config.toml --no-default-features --features ${{brand}} --frozen 2>&1 62 | displayName: Build ${{brand}} Debug 63 | 64 | - script: cargo test --config .cargo\ms-toolchain-config.toml --no-default-features --features ${{brand}} --frozen 2>&1 65 | displayName: Test ${{brand}} Debug 66 | 67 | # We suggest fmt and clippy after build and test, to catch build breaks and test 68 | # failures as quickly as possible. 69 | # This only needs to happen once, not per-branding. 70 | - script: cargo fmt --check 2>&1 71 | displayName: Check formatting 72 | 73 | - ${{ each brand in parameters.brandings }}: 74 | - script: cargo clippy --config .cargo\ms-toolchain-config.toml --no-default-features --features ${{brand}} --frozen -- -D warnings 2>&1 75 | displayName: Clippy (Linting) ${{brand}} 76 | 77 | # Build release last because it takes the longest and we should have gotten 78 | # all available error signal by this point. 79 | - ${{ each platform in parameters.buildPlatforms }}: 80 | - script: cargo build --config .cargo\ms-toolchain-config.toml --no-default-features --features ${{brand}} --target ${{platform}} --frozen --release 2>&1 81 | env: 82 | MAGIC_TRACING_GUID: ${{ parameters.tracingGuid }} 83 | displayName: Build ${{brand}}-${{platform}} Release 84 | 85 | # At this point, we've completed the build, but each of the outputs is in a 86 | # subdir specific to the architecture being built. That's okay, but the artifact 87 | # drop won't know to look for them in there. 88 | # 89 | # Copy them on out. 90 | - task: CopyFiles@2 91 | displayName: Copy files to output (${{brand}}/${{platform}}) 92 | inputs: 93 | sourceFolder: '$(CARGO_TARGET_DIR)/${{platform}}/release' 94 | targetFolder: '$(ob_outputDirectory)/${{brand}}/${{platform}}' 95 | contents: '*' 96 | 97 | # only do this once 98 | - task: CopyFiles@2 99 | displayName: Copy instrumentation manifest to output 100 | inputs: 101 | sourceFolder: 'cpp/logging' 102 | targetFolder: '$(ob_outputDirectory)/' 103 | contents: 'instrumentation.man' 104 | -------------------------------------------------------------------------------- /.pipelines/PR.Pipeline.yml: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | # OneBranch Pipelines - Buddy # 3 | # This pipeline was created by EasyStart from a sample located at: # 4 | # https://aka.ms/obpipelines/easystart/samples # 5 | # Documentation: https://aka.ms/obpipelines # 6 | # Yaml Schema: https://aka.ms/obpipelines/yaml/schema # 7 | # Retail Tasks: https://aka.ms/obpipelines/tasks # 8 | # Support: https://aka.ms/onebranchsup # 9 | ################################################################################# 10 | 11 | trigger: none 12 | # - main 13 | 14 | parameters: # parameters are shown up in ADO UI in a build queue time 15 | # buildPlatforms: This controls which Rust triples we build sudo for. 16 | # These three defaults correspond to x64, x86 and ARM64. 17 | # They're used by: 18 | # - The OneBranch.Common.yml, to control which --target's we build in release 19 | # - The vpack task, below. 20 | - name: buildPlatforms 21 | type: object 22 | default: 23 | - x86_64-pc-windows-msvc # x64 24 | - i686-pc-windows-msvc # x86 25 | - aarch64-pc-windows-msvc # arm64 26 | 27 | # Hourly builds: you may want to change these to nightly ("0 3 * * *" - run at 3am). 28 | schedules: 29 | - cron: 0 * * * * 30 | displayName: Hourly build 31 | branches: 32 | include: 33 | - master 34 | always: true 35 | 36 | variables: 37 | CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning 38 | WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' 39 | 40 | # LOAD BEARING - the vpack task fails without these 41 | ROOT: $(Build.SourcesDirectory) 42 | REPOROOT: $(Build.SourcesDirectory) 43 | OUTPUTROOT: $(REPOROOT)\out 44 | NUGET_XMLDOC_MODE: none 45 | 46 | resources: 47 | repositories: 48 | - repository: templates 49 | type: git 50 | name: OneBranch.Pipelines/GovernedTemplates 51 | ref: refs/heads/main 52 | 53 | extends: 54 | # We're an official build, so we need to extend from the _Official_ build template. 55 | template: v2/Microsoft.NonOfficial.yml@templates 56 | parameters: 57 | platform: 58 | name: 'windows_undocked' 59 | product: 'sudo' 60 | cloudvault: # https://aka.ms/obpipelines/cloudvault 61 | enabled: false 62 | globalSdl: # https://aka.ms/obpipelines/sdl 63 | binskim: 64 | # Rust build scripts will not be built with spectre-mitigations enabled, 65 | # so only scan the actual output binaries. 66 | scanOutputDirectoryOnly: true 67 | stages: 68 | # Our Build stage will build all three targets in one job, so we don't need 69 | # to repeat most of the boilerplate work in three separate jobs. 70 | - stage: Build 71 | jobs: 72 | - job: Windows 73 | pool: 74 | type: windows 75 | 76 | variables: 77 | # Binaries will go here 78 | ob_outputDirectory: '$(Build.SourcesDirectory)/out' # More settings at https://aka.ms/obpipelines/yaml/jobs 79 | additionalTargets: $(parameters.buildPlatforms) 80 | # For details on this cargo_target_dir setting, see https://eng.ms/docs/more/rust/topics/onebranch-workaround 81 | cargo_target_dir: C:\cargo_target_dir 82 | 83 | # The "standard" pipeline has a bunch of other variables it sets here 84 | # to control vpack creation. However, for a PR build, we don't really 85 | # need any of that. 86 | 87 | steps: 88 | # The actual build is over in Onebranch.Common.yml 89 | - template: .pipelines/OneBranch.Common.yml@self 90 | parameters: 91 | buildPlatforms: ${{ parameters.buildPlatforms }} 92 | # branding will use the default, which is set to build all of them. 93 | # tracingGuid will use the default placeholder for PR builds 94 | 95 | # This is very shamelessly stolen from curl's pipeline. Small 96 | # modification: since our cargo.toml has a bunch of lines with "version", 97 | # bail after the first. 98 | - script: |- 99 | rem Parse the version out of cargo.toml 100 | for /f "tokens=3 delims=- " %%x in ('findstr /c:"version = " sudo\cargo.toml') do (@echo ##vso[task.setvariable variable=SudoVersion]%%~x & goto :EOF) 101 | displayName: 'Set SudoVersion' 102 | 103 | # Codesigning. Cribbed directly from the curl codesign task 104 | - task: onebranch.pipeline.signing@1 105 | displayName: 'Sign files' 106 | inputs: 107 | command: 'sign' 108 | signing_profile: 'external_distribution' 109 | files_to_sign: '**/*.exe' 110 | search_root: '$(ob_outputDirectory)' 111 | use_testsign: false 112 | in_container: true 113 | -------------------------------------------------------------------------------- /.pipelines/Standard.Pipeline.yml: -------------------------------------------------------------------------------- 1 | ################################################################################# 2 | # OneBranch Pipelines - Buddy # 3 | # This pipeline was created by EasyStart from a sample located at: # 4 | # https://aka.ms/obpipelines/easystart/samples # 5 | # Documentation: https://aka.ms/obpipelines # 6 | # Yaml Schema: https://aka.ms/obpipelines/yaml/schema # 7 | # Retail Tasks: https://aka.ms/obpipelines/tasks # 8 | # Support: https://aka.ms/onebranchsup # 9 | ################################################################################# 10 | 11 | trigger: none 12 | # - main 13 | 14 | parameters: # parameters are shown up in ADO UI in a build queue time 15 | # buildPlatforms: This controls which Rust triples we build sudo for. 16 | # These three defaults correspond to x64, x86 and ARM64. 17 | # They're used by: 18 | # - The OneBranch.Common.yml, to control which --target's we build in release 19 | # - The vpack task, below. 20 | - name: buildPlatforms 21 | type: object 22 | default: 23 | - x86_64-pc-windows-msvc # x64 24 | - i686-pc-windows-msvc # x86 25 | - aarch64-pc-windows-msvc # arm64 26 | 27 | # The official builds default to just the Inbox builds 28 | - name: brandings 29 | type: object 30 | default: 31 | - Inbox 32 | # - Stable 33 | # - Dev 34 | 35 | # Hourly builds: you may want to change these to nightly ("0 3 * * *" - run at 3am). 36 | schedules: 37 | - cron: 0 * * * * 38 | displayName: Hourly build 39 | branches: 40 | include: 41 | - master 42 | always: true 43 | 44 | variables: 45 | CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] # needed for onebranch.pipeline.version task https://aka.ms/obpipelines/versioning 46 | WindowsContainerImage: 'onebranch.azurecr.io/windows/ltsc2019/vse2022:latest' 47 | 48 | # LOAD BEARING - the vpack task fails without these 49 | ROOT: $(Build.SourcesDirectory) 50 | REPOROOT: $(Build.SourcesDirectory) 51 | OUTPUTROOT: $(REPOROOT)\out 52 | NUGET_XMLDOC_MODE: none 53 | 54 | resources: 55 | repositories: 56 | - repository: templates 57 | type: git 58 | name: OneBranch.Pipelines/GovernedTemplates 59 | ref: refs/heads/main 60 | 61 | extends: 62 | # We're an official build, so we need to extend from the _Official_ build template. 63 | template: v2/Microsoft.Official.yml@templates 64 | parameters: 65 | platform: 66 | name: 'windows_undocked' 67 | product: 'sudo' 68 | cloudvault: # https://aka.ms/obpipelines/cloudvault 69 | enabled: false 70 | globalSdl: # https://aka.ms/obpipelines/sdl 71 | binskim: 72 | # Rust build scripts will not be built with spectre-mitigations enabled, 73 | # so only scan the actual output binaries. 74 | scanOutputDirectoryOnly: true 75 | stages: 76 | # Our Build stage will build all three targets in one job, so we don't need 77 | # to repeat most of the boilerplate work in three separate jobs. 78 | - stage: Build 79 | jobs: 80 | - job: Windows 81 | pool: 82 | type: windows 83 | 84 | variables: 85 | # Binaries will go here 86 | ob_outputDirectory: '$(Build.SourcesDirectory)/out' # More settings at https://aka.ms/obpipelines/yaml/jobs 87 | 88 | # The vPack gets created from stuff in here 89 | ob_createvpack_vpackdirectory: '$(ob_outputDirectory)/vpack' 90 | # It will have a structure like: 91 | # .../vpack/ 92 | # - amd64/ 93 | # - sudo.exe 94 | # - i386/ 95 | # - sudo.exe 96 | # - arm64/ 97 | # - sudo.exe 98 | 99 | # not sure where this goes 100 | # additionalRustTargets: i686-pc-windows-msvc 101 | additionalTargets: $(parameters.buildPlatforms) 102 | 103 | # For details on this cargo_target_dir setting, see https://eng.ms/docs/more/rust/topics/onebranch-workaround 104 | cargo_target_dir: C:\cargo_target_dir 105 | 106 | # All these? Also variables that control the vpack creation. 107 | ob_createvpack_enabled: true 108 | ob_createvpack_packagename: 'windows_sudo.$(Build.SourceBranchName)' 109 | ob_createvpack_owneralias: 'migrie@microsoft.com' 110 | ob_createvpack_description: 'Sudo for Windows' 111 | ob_createvpack_targetDestinationDirectory: '$(Destination)' 112 | ob_createvpack_propsFile: false 113 | ob_createvpack_provData: true 114 | ob_createvpack_versionAs: string 115 | ob_createvpack_version: '$(SudoVersion)-$(CDP_DEFINITION_BUILD_COUNT)' 116 | ob_createvpack_metadata: '$(Build.SourceVersion)' 117 | ob_createvpack_topLevelRetries: 0 118 | ob_createvpack_failOnStdErr: true 119 | ob_createvpack_taskLogVerbosity: Detailed 120 | ob_createvpack_verbose: true 121 | 122 | steps: 123 | # Before we build! Right before we build, pull down localizations from 124 | # Touchdown. 125 | # 126 | # The Terminal build would literally pass this as a parameter of a list 127 | # of steps to the job-build-project.yml, which is overkill for us 128 | - template: .pipelines/steps-fetch-and-prepare-localizations.yml@self 129 | parameters: 130 | includePseudoLoc: true 131 | 132 | # The actual build is over in Onebranch.Common.yml 133 | - template: .pipelines/OneBranch.Common.yml@self 134 | parameters: 135 | buildPlatforms: ${{ parameters.buildPlatforms }} 136 | brandings: ${{ parameters.brandings }} 137 | tracingGuid: $(SecretTracingGuid) 138 | 139 | # This is very shamelessly stolen from curl's pipeline. Small 140 | # modification: since our cargo.toml has a bunch of lines with "version", 141 | # bail after the first. 142 | - script: |- 143 | rem Parse the version out of cargo.toml 144 | for /f "tokens=3 delims=- " %%x in ('findstr /c:"version = " sudo\cargo.toml') do (@echo ##vso[task.setvariable variable=SudoVersion]%%~x & goto :EOF) 145 | displayName: 'Set SudoVersion' 146 | 147 | # Codesigning. Cribbed directly from the curl codesign task 148 | - task: onebranch.pipeline.signing@1 149 | displayName: 'Sign files' 150 | inputs: 151 | command: 'sign' 152 | signing_profile: 'external_distribution' 153 | files_to_sign: '**/*.exe' 154 | search_root: '$(ob_outputDirectory)' 155 | use_testsign: false 156 | in_container: true 157 | 158 | # This stage grabs each of the sudo's we've built for different 159 | # architectures, and copies them into the appropriate vpack directory. 160 | - ${{ each platform in parameters.buildPlatforms }}: 161 | - task: CopyFiles@2 162 | displayName: Copy files to vpack (${{platform}}) 163 | inputs: 164 | # We always use the 'Inbox' branding vvvvv here - vpacks are only ever consumed by the OS 165 | sourceFolder: '$(ob_outputDirectory)/Inbox/${{platform}}' 166 | ${{ if eq(platform, 'i686-pc-windows-msvc') }}: 167 | targetFolder: '$(ob_createvpack_vpackdirectory)/i386' 168 | ${{ elseif eq(platform, 'x86_64-pc-windows-msvc') }}: 169 | targetFolder: '$(ob_createvpack_vpackdirectory)/amd64' 170 | ${{ else }}: # aarch64-pc-windows-msvc 171 | targetFolder: '$(ob_createvpack_vpackdirectory)/arm64' 172 | contents: '*' 173 | - task: CopyFiles@2 174 | # only do this once 175 | displayName: Copy manifest to vpack 176 | inputs: 177 | sourceFolder: '$(ob_outputDirectory)/' 178 | targetFolder: '$(ob_createvpack_vpackdirectory)/' 179 | contents: 'instrumentation.man' 180 | -------------------------------------------------------------------------------- /.pipelines/daily-loc-build.yml: -------------------------------------------------------------------------------- 1 | trigger: none 2 | pr: none 3 | schedules: 4 | - cron: "0 3 * * 2-6" # Run at 03:00 UTC Tuesday through Saturday (After the work day in Pacific, Mon-Fri) 5 | displayName: "Nightly Localization Build" 6 | branches: 7 | include: 8 | - main 9 | always: false # only run if there's code changes! 10 | 11 | pool: 12 | vmImage: windows-2022 13 | 14 | resources: 15 | repositories: 16 | - repository: self 17 | type: git 18 | ref: main 19 | 20 | steps: 21 | 22 | - checkout: self 23 | clean: true 24 | submodules: false 25 | fetchDepth: 1 # Don't need a deep checkout for loc files! 26 | fetchTags: false # Tags still result in depth > 1 fetch; we don't need them here 27 | persistCredentials: true 28 | 29 | - task: MicrosoftTDBuild.tdbuild-task.tdbuild-task.TouchdownBuildTask@3 30 | displayName: 'Touchdown Build - 92350, PRODEXT' 31 | inputs: 32 | teamId: 92350 33 | TDBuildServiceConnection: $(TouchdownServiceConnection) 34 | authType: SubjectNameIssuer 35 | resourceFilePath: | 36 | **\en-US\*.resw 37 | outputDirectoryRoot: LocOutput 38 | appendRelativeDir: true 39 | pseudoSetting: Included 40 | 41 | # Saving one of these makes it really easy to inspect the loc output... 42 | - powershell: 'tar czf LocOutput.tar.gz LocOutput' 43 | displayName: 'Archive Loc Output for Submission' 44 | 45 | - task: PublishBuildArtifacts@1 46 | displayName: 'Publish Artifact: LocOutput' 47 | inputs: 48 | PathtoPublish: LocOutput.tar.gz 49 | ArtifactName: LocOutput 50 | -------------------------------------------------------------------------------- /.pipelines/steps-fetch-and-prepare-localizations.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: includePseudoLoc 3 | type: boolean 4 | default: true 5 | 6 | steps: 7 | - task: TouchdownBuildTask@3 8 | displayName: Download Localization Files 9 | inputs: 10 | teamId: 92350 11 | TDBuildServiceConnection: $(TouchdownServiceConnection) 12 | authType: SubjectNameIssuer 13 | resourceFilePath: | 14 | **\en-US\*.resw 15 | appendRelativeDir: true 16 | localizationTarget: false 17 | ${{ if eq(parameters.includePseudoLoc, true) }}: 18 | pseudoSetting: Included 19 | 20 | - pwsh: |- 21 | $Files = Get-ChildItem . -R -Filter 'Resources.resw' | ? FullName -Like '*en-US\*\Resources.resw' 22 | $Files | % { Move-Item -Verbose $_.Directory $_.Directory.Parent.Parent -EA:Ignore } 23 | displayName: Move Loc files into final locations 24 | -------------------------------------------------------------------------------- /Building.md: -------------------------------------------------------------------------------- 1 | # Building Sudo for Windows 2 | 3 | Sudo for Windows is a Rust project. If you're new to Rust, you can get started with the [Rust Book](https://doc.rust-lang.org/book/). You can quickly get started with rust by installing and running `rustup`: 4 | 5 | ```cmd 6 | winget install --id Rustlang.rustup --source winget 7 | rustup update 8 | ``` 9 | 10 | ## Building 11 | 12 | Rust is nice and straightforward. You can build sudo for the default architecture with a simple 13 | 14 | ``` 15 | cargo build 16 | ``` 17 | 18 | You may want to specify a specific architecture. To do that, you'll want instead: 19 | 20 | ``` 21 | cargo build --target x86_64-pc-windows-msvc 22 | ``` 23 | 24 | (You can also use `i686-pc-windows-msvc` as the target). 25 | 26 | ### Running tests 27 | 28 | Assuming that you passed a target architecture above: 29 | 30 | ``` 31 | cargo test --target x86_64-pc-windows-msvc 32 | ``` 33 | 34 | We have additional manual tests that you can use to validate sudo in the 35 | `tools\tests.ipynb` notebook. 36 | 37 | ### Formatting and clippy 38 | 39 | ``` 40 | cargo fmt 41 | cargo clippy 42 | ``` 43 | 44 | If your code passes a `cargo build && cargo test && cargo fmt && cargo clippy`, you're ready to send a PR. 45 | 46 | ### Notes on building with the Microsoft internal toolchain 47 | 48 | When we're building this project internally, we need to use an internally-maintained fork of the rust toolchain. This toolchain needs to be used for all production work at Microsoft so we can stay compliant with Secure Development Lifecycle (SDL) requirements. 49 | 50 | **If you're external to Microsoft, this next section doesn't apply to you**. You 51 | can use the standard Rust toolchain. 52 | 53 | First, install the internal `msrustup` toolchain to install the right version of 54 | all our Rust tools. You can get it from the https://aka.ms/msrustup-win. After 55 | that installs, then you'll probably also need to run the following: 56 | 57 | ``` 58 | rustup default ms-stable 59 | ``` 60 | 61 | That'll select the ms toolchain as the default. If you ever want to switch back, you can always just run 62 | 63 | ``` 64 | rustup default stable-x86_64-pc-windows-msvc 65 | ``` 66 | 67 | Additionally, we've got a separate fork of our `.cargo/config.toml` we need to use for internal builds. Notably, this includes `-Cehcont_guard` to enable EH Continuation Metadata. It also redirects cargo to use our own package feed for dependencies. 68 | 69 | You can manually build with that config with: 70 | 71 | ``` 72 | cargo build --config .cargo\ms-toolchain-config.toml 73 | ``` 74 | 75 | Note, if you run that on the public toolchain, you'll most definitely run into ``error: unknown codegen option: `ehcont_guard` `` when building. 76 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Microsoft Open Source Code of Conduct 2 | 3 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). 4 | 5 | Resources: 6 | 7 | - [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/) 8 | - [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) 9 | - Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Sudo for Windows Contributor's Guide 2 | 3 | Below is our guidance for how to report issues, propose new features, and submit 4 | contributions via Pull Requests (PRs). Our philosophy is heavily based around 5 | understanding the problem and scenarios first, this is why we follow this 6 | pattern before work has started. 7 | 8 | 1. There is an issue 9 | 2. There has been a conversation 10 | 3. There is agreement on the problem, the fit for Sudo for Windows, and the 11 | solution to the problem (implementation) 12 | 13 | ## Filing an issue 14 | 15 | Please follow this simple rule to help us eliminate any unnecessary wasted 16 | effort & frustration, and ensure an efficient and effective use of everyone's 17 | time - yours, ours, and other community members': 18 | 19 | > 👉 If you have a question, think you've discovered an issue, would like to 20 | > propose a new feature, etc., then find/file an issue **BEFORE** starting work 21 | > to fix/implement it. 22 | 23 | When requesting new features / enhancements, understanding problem and scenario 24 | around it is extremely important. Having additional evidence, data, tweets, blog 25 | posts, research, ... anything is extremely helpful. This information provides 26 | context to the scenario that may otherwise be lost. 27 | 28 | * Don't know whether you're reporting an issue or requesting a feature? **File an issue** 29 | * Have a question that you don't see answered in docs, videos, etc.? **File an issue** 30 | * Want to know if we're planning on building a particular feature? **File an issue** 31 | * Got a great idea for a new feature? **File an issue** 32 | * Don't understand how to do something? **File an issue** 33 | * Found an existing issue that describes yours? **Great!** upvote and add 34 | additional commentary / info / repro-steps / etc. 35 | 36 | A quick search before filing an issue also could be helpful. It is likely 37 | someone else has found the problem you're seeing, and someone may be working on 38 | or have already contributed a fix! 39 | 40 | ### Reporting Security Issues 41 | 42 | **Please do not report security vulnerabilities through public GitHub issues.** 43 | Instead, please report them to the Microsoft Security Response Center (MSRC). 44 | See [SECURITY.md](./SECURITY.md) for more information. 45 | 46 | ### How to tell the Sudo team "this is an interesting thing to focus on" 47 | 48 | Upvote the original issue by clicking its [+😊] button and hitting 👍 (+1) icon 49 | or a different one. This way allows us to measure how impactful different issues 50 | are compared to others. The issue with comments like "+1", "me too", or similar 51 | is they actually make it harder to have a conversation and harder to quickly 52 | determine trending important requests. 53 | 54 | ### Localization issues 55 | 56 | Please file localization issues, so our internal localization team can identify 57 | and fix them. However we currently don't accept community Pull Requests fixing 58 | localization issues. Localization is handled by the internal Microsoft team 59 | only. 60 | 61 | ## Contributing code 62 | 63 | As you might imagine, shipping something inside of Windows is a complicated 64 | process--doubly so for a security component. There is a lot of validation and 65 | paperwork that we don't really want to subject the community to. We want you to 66 | be able to contribute easily and freely, and to let us deal with the paperwork. 67 | We'll do our best to make sure this process is as seamless as possible. 68 | 69 | To support the community in building new feature areas for Sudo for Windows, 70 | we're going to make extensive use of feature flags, to conditionally add new 71 | features to Sudo for Windows. 72 | 73 | When contributing to Sudo for Windows, we will treat "bugfixes" and "features" 74 | separately. Bug fixes can be merged into the codebase freely, so long as they 75 | don't majorly change existing behaviors. New features will need to have their 76 | code guarded by feature flag checks before we can accept them as contributions. 77 | 78 | As always, filing issues on the repo is the best way to have the team evaluate 79 | if the change you're proposing would be considered a "bug fix" or "feature" 80 | work. We will indicate which is which using the `Issue-Bug` and 81 | `Issue-Feature`/`Issue-Task` labels. These labels are intended to be informative, 82 | and may change throughout the lifecycle of a discussion. 83 | 84 | We'll be grouping sets of feature flags into different "branding"s throughout 85 | the project. These brandings are as follows: 86 | * **"Inbox"**: These are features that are included in the version of sudo that 87 | ships with Windows itself. 88 | * **"Stable"**: Features that ship in stable versions of sudo released here on 89 | GitHub and on WinGet. 90 | * **"Dev"**: The least stable features, which are only built in local development 91 | builds. These are for work-in-progress features, that aren't quite ready for 92 | public consumption 93 | 94 | All new features should be added under the "Dev" branding first. The core team 95 | will then be responsible for moving those features into the appropriate branding 96 | as we get internal signoffs. This will allow features to be worked on 97 | continually in the open, while we slowly roll them into the OS product. We 98 | unfortunately cannot provide timelines for when features will be able to move 99 | from Stable into Inbox. Historical data showing that a feature has a track 100 | record of being stable and secure is a great way for us to justify any 101 | particular feature's inclusion into the product. 102 | 103 | If you're ready to jump in, head on over to [Building.md](./Building.md) to get 104 | started. 105 | 106 | ## Repo Bot 107 | 108 | The team triages new issues several times a week. During triage, the team uses 109 | labels to categorize, manage, and drive the project workflow. 110 | 111 | We employ a bot engine to help us automate common processes within our workflow. 112 | 113 | We drive the bot by tagging issues with specific labels which cause the bot 114 | engine to close issues, merge branches, etc. This bot engine helps us keep the 115 | repo clean by automating the process of notifying appropriate parties if/when 116 | information/follow-up is needed, and closing stale issues/PRs after reminders 117 | have remained unanswered for several days. 118 | 119 | Therefore, if you do file issues, or create PRs, please keep an eye on your 120 | GitHub notifications. If you do not respond to requests for information, your 121 | issues/PRs may be closed automatically. 122 | 123 | ## Thank you 124 | 125 | Thank you in advance for your contribution! 126 | 127 | [`sudo.ps1`]: ./scripts/sudo.ps1 128 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "2" 3 | 4 | members = [ 5 | "sudo", 6 | "sudo_events", 7 | "win32resources", 8 | ] 9 | 10 | # This list of dependencies allows us to specify version numbers for dependency in a single place. 11 | # The dependencies in this list are _not_ automatically added to crates (Cargo.toml files). 12 | # Each individual Cargo.toml file must explicitly declare its dependencies. To use a dependency 13 | # from this list, specify "foo.workspace = true". For example: 14 | # 15 | # [dependencies] 16 | # log.workspace = true 17 | # 18 | # See: https://doc.rust-lang.org/cargo/reference/workspaces.html#the-dependencies-table 19 | # 20 | [workspace.dependencies] 21 | cc = "1.0" 22 | # We're disabling the default features for clap because we don't need the 23 | # "suggestions" feature. That provides really amazing suggestions for typos, but 24 | # it unfortunately does not seem to support localization. 25 | # 26 | # To use clap at all, you do need the std feature enabled, so enable that. 27 | # 28 | # See: https://docs.rs/clap/latest/clap/_features/index.html 29 | clap = { version = "4.4.7", default-features = false, features = ["std"] } 30 | embed-manifest = "1.4" 31 | which = "6.0" 32 | win_etw_provider = "0.1.8" 33 | win_etw_macros = "0.1.8" 34 | windows = "0.57" 35 | windows-registry = "0.1" 36 | winres = "0.1" 37 | 38 | # For more profile settings, and details on the ones below, see https://doc.rust-lang.org/cargo/reference/profiles.html#profile-settings 39 | [profile.release] 40 | # Enable full debug info for optimized builds. 41 | debug = "full" 42 | # Split debuginfo into its own file to reduce binary size. 43 | split-debuginfo = "packed" 44 | lto = true 45 | panic = "abort" 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Microsoft Corporation. All rights reserved. 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /NOTICE.md: -------------------------------------------------------------------------------- 1 | # NOTICES AND INFORMATION 2 | Do Not Translate or Localize 3 | 4 | This software incorporates material from third parties. Microsoft makes certain 5 | open source code available at [http://3rdpartysource.microsoft.com](http://3rdpartysource.microsoft.com), or you may 6 | send a check or money order for US $5.00, including the product name, the open 7 | source component name, and version number, to: 8 | 9 | ``` 10 | Source Code Compliance Team 11 | Microsoft Corporation 12 | One Microsoft Way 13 | Redmond, WA 98052 14 | USA 15 | ``` 16 | 17 | Notwithstanding any other terms, you may reverse engineer this software to the 18 | extent required to debug changes to any libraries licensed under the GNU Lesser 19 | General Public License. 20 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ![Sudo for Windows icon](./img/Windows/AppList.targetsize-24.png) Sudo for Windows 2 | 3 | Welcome to the repository for [Sudo for Windows][sudo-for-windows] 🥪. Sudo 4 | for Windows allows users to run elevated commands directly from unelevated 5 | terminal windows. 6 | 7 | The "Inbox" version of sudo is available for Windows 11 builds 26045 and later. If you're on an Insiders 8 | build with sudo, you can enable it in the Windows Settings app, on the 9 | "Developer Features" page. 10 | 11 | Here you can report issues and file feature requests. 12 | 13 | ## Relationship to `sudo` on Unix/Linux 14 | 15 | Everything about permissions and the command line experience is 16 | different between Windows and Linux. This project is not a fork of the Unix/Linux 17 | `sudo` project, nor is it a port of that `sudo` project. Instead, Sudo for 18 | Windows is a Windows-specific implementation of the `sudo` concept. 19 | 20 | As the two are entirely different applications, you'll find that certain 21 | elements of the traditional `sudo` experience are not present in Sudo for Windows, and 22 | vice versa. Scripts and documentation that are written for `sudo` may not 23 | be able to be used directly with Sudo for Windows without some modification. 24 | 25 | ## Documentation 26 | 27 | All project documentation is located at 28 | [aka.ms/sudo-docs][sudo-docs]. If you would like to contribute to 29 | the documentation, please submit a pull request on the [Sudo for Windows 30 | Documentation repo][documentation-repo]. 31 | 32 | ## Contributing 33 | 34 | Check out [CONTRIBUTING.md](https://github.com/microsoft/sudo/blob/main/CONTRIBUTING.md) for details on how to contribute to this project. 35 | 36 | ### `sudo.ps1` 37 | 38 | In the meantime, you can contribute to the [`sudo.ps1`] script. This script is 39 | meant to be a helper wrapper around `sudo.exe` that provides a more 40 | user-friendly experience for using sudo from PowerShell. This script is located 41 | in the `scripts/` directory. 42 | 43 | ## Communicating with the Team 44 | 45 | The easiest way to communicate with the team is via GitHub issues. 46 | 47 | Please file new issues, feature requests and suggestions, but **DO search for 48 | similar open/closed preexisting issues before creating a new issue.** 49 | 50 | If you would like to ask a question that you feel doesn't warrant an issue 51 | (yet), try a [discussion thread][discussions]. Those are especially helpful for question & 52 | answer threads. Otherwise, you can reach out to us via your social media 53 | platform of choice: 54 | 55 | * Mike Griese, Senior Developer: [@zadjii@mastodon.social](https://mastodon.social/@zadjii) 56 | * Jordi Adoumie, Product Manager: [@joadoumie](https://twitter.com/joadoumie) 57 | * Dustin Howett, Engineering Lead: [@dhowett@mas.to](https://mas.to/@DHowett) 58 | * Clint Rutkas, Lead Product Manager: [@crutkas](https://twitter.com/clintrutkas) 59 | 60 | ## Code of Conduct 61 | 62 | This project has adopted the [Microsoft Open Source Code of 63 | Conduct][conduct-code]. For more information see the [Code of Conduct 64 | FAQ][conduct-FAQ] or contact [opencode@microsoft.com][conduct-email] with any 65 | additional questions or comments. 66 | 67 | [conduct-code]: https://opensource.microsoft.com/codeofconduct/ 68 | [conduct-FAQ]: https://opensource.microsoft.com/codeofconduct/faq/ 69 | [conduct-email]: mailto:opencode@microsoft.com 70 | [`sudo.ps1`]: ./scripts/sudo.ps1 71 | [discussions]: https://github.com/microsoft/sudo/discussions 72 | [sudo-for-windows]: https://aka.ms/sudo 73 | [sudo-docs]: https://aka.ms/sudo-docs 74 | [documentation-repo]: https://github.com/MicrosoftDocs/windows-dev-docs/tree/docs/hub/sudo 75 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Security 4 | 5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [many more](https://opensource.microsoft.com/). 6 | 7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets Microsoft's [definition](https://docs.microsoft.com/en-us/previous-versions/tn-archive/cc751383(v=technet.10)) of a security vulnerability, please report it to us as described below. 8 | 9 | ## Reporting Security Issues 10 | 11 | **Please do not report security vulnerabilities through public GitHub issues.** 12 | 13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). 14 | 15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). 16 | 17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). 18 | 19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: 20 | 21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) 22 | * Full paths of source file(s) related to the manifestation of the issue 23 | * The location of the affected source code (tag/branch/commit or direct URL) 24 | * Any special configuration required to reproduce the issue 25 | * Step-by-step instructions to reproduce the issue 26 | * Proof-of-concept or exploit code (if possible) 27 | * Impact of the issue, including how an attacker might exploit the issue 28 | 29 | This information will help us triage your report more quickly. 30 | 31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. 32 | 33 | ## Preferred Languages 34 | 35 | We prefer all communications to be in English. 36 | 37 | ## Policy 38 | 39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). 40 | 41 | 42 | -------------------------------------------------------------------------------- /SUPPORT.md: -------------------------------------------------------------------------------- 1 | # Support 2 | 3 | ## How to file issues and get help 4 | 5 | This project uses [GitHub issues][gh-issue] to [track bugs][gh-bug] and [feature 6 | requests][gh-feature]. Please search the existing issues before filing new 7 | issues to avoid duplicates. For new topics, file your bug or feature request as 8 | a new issue. 9 | 10 | For help and questions about using this project, please look at the [docs site 11 | for Sudo for Windows][docs] and our [Contributor's Guide][contributor] if you 12 | want to work on Sudo for Windows. 13 | 14 | ## Microsoft Support Policy 15 | 16 | Support for Sudo for Windows is limited to the resources listed above. 17 | 18 | [gh-issue]: https://github.com/microsoft/sudo/issues/new/choose 19 | [gh-bug]: https://github.com/microsoft/sudo/issues/new?assignees=&labels=Issue-Bug&template=bug_report.md&title= 20 | [gh-feature]: https://github.com/microsoft/sudo/issues/new?assignees=&labels=Issue-Feature&template=Feature_Request.md&title= 21 | [docs]: https://aka.ms/sudo-docs 22 | [contributor]: ./CONTRIBUTING.md 23 | -------------------------------------------------------------------------------- /cpp/logging/EventViewerLogging.c: -------------------------------------------------------------------------------- 1 | #define NOMINMAX 2 | #define WIN32_LEAN_AND_MEAN 3 | #include 4 | 5 | #include 6 | 7 | #include "instrumentation.h" // Generated from manifest 8 | -------------------------------------------------------------------------------- /cpp/logging/README.md: -------------------------------------------------------------------------------- 1 | ## Helpful info for Event Viewer logging 2 | 3 | This C++ project logs to the Windows Event Viewer. It's all wired up to be called from Rust just the same as our RPC code. If you want to test changes here: 4 | 5 | 1. Make sure to go change the `resourceFileName` and the `messageFileName` in 6 | `instrumentation.man` to point at where the files are in your build 7 | directory. (For me, that was 8 | `D:\dev\private\sudo\target\x86_64-pc-windows-msvc\debug\sudo.exe`). It needs 9 | to be the full path, so Event Viewer can find the exe (to load the resources 10 | from it to know how to format the packet of binary data written to it) 11 | - Make sure to change it back to `%systemroot%\System32\sudo.exe` before you push! 12 | 2. Make sure that Event Viewer is closed, and do 13 | ```bat 14 | wevtutil um cpp\logging\instrumentation.man 15 | ``` 16 | to remove the old manifest from event viewer 17 | 3. Build the project 18 | 4. Do a 19 | ```bat 20 | wevtutil im cpp\logging\instrumentation.man 21 | ``` 22 | to install the new manifest to event viewer 23 | 5. Open event viewer, and navigate to "Applications and Services Logs" -> 24 | "Microsoft" -> "Windows" -> "Sudo" -> "Admin" 25 | - alternatively: 26 | ```bat 27 | wevtutil qe Microsoft-Windows-Sudo/Admin /c:3 /rd:true /f:text 28 | ``` 29 | -------------------------------------------------------------------------------- /cpp/logging/instrumentation.man: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 30 | 55 | 56 | 57 | 58 | 59 | 66 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /cpp/rpc/README.md: -------------------------------------------------------------------------------- 1 | # Sudo RPC library 2 | 3 | To do local RPC, we need to use midl to generate function bindings for our RPC 4 | interface, which is defined in `sudo_rpc.idl`. midl expects implementations and 5 | callbacks via C functions which we can do in Rust, but there's one problem: 6 | Error handling on the client side occurs with structed exceptions (SEH). 7 | Those cannot be easily replicated in pure Rust and so the client side calls 8 | are all wrapped in C functions. 9 | 10 | Changes here go as follows: 11 | * Change the interface in `sudo_rpc.idl` 12 | * Write a client-side wrapper in `RpcClient.c` in the style of the other ones 13 | * Implement a client-side wrapper Rust in `rpc_bindings_client.rs` 14 | * Implement the server-side part in `rpc_bindings_server.rs` 15 | 16 | Be careful about the function definitions. At the moment, there are no checks 17 | in place that ensure that the Rust code matches the C code or the .idl file. 18 | -------------------------------------------------------------------------------- /cpp/rpc/RpcClient.c: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | // Our generated header file 8 | #include "sudo_rpc.h" 9 | 10 | // Rust can't (easily) handle SEH exceptions, which the RPC however unfortunately uses. 11 | // And so this wrapper C implementation exists. 12 | 13 | // From : 14 | // Some RPC exceptions are already HRESULTs. Others are in the regular Win32 15 | // error space. If the incoming exception code isn't an HRESULT, wrap it. 16 | inline HRESULT map_rpc_status(DWORD code) 17 | { 18 | return IS_ERROR(code) ? code : HRESULT_FROM_WIN32(code); 19 | } 20 | 21 | HRESULT seh_wrapper_client_DoElevationRequest( 22 | RPC_IF_HANDLE binding, 23 | HANDLE parent_handle, 24 | const HANDLE* pipe_handles, 25 | const HANDLE* file_handles, 26 | DWORD sudo_mode, 27 | UTF8_STRING application, 28 | UTF8_STRING args, 29 | UTF8_STRING target_dir, 30 | UTF8_STRING env_vars, 31 | GUID eventId, 32 | HANDLE* child) 33 | { 34 | RpcTryExcept 35 | { 36 | return client_DoElevationRequest( 37 | binding, 38 | parent_handle, 39 | pipe_handles, 40 | file_handles, 41 | sudo_mode, 42 | application, 43 | args, 44 | target_dir, 45 | env_vars, 46 | eventId, 47 | child); 48 | } 49 | RpcExcept(RpcExceptionFilter(RpcExceptionCode())) 50 | { 51 | return map_rpc_status(RpcExceptionCode()); 52 | } 53 | RpcEndExcept; 54 | } 55 | 56 | HRESULT seh_wrapper_client_Shutdown(RPC_IF_HANDLE binding) 57 | { 58 | RpcTryExcept 59 | { 60 | client_Shutdown(binding); 61 | return S_OK; 62 | } 63 | RpcExcept(RpcExceptionFilter(RpcExceptionCode())) 64 | { 65 | return map_rpc_status(RpcExceptionCode()); 66 | } 67 | RpcEndExcept; 68 | } 69 | 70 | /******************************************************/ 71 | /* MIDL allocate and free */ 72 | /******************************************************/ 73 | 74 | void __RPC_FAR* __RPC_USER midl_user_allocate(size_t len) 75 | { 76 | return (malloc(len)); 77 | } 78 | 79 | void __RPC_USER midl_user_free(void __RPC_FAR* ptr) 80 | { 81 | free(ptr); 82 | } 83 | -------------------------------------------------------------------------------- /cpp/rpc/sudo_rpc.acf: -------------------------------------------------------------------------------- 1 | [implicit_handle(handle_t sudo_rpc_IfHandle)] 2 | interface sudo_rpc 3 | { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /cpp/rpc/sudo_rpc.idl: -------------------------------------------------------------------------------- 1 | // This is where GUID is defined: 2 | import "wtypesbase.idl"; 3 | 4 | typedef struct tagUTF8_STRING { 5 | DWORD length; 6 | [size_is(length)] const unsigned char *data; 7 | } UTF8_STRING; 8 | 9 | [ 10 | uuid (f691b703-f681-47dc-afcd-034b2faab911), // You must change this when you change the interface 11 | version(1.0), 12 | ] 13 | interface sudo_rpc 14 | { 15 | HRESULT DoElevationRequest( 16 | [in] handle_t binding, 17 | [in, system_handle(sh_process)] HANDLE parent_handle, 18 | [in, system_handle(sh_pipe), unique, size_is(3)] const HANDLE* pipe_handles, // in, out, err 19 | [in, system_handle(sh_file), unique, size_is(3)] const HANDLE* file_handles, // in, out, err 20 | [in] DWORD sudo_mode, 21 | [in] UTF8_STRING application, 22 | [in] UTF8_STRING args, // a null-delimited list 23 | [in] UTF8_STRING target_dir, 24 | [in] UTF8_STRING env_vars, // a null-delimited list 25 | [in] GUID eventId, 26 | [out, system_handle(sh_process)] HANDLE* child 27 | ); 28 | 29 | void Shutdown([in] handle_t h1); 30 | } 31 | -------------------------------------------------------------------------------- /docs/generate.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | @rem calculate the next version number based on whatever the last draft-xyz.docx file is 4 | @rem this is a bit of a hack, but it works 5 | 6 | @rem get the last draft file 7 | for /f "delims=" %%a in ('dir /b /on draft-*.docx') do set lastdraft=%%a 8 | 9 | @rem if we didn't find an existing one, start with 000 10 | if "%lastdraft%"=="" set lastdraft=draft-000.docx 11 | 12 | @rem get the version number from the last draft file 13 | for /f "tokens=2 delims=-." %%a in ("%lastdraft%") do set /a version=%%a+1 14 | 15 | echo Generating draft-%version%.docx... 16 | 17 | @rem create the new draft file 18 | @rem 19 | @rem mermaid-filter.cmd is from github.com/raghur/mermaid-filter. That's deeply 20 | @rem out of date, so some of the newer features are missing. You can manually 21 | @rem patch the mermaid.min.js if you want though. 22 | pandoc -s -F mermaid-filter.cmd --from=markdown+yaml_metadata_block --to=docx .\draft.md -o .\draft-%version%.docx 23 | 24 | @rem delete mermaid-filter.err, if it's empty 25 | 26 | if exist mermaid-filter.err ( 27 | for %%a in (mermaid-filter.err) do if %%~za==0 del mermaid-filter.err 28 | ) 29 | -------------------------------------------------------------------------------- /docs/obsidian-callouts.lua: -------------------------------------------------------------------------------- 1 | local stringify = (require "pandoc.utils").stringify 2 | 3 | function BlockQuote (el) 4 | start = el.content[1] 5 | if (start.t == "Para" and start.content[1].t == "Str" and 6 | start.content[1].text:match("^%[!%w+%][-+]?$")) then 7 | _, _, ctype = start.content[1].text:find("%[!(%w+)%]") 8 | el.content:remove(1) 9 | start.content:remove(1) 10 | div = pandoc.Div(el.content, {class = "callout"}) 11 | div.attributes["data-callout"] = ctype:lower() 12 | div.attributes["title"] = stringify(start.content):gsub("^ ", "") 13 | return div 14 | else 15 | return el 16 | end 17 | end -------------------------------------------------------------------------------- /docs/settings-app-toggle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/settings-app-toggle.png -------------------------------------------------------------------------------- /docs/sudo-conhost.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/sudo-conhost.png -------------------------------------------------------------------------------- /docs/sudo-terminal-multi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/sudo-terminal-multi.png -------------------------------------------------------------------------------- /docs/sudo-terminal-redirected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/sudo-terminal-redirected.png -------------------------------------------------------------------------------- /docs/sudo-terminal-service.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/sudo-terminal-service.png -------------------------------------------------------------------------------- /docs/sudo-terminal-single.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/sudo-terminal-single.png -------------------------------------------------------------------------------- /docs/sudo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/docs/sudo.png -------------------------------------------------------------------------------- /docs/versions.md: -------------------------------------------------------------------------------- 1 | # Sudo for Windows - Versions 2 | 3 | There are a few different versions of Sudo for Windows - this doc aims to 4 | outline the differences between them. Each includes different sets of code, and 5 | releases in different cadences. 6 | 7 | * **"Inbox"**: This is the version of Sudo that ships with Windows itself. This 8 | is the most stable version, and might only include a subset of the features in 9 | the source code. This is delivered with the OS, via servicing upgrades. 10 | - Build this version with `cargo build --no-default-features --features Inbox` 11 | * **"Stable"**: The stable version of Sudo for Windows which ships out of this 12 | repo. This can be installed side-by-side with the inbox version. 13 | - Build this version with `cargo build --no-default-features --features Stable` 14 | * **"Dev"**: This is a local-only build of sudo. This has all the bits of code 15 | turned on, for the most up-to-date version of the code. 16 | - Build this version with `cargo build` 17 | 18 | Dev builds are the default for local compilation, to make the development inner loop the 19 | easiest. 20 | 21 | For more info, see "[Contributing code](../CONTRIBUTING.md#contributing-code)" in 22 | the contributors guide. 23 | -------------------------------------------------------------------------------- /enable_sudo.cmd: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | net session >nul 2>&1 4 | if %errorLevel% == 0 ( 5 | goto :do_it 6 | ) 7 | 8 | echo You need to be admin to enable sudo! 9 | goto :exit 10 | 11 | :do_it 12 | echo Enabling sudo... 13 | 14 | set key=HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Sudo 15 | set value=Enabled 16 | set data=3 17 | reg add "%key%" /v "%value%" /t REG_DWORD /d %data% /f 18 | 19 | :exit 20 | -------------------------------------------------------------------------------- /img/Windows/AppList.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-100.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-125.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-150.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-200.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-400.png -------------------------------------------------------------------------------- /img/Windows/AppList.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-16.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-16_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-16_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-16_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-16_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-20.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-20_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-20_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-20_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-20_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-24.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-24_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-24_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-24_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-24_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-256.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-256_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-256_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-256_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-256_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-30.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-30_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-30_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-30_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-30_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-32.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-32_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-32_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-32_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-32_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-36.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-36_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-36_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-36_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-36_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-40.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-40_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-40_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-40_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-40_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-48.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-48_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-48_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-48_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-48_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-56.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-56.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-56_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-56_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-56_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-56_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-60.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-60_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-60_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-60_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-60_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-64.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-64_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-64_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-64_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-64_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-72.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-72_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-72_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-72_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-72_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-80.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-80_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-80_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-80_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-80_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-96.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-96_altform-lightunplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-96_altform-lightunplated.png -------------------------------------------------------------------------------- /img/Windows/AppList.targetsize-96_altform-unplated.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/AppList.targetsize-96_altform-unplated.png -------------------------------------------------------------------------------- /img/Windows/BadgeLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/BadgeLogo.scale-100.png -------------------------------------------------------------------------------- /img/Windows/BadgeLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/BadgeLogo.scale-125.png -------------------------------------------------------------------------------- /img/Windows/BadgeLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/BadgeLogo.scale-150.png -------------------------------------------------------------------------------- /img/Windows/BadgeLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/BadgeLogo.scale-200.png -------------------------------------------------------------------------------- /img/Windows/BadgeLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/BadgeLogo.scale-400.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-100.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-125.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-150.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-200.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-400.png -------------------------------------------------------------------------------- /img/Windows/LargeTile.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/LargeTile.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-100.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-125.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-150.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-200.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-400.png -------------------------------------------------------------------------------- /img/Windows/MedTile.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/MedTile.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-100.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-125.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-150.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-200.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-400.png -------------------------------------------------------------------------------- /img/Windows/SmallTile.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SmallTile.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-100.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-100_altform-colorful_theme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-100_altform-colorful_theme-dark.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-125.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-125_altform-colorful_theme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-125_altform-colorful_theme-dark.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-150.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-150_altform-colorful_theme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-150_altform-colorful_theme-dark.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-200.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-200_altform-colorful_theme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-200_altform-colorful_theme-dark.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-400.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-400_altform-colorful_theme-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-400_altform-colorful_theme-dark.png -------------------------------------------------------------------------------- /img/Windows/SplashScreen.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/SplashScreen.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/StoreDisplay-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreDisplay-150.png -------------------------------------------------------------------------------- /img/Windows/StoreDisplay-300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreDisplay-300.png -------------------------------------------------------------------------------- /img/Windows/StoreDisplay-71.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreDisplay-71.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-100.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-125.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-150.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-200.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-400.png -------------------------------------------------------------------------------- /img/Windows/StoreLogo.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/StoreLogo.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-100.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-100_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-100_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-125.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-125.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-125_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-125_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-150.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-150.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-150_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-150_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-200.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-200.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-200_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-200_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-400.png -------------------------------------------------------------------------------- /img/Windows/WideTile.scale-400_altform-colorful_theme-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/Windows/WideTile.scale-400_altform-colorful_theme-light.png -------------------------------------------------------------------------------- /img/ico/Sudo.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/Sudo.ico -------------------------------------------------------------------------------- /img/ico/_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_16.png -------------------------------------------------------------------------------- /img/ico/_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_20.png -------------------------------------------------------------------------------- /img/ico/_24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_24.png -------------------------------------------------------------------------------- /img/ico/_256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_256.png -------------------------------------------------------------------------------- /img/ico/_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_32.png -------------------------------------------------------------------------------- /img/ico/_40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_40.png -------------------------------------------------------------------------------- /img/ico/_48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_48.png -------------------------------------------------------------------------------- /img/ico/_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/microsoft/sudo/9c53e97eb4fc58c9e135045946881123e0851528/img/ico/_64.png -------------------------------------------------------------------------------- /img/svg/ic_fluent_Sudo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /owners.txt: -------------------------------------------------------------------------------- 1 | ; This owners file addition was requested by migrie@microsoft.com 2 | ; This owners.txt file was initially populated by Easy Start. Every code 3 | ; change inside of an Ownership Enforcer enabled branch (such as master) must be 4 | ; approved by at least one expert listed in an applicable owners.txt file. This 5 | ; root owners.txt file is applicable to every change. Targeted experts can be 6 | ; defined by placing an owners.txt file inside any subdirectory. More information 7 | ; about Ownership Enforcer can be found at https://aka.ms/ownershipenforcer. 8 | migrie 9 | duhowett -------------------------------------------------------------------------------- /scripts/sudo.ps1: -------------------------------------------------------------------------------- 1 | # Copyright (c) Microsoft Corporation. 2 | # Licensed under the MIT License. 3 | 4 | # open question - Should -NoProfile be used when invoking PowerShell 5 | BEGIN { 6 | if ($__SUDO_TEST -ne $true) { 7 | $SUDOEXE = "sudo.exe" 8 | } 9 | else { 10 | if ($null -eq $SUDOEXE) { 11 | throw "variable SUDOEXE has not been set for testing" 12 | } 13 | } 14 | 15 | if ([Environment]::OSVersion.Platform -ne "Win32NT") { 16 | throw "This script works only on Microsoft Windows" 17 | } 18 | 19 | if ($null -eq (Get-Command -Type Application -Name "$SUDOEXE" -ErrorAction Ignore)) { 20 | throw "'$SUDOEXE' cannot be found." 21 | } 22 | 23 | $psProcess = Get-Process -id $PID 24 | if (($null -eq $psProcess) -or ($psProcess.Count -ne 1)) { 25 | throw "Cannot retrieve process for '$PID'" 26 | } 27 | 28 | $thisPowerShell = $psProcess.MainModule.FileName 29 | if ($null -eq $thisPowerShell) { 30 | throw "Cannot determine path to '$psProcess'" 31 | } 32 | 33 | function convertToBase64EncodedString([string]$cmdLine) { 34 | $bytes = [System.Text.Encoding]::Unicode.GetBytes($cmdLine) 35 | [Convert]::ToBase64String($bytes) 36 | } 37 | 38 | $MI = $MyInvocation 39 | } 40 | 41 | END { 42 | $cmdArguments = $args 43 | 44 | # short-circuit if the user provided a scriptblock, then we will use it and ignore any other arguments 45 | if ($cmdArguments.Count -eq 1 -and $cmdArguments[0] -is [scriptblock]) { 46 | $scriptBlock = $cmdArguments[0] 47 | $encodedCommand = convertToBase64EncodedString -cmdLine ($scriptBlock.ToString()) 48 | if (($psversiontable.psversion.major -eq 7) -and ($__SUDO_DEBUG -eq $true)) { 49 | Trace-Command -PSHOST -name param* -Expression { & $SUDOEXE "$thisPowerShell" -e $encodedCommand } 50 | } 51 | else { 52 | & $SUDOEXE "$thisPowerShell" -e $encodedCommand 53 | } 54 | return 55 | } 56 | 57 | $cmdLine = $MI.Line 58 | $sudoOffset = $cmdLine.IndexOf($MI.InvocationName) 59 | $cmdLineWithoutScript = $cmdLine.SubString($sudoOffset + 5) 60 | $cmdLineAst = [System.Management.Automation.Language.Parser]::ParseInput($cmdLineWithoutScript, [ref]$null, [ref]$null) 61 | $commandAst = $cmdLineAst.Find({$args[0] -is [System.Management.Automation.Language.CommandAst]}, $false) 62 | $commandName = $commandAst.GetCommandName() 63 | $isApplication = Get-Command -Type Application -Name $commandName -ErrorAction Ignore | Select-Object -First 1 64 | $isCmdletOrScript = Get-Command -Type Cmdlet,ExternalScript -Name $commandName -ErrorAction Ignore | Select-Object -First 1 65 | 66 | # if the command is a native command, just invoke it 67 | if ($null -ne $isApplication) { 68 | if (($psversiontable.psversion.major -eq 7) -and ($__SUDO_DEBUG -eq $true)) { 69 | trace-command -PSHOST -name param* -Expression { & $SUDOEXE $cmdArguments } 70 | } 71 | else { 72 | & $SUDOEXE $cmdArguments 73 | } 74 | } 75 | elseif ($null -ne $isCmdletOrScript) { 76 | $encodedCommand = convertToBase64EncodedString($cmdLineWithoutScript) 77 | if (($psversiontable.psversion.major -eq 7) -and ($__SUDO_DEBUG -eq $true)) { 78 | trace-command -PSHOST -name param* -Expression { & $SUDOEXE -nologo -e $encodedCommand } 79 | } 80 | else { 81 | & $SUDOEXE $thisPowerShell -nologo -e $encodedCommand 82 | } 83 | } 84 | else { 85 | throw "Cannot find '$commandName'" 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /sudo/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sudo" 3 | version = "1.0.1" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | build = "build.rs" 9 | 10 | [[bin]] 11 | test = true 12 | name = "sudo" 13 | 14 | [build-dependencies] 15 | winres.workspace = true 16 | cc.workspace = true 17 | embed-manifest.workspace = true 18 | which = { workspace = true } 19 | 20 | [dependencies] 21 | 22 | clap = { workspace = true, default-features = false, features = ["color", "help", "usage", "error-context"] } 23 | which = { workspace = true } 24 | windows-registry = { workspace = true } 25 | 26 | sudo_events = { path = "../sudo_events" } 27 | win32resources = { path = "../win32resources" } 28 | 29 | [dependencies.windows] 30 | workspace = true 31 | features = [ 32 | "Wdk_Foundation", 33 | "Wdk_System_Threading", 34 | "Win32_Foundation", 35 | "Win32_Globalization", 36 | "Win32_Security", 37 | "Win32_Security_Authorization", 38 | "Win32_Storage_FileSystem", 39 | "Win32_System_Console", 40 | "Win32_System_Diagnostics_Debug", 41 | "Win32_System_Diagnostics_Etw", 42 | "Win32_System_Environment", 43 | "Win32_System_Kernel", 44 | "Win32_System_Memory", 45 | "Win32_System_Registry", 46 | "Win32_System_Rpc", 47 | "Win32_System_SystemInformation", 48 | "Win32_System_SystemServices", 49 | "Win32_System_Threading", 50 | "Win32_System_WindowsProgramming", 51 | "Win32_UI_Shell", 52 | "Win32_UI_WindowsAndMessaging", 53 | ] 54 | 55 | [features] 56 | # We attempt to use feature flags in a similar way to how the rest of the 57 | # Windows codebase does. We've got a set of "brandings", each which contain a 58 | # set of feature flags. Each branding is a superset of the previous branding, 59 | # and is progressively "less stable" that the previous. 60 | # 61 | # The idea is that we can build with a specific branding, and get all the 62 | # features that are enabled for that branding, plus all the "more stable" ones. 63 | # 64 | # We default to "Dev" branding, which has all the code turned on. Call `cargo 65 | # build --no-default-features --features Inbox` to just get the inbox build (for 66 | # example). 67 | 68 | ############################################ 69 | # Feature flags 70 | Feature_test_flag = [] # This is a test feature flag, to demo how they can be used. 71 | 72 | ############################################ 73 | # Branding 74 | # Put each individual feature flag into ONE of the following brandings 75 | Inbox = [] 76 | Stable = ["Inbox"] 77 | Dev = ["Stable", "Feature_test_flag"] 78 | 79 | # by default, build everything. This is a little different than you'd typically 80 | # expect for a rust crate, but since we're not actually expecting anyone to be 81 | # ingesting us as a crate, it's fine. 82 | default = ["Dev"] 83 | 84 | -------------------------------------------------------------------------------- /sudo/Resources/en-US/Sudo.resw: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | Sudo for Windows 122 | {Locked=qps-ploc,qps-ploca,qps-plocm} 123 | 124 | 125 | Sudo for Windows. 126 | Can be used to run a command as admin. When run, will prompt for confirmation with a User Accounts Control dialog. Currently only supports running commands as the admin user who confirms the dialog. 127 | 128 | If used to run a console application, sudo will return when the target process exits. 129 | If used to run a graphical application (for example, notepad.exe), sudo will return immediately. 130 | 131 | In New Window mode, sudo will launch applications from the Windows directory in C:\\Windows\\System32. You can use the --chdir option to change the working directory before running the command. 132 | 133 | If a mode is omitted, sudo will use the mode set in the system settings. If a mode is specified with one of --new-window, --disable-input, or --inline, sudo will exit with an error if that mode is not currently allowed by the system settings. 134 | 135 | {Locked="sudo","notepad.exe","C:\\Windows\\System32","--chdir"} 136 | 137 | 138 | Sudo is disabled on this machine. To enable it, go to the \x1b]8;;ms-settings:developers\x1b\\Developer Settings page\x1b]8;;\x1b\\ in the Settings app 139 | {Locked="\x1b]8;;ms-settings:developers\x1b\\","\x1b]8;;\x1b\\"} 140 | 141 | 142 | Print help (see less with '-h') 143 | {Locked="-h"} 144 | 145 | 146 | Print help (see more with '--help') 147 | {Locked="--help"} 148 | 149 | 150 | Print version 151 | 152 | 153 | The elevate subcommand is for internal use only 154 | {Locked="elevate"} 155 | 156 | 157 | Parent process ID 158 | 159 | 160 | Command-line to run 161 | 162 | 163 | Get current configuration information of sudo 164 | 165 | 166 | Run a command as admin 167 | 168 | 169 | Pass the current environment variables to the command 170 | 171 | 172 | Use a new window for the command 173 | 174 | 175 | Run in the current terminal, with input to the target application disabled 176 | 177 | 178 | Run in the current terminal 179 | Description of a command-line flag that will cause sudo to run the target application in the current console window. 180 | 181 | 182 | Command-line to run 183 | 184 | 185 | Sudo is disabled by your organization's policy. 186 | 187 | 188 | Sudo is disabled on this machine. 189 | 190 | 191 | Invalid mode: 192 | This string will be followed by a string the user entered (which was and invalid value) 193 | 194 | 195 | Error setting mode: 196 | This string will be followed by an error message 197 | 198 | 199 | Unknown error: 200 | This string will be followed by an error message 201 | 202 | 203 | Sudo is currently in Force New Window mode on this machine 204 | 205 | 206 | Sudo is currently in Disable Input mode on this machine 207 | Message printed to the user informing them of the current sudo mode. In this case, the mode is the "Disable Input" mode. 208 | 209 | 210 | Sudo is currently in Inline mode on this machine 211 | 212 | 213 | You must run this command as an administrator. 214 | 215 | 216 | You cannot set a mode higher than Force New Window mode on this machine 217 | Error message printed when the user attempts to set sudo into a mode higher than the mode currently allowed by policy. In this case, the currently allowed mode is the "Force New Window" mode. 218 | 219 | 220 | You cannot set a mode higher than Disable Input mode on this machine 221 | Error message printed when the user attempts to set sudo into a mode higher than the mode currently allowed by policy. In this case, the currently allowed mode is the "Disable Input" mode. 222 | 223 | 224 | You cannot set a mode higher than Inline mode on this machine 225 | Error message printed when the user attempts to set sudo into a mode higher than the mode currently allowed by policy. In this case, the currently allowed mode is the "Inline" mode. 226 | 227 | 228 | Sudo mode set to Force New Window mode 229 | 230 | 231 | Sudo mode set to DisableInput mode 232 | 233 | 234 | Sudo mode set to Inline mode 235 | 236 | 237 | Command not found 238 | 239 | 240 | Operation was cancelled by the user 241 | 242 | 243 | Launched {0} in a new window. 244 | {0} will be replaced by the name of a command-line executable 245 | 246 | 247 | Change the working directory before running the command 248 | 249 | 250 | You cannot run in a mode higher than Force New Window mode on this machine 251 | Error message printed when the user requested a mode higher than the currently allowed mode. In this case, the currently allowed mode is the "Force New Window" mode. 252 | 253 | 254 | You cannot run in a mode higher than Disable Input mode on this machine 255 | Error message printed when the user requested a mode higher than the currently allowed mode. In this case, the currently allowed mode is the "Disable Input" mode. 256 | 257 | 258 | You cannot run in a mode higher than Inline mode on this machine 259 | Error message printed when the user requested a mode higher than the currently allowed mode. In this case, the currently allowed mode is the "Inline" mode. 260 | 261 | 262 | You are not allowed to preserve environment variables 263 | Error message printed when the user tries to preserve environment variables, but is not allowed to 264 | 265 | 266 | You are not allowed to run sudo 267 | Error message printed when the user is not allowed to run sudo because they aren't an administrator 268 | 269 | 270 | set USERPROFILE variable to target user's USERPROFILE 271 | {Locked="USERPROFILE"} Help text for a commandline arg that sets the USERPROFILE variable 272 | 273 | 274 | -------------------------------------------------------------------------------- /sudo/build.rs: -------------------------------------------------------------------------------- 1 | use embed_manifest::embed_manifest_file; 2 | use std::path::PathBuf; 3 | use std::process::Command; 4 | use { 5 | std::{env, io}, 6 | winres::WindowsResource, 7 | }; 8 | 9 | fn get_sdk_path() -> Option { 10 | let mut sdk_path: Option = None; 11 | let target = env::var("TARGET").unwrap(); 12 | 13 | // For whatever reason, find_tool doesn't work directly on `midl.exe`. It 14 | // DOES work however, on `link.exe`, and will hand us back a PATH that has 15 | // the path to the appropriate midl.exe in it. 16 | let link_exe = cc::windows_registry::find_tool(target.as_str(), "link.exe") 17 | .expect("Failed to find link.exe"); 18 | link_exe.env().iter().for_each(|(k, v)| { 19 | if k == "PATH" { 20 | let elements = (v.to_str().expect("path exploded")) 21 | .split(';') 22 | .collect::>(); 23 | // iterate over the elements to find one that starts with 24 | // "C:\Program Files (x86)\Windows Kits\10\bin\10.0.*" 25 | for element in elements { 26 | if element.starts_with("C:\\Program Files (x86)\\Windows Kits\\10\\bin\\10.0.") { 27 | sdk_path = Some(element.to_string()); 28 | } 29 | } 30 | } 31 | }); 32 | sdk_path 33 | } 34 | 35 | fn get_sdk_tool(sdk_path: &Option, tool_name: &str) -> String { 36 | // seems like, in a VS tools prompt, midl.exe is in the path so the above 37 | // doesn't include the path. kinda weird but okay? 38 | let tool_path = match sdk_path { 39 | Some(s) => PathBuf::from(s) 40 | .join(tool_name) 41 | .to_str() 42 | .unwrap() 43 | .to_owned(), 44 | None => { 45 | // This is the case that happens when you run the build from a VS 46 | // tools prompt. In this case, the tool is already in the path, so 47 | // we can just get the absolute path to the exe using the windows 48 | // path search. 49 | 50 | let tool_path = which::which(tool_name).expect("Failed to find tool in path"); 51 | tool_path.to_str().unwrap().to_owned() 52 | } 53 | }; 54 | tool_path 55 | } 56 | 57 | fn build_rpc() { 58 | // Build our RPC library 59 | 60 | let sdk_path: Option = get_sdk_path(); 61 | let midl_path = get_sdk_tool(&sdk_path, "midl.exe"); 62 | 63 | // Now, we need to get the path to the shared include directory, which is 64 | // dependent on the SDK version. We're gonna find it based on the midl we 65 | // already found. 66 | // 67 | // Our midl path is now something like: 68 | // C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\midl.exe 69 | // 70 | // We want to get the path to the shared include directory, which is like 71 | // 72 | // C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared 73 | // 74 | // (of course, the version number will change depending on the SDK version) 75 | // So, just take that path, remove two elements from the end, replace bin with Include, and add shared. 76 | let mut include_path = PathBuf::from(midl_path.clone()); 77 | include_path.pop(); 78 | include_path.pop(); 79 | // now we're at C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0 80 | let copy_of_include_path = include_path.clone(); 81 | let version = copy_of_include_path.file_name().unwrap().to_str().unwrap(); 82 | include_path.pop(); 83 | include_path.pop(); 84 | // now we're at C:\Program Files (x86)\Windows Kits\10\ 85 | include_path.push("Include"); 86 | include_path.push(version); 87 | include_path.push("shared"); 88 | 89 | println!("midl_path: {:?}", midl_path); 90 | 91 | let target = env::var("TARGET").unwrap(); 92 | 93 | let cl_path = 94 | cc::windows_registry::find_tool(target.as_str(), "cl.exe").expect("Failed to find cl.exe"); 95 | // add cl.exe to our path 96 | let mut path = env::var("PATH").unwrap(); 97 | path.push(';'); 98 | path.push_str(cl_path.path().parent().unwrap().to_str().unwrap()); 99 | env::set_var("PATH", path); 100 | 101 | // Great! we've now finally got a path to midl.exe, and cl.exe is on the PATH 102 | 103 | // Now we can actually run midl.exe, to compile the IDL file. This will 104 | // generate a bunch of files in the OUT_DIR which we need to do RPC. 105 | 106 | let mut cmd = Command::new(midl_path); 107 | cmd.arg("../cpp/rpc/sudo_rpc.idl"); 108 | cmd.arg("/h").arg("sudo_rpc.h"); 109 | cmd.arg("/target").arg("NT100"); // LOAD BEARING: Enables system_handle 110 | cmd.arg("/acf").arg("../cpp/rpc/sudo_rpc.acf"); 111 | cmd.arg("/prefix").arg("client").arg("client_"); 112 | cmd.arg("/prefix").arg("server").arg("server_"); 113 | cmd.arg("/oldnames"); 114 | cmd.arg("/I").arg(include_path); 115 | 116 | // Force midl to use the right architecture depending on our Rust target. 117 | cmd.arg("/env").arg(match target.as_str() { 118 | "x86_64-pc-windows-msvc" => "x64", 119 | "i686-pc-windows-msvc" => "win32", 120 | "aarch64-pc-windows-msvc" => "arm64", 121 | _ => panic!("Unknown target {}", target), 122 | }); 123 | 124 | // I was pretty confident that we needed to pass /protocol ndr64 here, but 125 | // if we do that it'll break the win32 build. Omitting it entirely seems to 126 | // Just Work. 127 | // cmd.arg("/protocol").arg("ndr64"); 128 | 129 | cmd.arg("/out").arg(env::var("OUT_DIR").unwrap()); 130 | 131 | println!("Full midl command: {:?}", cmd); 132 | let mut midl_result = cmd.spawn().expect("Failed to run midl.exe"); 133 | println!( 134 | "midl.exe returned {:?}", 135 | midl_result.wait().expect("midl.exe failed") 136 | ); 137 | 138 | // Now that our PRC header and stubs were generated, we can compile them 139 | // into our actual RPC lib. 140 | let mut rpc_build = cc::Build::new(); 141 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 142 | rpc_build 143 | .warnings(true) 144 | .warnings_into_errors(true) 145 | .include(env::var("OUT_DIR").unwrap()) 146 | .file(out_dir.join("sudo_rpc_c.c")) 147 | .file(out_dir.join("sudo_rpc_s.c")) 148 | .file("../cpp/rpc/RpcClient.c") 149 | .flag("/guard:ehcont"); 150 | 151 | println!("build cmdline: {:?}", rpc_build.get_compiler().to_command()); 152 | rpc_build.compile("myRpc"); 153 | println!("cargo:rustc-link-lib=myRpc"); 154 | 155 | println!("cargo:rerun-if-changed=../cpp/rpc/RpcClient.c"); 156 | println!("cargo:rerun-if-changed=../cpp/rpc/sudo_rpc.idl"); 157 | } 158 | 159 | fn build_logging() { 160 | // Build our Event Logging library 161 | 162 | let sdk_path: Option = get_sdk_path(); 163 | let mc_path = get_sdk_tool(&sdk_path, "mc.exe"); 164 | 165 | println!("mc_path: {:?}", mc_path); 166 | 167 | let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); 168 | 169 | let mut cmd = Command::new(mc_path); 170 | cmd.arg("-h").arg(&out_dir); 171 | cmd.arg("-r").arg(&out_dir); 172 | cmd.arg("../cpp/logging/instrumentation.man"); 173 | 174 | println!("Full mc command: {:?}", cmd); 175 | 176 | let mc_result = cmd 177 | .spawn() 178 | .expect("Failed to run mc.exe") 179 | .wait() 180 | .expect("mc.exe failed"); 181 | if !mc_result.success() { 182 | eprintln!("\n\nerror occurred: {}\n\n", mc_result); 183 | std::process::exit(1); 184 | } 185 | 186 | let mut logging_build = cc::Build::new(); 187 | logging_build 188 | .warnings(true) 189 | .warnings_into_errors(true) 190 | .include(env::var("OUT_DIR").unwrap()) 191 | .file("../cpp/logging/EventViewerLogging.c") 192 | .flag("/guard:ehcont"); 193 | 194 | println!( 195 | "build cmdline: {:?}", 196 | logging_build.get_compiler().to_command() 197 | ); 198 | logging_build.compile("myEventLogging"); 199 | println!("cargo:rustc-link-lib=myEventLogging"); 200 | 201 | println!("cargo:rerun-if-changed=../cpp/logging/EventViewerLogging.c"); 202 | println!("cargo:rerun-if-changed=../cpp/logging/instrumentation.man"); 203 | } 204 | 205 | fn main() -> io::Result<()> { 206 | // Always build the RPC lib. 207 | build_rpc(); 208 | 209 | // Always build the Event Logging lib. 210 | build_logging(); 211 | 212 | println!("cargo:rerun-if-changed=sudo/Resources/en-US/Sudo.resw"); 213 | println!("cargo:rerun-if-changed=sudo.rc"); 214 | println!("cargo:rerun-if-changed=../Generated Files/out.rc"); 215 | println!("cargo:rerun-if-changed=../Generated Files/out_resources.h"); 216 | 217 | // compile the resource file. 218 | // Run 219 | // powershell -c .pipelines\convert-resx-to-rc.ps1 .\ no_existy.h res.h no_existy.rc out.rc resource_ids.rs 220 | // to generate the resources 221 | 222 | let generate_resources_result = Command::new("powershell") 223 | .arg("-NoProfile") 224 | .arg("-c") 225 | .arg("..\\.pipelines\\convert-resx-to-rc.ps1") 226 | .arg("..\\") // Root directory which contains the resx files 227 | .arg("no_existy.h") // File name of the base resource.h which contains all the non-localized resource definitions 228 | .arg("resource.h") // Target file name of the resource header file, which will be used in code - Example: resource.h 229 | .arg("sudo\\sudo.rc") // File name of the base ProjectName.rc which contains all the non-localized resources 230 | .arg("out.rc") // Target file name of the resource rc file, which will be used in code - Example: ProjectName.rc 231 | .arg("resource_ids.rs") // Target file name of the rust resource file, which will be used in code - Example: resource.rs 232 | .status() 233 | .expect("Failed to generate resources"); 234 | 235 | if !generate_resources_result.success() { 236 | println!( 237 | "\nFailed to generate resources by executing powershell script: {}.", 238 | generate_resources_result 239 | ); 240 | println!( 241 | "Maybe you haven't granted the access to execute the powershell script on this system." 242 | ); 243 | println!("For more details, please execute the `cargo build` command with the `-vv` flag."); 244 | std::process::exit(1); 245 | } 246 | 247 | // witchcraft to get windows.h from the SDK to be able to be found, for the resource compiler 248 | let target = env::var("TARGET").unwrap(); 249 | if let Some(tool) = cc::windows_registry::find_tool(target.as_str(), "cl.exe") { 250 | for (key, value) in tool.env() { 251 | env::set_var(key, value); 252 | } 253 | } 254 | 255 | if env::var_os("CARGO_CFG_WINDOWS").is_some() { 256 | // TODO:MSFT 257 | // Re-add the following: 258 | // 259 | // detached 260 | // 261 | // to our manifest 262 | embed_manifest_file("sudo.manifest").expect("Failed to embed manifest"); 263 | 264 | let generated_rc_content = std::fs::read_to_string("../Generated Files/out.rc").unwrap(); 265 | let instrumentation_rc_content = 266 | std::fs::read_to_string(env::var("OUT_DIR").unwrap() + "/instrumentation.rc").unwrap(); 267 | let generated_header = std::fs::read_to_string("../Generated Files/resource.h").unwrap(); 268 | WindowsResource::new() 269 | // We don't want to use set_resource_file here, because we _do_ want 270 | // the file version info that winres can autogenerate. Instead, 271 | // manually stitch in our generated header (with resource IDs), and 272 | // our generated rc file (with the localized strings) 273 | .append_rc_content(&generated_header) 274 | .append_rc_content(&instrumentation_rc_content) 275 | .append_rc_content(&generated_rc_content) 276 | .compile()?; 277 | } 278 | Ok(()) 279 | } 280 | 281 | // Magic incantation to get the build to generate the .rc file, before we build things: 282 | // 283 | // powershell -c .pipelines\convert-resx-to-rc.ps1 src\cascadia\ this_doesnt_exist.h out_resources.h no_existy.rc out.rc resource_ids.rs 284 | // 285 | // do that from the root of the repo, and it will generate the .rc file, into 286 | // src\cascadia\Generated Files\{out.rc, out_resources.h} 287 | // 288 | // 289 | // Alternatively, 290 | // powershell -c .pipelines\convert-resx-to-rc.ps1 .\ no_existy.h res.h no_existy.rc out.rc resource_ids.rs 291 | // 292 | // will generate the .rc file into the a "Generated Files" dir in the root of the repo. 293 | -------------------------------------------------------------------------------- /sudo/src/elevate_handler.rs: -------------------------------------------------------------------------------- 1 | use crate::helpers::*; 2 | use crate::logging_bindings::event_log_request; 3 | use crate::messages::ElevateRequest; 4 | use crate::rpc_bindings_server::rpc_server_setup; 5 | use crate::tracing; 6 | use std::ffi::CString; 7 | use std::os::windows::io::{FromRawHandle, IntoRawHandle}; 8 | use std::os::windows::process::CommandExt; 9 | use std::process::Stdio; 10 | use windows::{ 11 | core::*, Win32::Foundation::*, Win32::System::Console::*, Win32::System::Threading::*, 12 | }; 13 | 14 | fn handle_to_stdio(h: HANDLE) -> Stdio { 15 | if h.is_invalid() { 16 | return Stdio::inherit(); 17 | } 18 | 19 | unsafe { 20 | let p = GetCurrentProcess(); 21 | let mut clone = Default::default(); 22 | match DuplicateHandle(p, h, p, &mut clone, 0, true, DUPLICATE_SAME_ACCESS) { 23 | Ok(_) => Stdio::from_raw_handle(clone.0 as _), 24 | Err(_) => Stdio::null(), 25 | } 26 | } 27 | } 28 | 29 | /// Prepare the target process, spawn it, and hand back the Child process. This will take care of setting up the handles for redirected input/output, and setting the environment variables. 30 | pub fn spawn_target_for_request(request: &ElevateRequest) -> Result { 31 | tracing::trace_log_message(&format!("Spawning: {}...", &request.application)); 32 | 33 | let mut command_args = std::process::Command::new(request.application.clone()); 34 | 35 | command_args.current_dir(request.target_dir.clone()); 36 | command_args.args(request.args.clone()); 37 | 38 | tracing::trace_log_message(&format!("args: {:?}", &request.args)); 39 | 40 | if !request.env_vars.is_empty() { 41 | command_args.env_clear(); 42 | command_args.envs(env_from_raw_bytes(&request.env_vars)); 43 | } 44 | 45 | // If we're in ForceNewWindow mode, we want the target process to use a new 46 | // console window instead of inheriting the one from the parent process. 47 | if request.sudo_mode == SudoMode::ForceNewWindow { 48 | command_args.creation_flags(CREATE_NEW_CONSOLE.0); 49 | } 50 | 51 | // Set the stdin/stdout/stderr of the child process In disabled input 52 | // mode, set stdin to null. We don't want the target application to be 53 | // able to read anything from stdin. 54 | command_args.stdin(if request.sudo_mode != SudoMode::DisableInput { 55 | handle_to_stdio(request.handles[0]) 56 | } else { 57 | Stdio::null() 58 | }); 59 | command_args.stdout(handle_to_stdio(request.handles[1])); 60 | command_args.stderr(handle_to_stdio(request.handles[2])); 61 | 62 | command_args.spawn().map_err(|err| { 63 | match err.kind() { 64 | std::io::ErrorKind::NotFound => { 65 | // This error code is MSG_DIR_BAD_COMMAND_OR_FILE. That's 66 | // what CMD uses to indicate a command not found. 67 | E_DIR_BAD_COMMAND_OR_FILE.into() 68 | } 69 | _ => err.into(), 70 | } 71 | }) 72 | } 73 | 74 | /// Execute the elevation request. 75 | /// * Conditionally attach to the parent process's console (if requested) 76 | /// * Spawn the target process (with redirected input/output if requested, and with the environment variables passed in if needed) 77 | /// Called by rust_handle_elevation_request 78 | pub fn handle_elevation_request(request: &ElevateRequest) -> Result> { 79 | // Log the request we received to the event log. This should create a pair 80 | // of events, one for the request, and one for the response, each with the 81 | // same RequestID. 82 | event_log_request(false, request); 83 | 84 | // Check if the requested sudo mode is allowed 85 | let config: RegistryConfigProvider = Default::default(); 86 | let allowed_mode = get_allowed_mode(&config)?; 87 | if request.sudo_mode > allowed_mode { 88 | tracing::trace_log_message(&format!( 89 | "Requested sudo mode is not allowed: {:?} ({:?})", 90 | request.sudo_mode, allowed_mode 91 | )); 92 | return Err(E_ACCESSDENIED.into()); 93 | } 94 | 95 | // If we're in ForceNewWindow mode, we _don't_ want to detach from our 96 | // current console and reattach to the parent process's console. Instead, 97 | // we'll just create the target process with CREATE_NEW_CONSOLE. 98 | // 99 | // This scenario only happens when we're running `sudo -E --newWindow`, to 100 | // copy env vars but also use a new console window. If we don't pass -E, 101 | // then we'll have instead just directly ShellExecute'd the target 102 | // application (and never hit this codepath) 103 | // 104 | // Almost all the time, we'll actually hit the body of this conditional. 105 | if request.sudo_mode != SudoMode::ForceNewWindow { 106 | // It would seem that we always need to detach from the current console, 107 | // even in redirected i/o mode. In the case that we aren't fully redirected 108 | // (like, if stdin is redirected but stdout isn't), we'll still need to 109 | // attach to the parent console for the other std handles. 110 | 111 | unsafe { 112 | // Detach from the current console 113 | _ = FreeConsole(); 114 | 115 | // Attach to the parent process's console 116 | if { AttachConsole(request.parent_pid) }.is_ok() { 117 | // Add our own CtrlC handler, so that we can ignore it. 118 | _ = SetConsoleCtrlHandler(Some(ignore_ctrl_c), true); 119 | // TODO! add some error handling here you goober 120 | } 121 | } 122 | } 123 | 124 | // We're attached to the right console, Run the command. 125 | let process_launch = spawn_target_for_request(request); 126 | unsafe { 127 | _ = SetConsoleCtrlHandler(Some(ignore_ctrl_c), false); 128 | _ = FreeConsole(); 129 | } 130 | 131 | let child = process_launch?; 132 | 133 | // Limit the things the caller can do with the process handle, because the one we just created is PROCESS_ALL_ACCESS. 134 | // I tried to use [out, system_handle(sh_process, PROCESS_QUERY_LIMITED_INFORMATION)] 135 | // in the COM API to have it limit the handle permissions but that didn't work at all. 136 | // So now we do it manually here. 137 | unsafe { 138 | let mut child_handle = Owned::default(); 139 | let current_process = GetCurrentProcess(); 140 | DuplicateHandle( 141 | current_process, 142 | HANDLE(child.into_raw_handle() as _), 143 | current_process, 144 | &mut *child_handle, 145 | (PROCESS_QUERY_LIMITED_INFORMATION | PROCESS_DUP_HANDLE | PROCESS_SYNCHRONIZE).0, 146 | false, 147 | DUPLICATE_CLOSE_SOURCE, 148 | )?; 149 | Ok(child_handle) 150 | } 151 | } 152 | 153 | /// Starts the RPC server and blocks until Shutdown() is called. 154 | pub fn start_rpc_server( 155 | parent_pid: u32, 156 | nonce: u32, 157 | _caller_sid: Option<&String>, 158 | _args: &[&String], 159 | ) -> Result { 160 | // TODO:48520593 In rust_handle_elevation_request, validate that the parent 161 | // process handle is the same one that we opened here. 162 | 163 | let endpoint = generate_rpc_endpoint_name(parent_pid, nonce); 164 | let endpoint = CString::new(endpoint).unwrap(); 165 | rpc_server_setup(&endpoint, parent_pid)?; 166 | 167 | Ok(0) 168 | } 169 | -------------------------------------------------------------------------------- /sudo/src/logging_bindings.rs: -------------------------------------------------------------------------------- 1 | use crate::helpers::join_args; 2 | use crate::messages::ElevateRequest; 3 | use std::env; 4 | use std::ffi::CString; 5 | use std::mem::size_of_val; 6 | use std::ops::{Deref, DerefMut}; 7 | use std::ptr::addr_of; 8 | use windows::core::*; 9 | use windows::Win32::System::Diagnostics::Etw::*; 10 | 11 | // These come from cpp/logging/EventViewerLogging.c 12 | extern "C" { 13 | static PROVIDER_GUID: GUID; 14 | static SudoRequestRunEvent: EVENT_DESCRIPTOR; 15 | static SudoRecieveRunRequestEvent: EVENT_DESCRIPTOR; 16 | } 17 | 18 | #[repr(transparent)] 19 | #[derive(Default)] 20 | struct OwnedReghandle(pub u64); 21 | 22 | impl Drop for OwnedReghandle { 23 | fn drop(&mut self) { 24 | if self.0 != 0 { 25 | unsafe { 26 | EventUnregister(self.0); 27 | } 28 | } 29 | } 30 | } 31 | 32 | impl Deref for OwnedReghandle { 33 | type Target = u64; 34 | 35 | fn deref(&self) -> &Self::Target { 36 | &self.0 37 | } 38 | } 39 | 40 | impl DerefMut for OwnedReghandle { 41 | fn deref_mut(&mut self) -> &mut Self::Target { 42 | &mut self.0 43 | } 44 | } 45 | 46 | fn str_to_cstr_vec>>(s: T) -> Vec { 47 | CString::new(s) 48 | .expect("strings should not have nulls") 49 | .into_bytes_with_nul() 50 | } 51 | 52 | fn create_descriptor(ptr: *const T, len: U) -> EVENT_DATA_DESCRIPTOR 53 | where 54 | U: TryInto, 55 | >::Error: std::fmt::Debug, 56 | { 57 | EVENT_DATA_DESCRIPTOR { 58 | Ptr: ptr as _, 59 | Size: len.try_into().unwrap(), 60 | Anonymous: Default::default(), 61 | } 62 | } 63 | 64 | /// Writes this request to the Windows Event Log. We do this for admins to be 65 | /// able to audit who's calling what with sudo. 66 | /// We log our messages to "Applications and Services Logs" -> "Microsoft" -> 67 | /// "Windows" -> "Sudo" -> "Admin". 68 | /// 69 | /// Alternatively, you can view this log with 70 | /// `wevtutil qe Microsoft-Windows-Sudo/Admin /c:3 /rd:true /f:text` 71 | pub fn event_log_request(is_client: bool, req: &ElevateRequest) { 72 | let mut registration_handle = OwnedReghandle::default(); 73 | // The error code returned by EventRegister is primarily intended for use in debugging and diagnostic scenarios. 74 | // Most production code should continue to run even if an ETW provider failed to register, 75 | // so release builds should usually ignore the error code returned by EventRegister. 76 | unsafe { EventRegister(&PROVIDER_GUID, None, None, &mut *registration_handle) }; 77 | 78 | let application = str_to_cstr_vec(req.application.as_str()); 79 | let args_len = req.args.len() as u32; 80 | let args: Vec<_> = req 81 | .args 82 | .iter() 83 | .map(|arg| str_to_cstr_vec(arg.as_str())) 84 | .collect(); 85 | let cwd = str_to_cstr_vec(req.target_dir.as_str()); 86 | let mode = req.sudo_mode as u32; 87 | let inherit_env = !req.env_vars.is_empty(); 88 | let redirected = req.handles.iter().any(|h| !h.is_invalid()); 89 | let commandline = str_to_cstr_vec(format!( 90 | "{} {} {}", 91 | env::current_exe().unwrap().display(), 92 | req.application, 93 | join_args(&req.args) 94 | )); 95 | let request_id = req.event_id; 96 | 97 | let mut descriptors = Vec::with_capacity(9 + args.len()); 98 | // 99 | descriptors.push(create_descriptor(application.as_ptr(), application.len())); 100 | // 101 | descriptors.push(create_descriptor( 102 | addr_of!(args_len), 103 | size_of_val(&args_len), 104 | )); 105 | // 106 | for arg in &args { 107 | descriptors.push(EVENT_DATA_DESCRIPTOR { 108 | Ptr: arg.as_ptr() as _, 109 | Size: arg.len() as u32, 110 | Anonymous: Default::default(), 111 | }); 112 | } 113 | // 114 | descriptors.push(create_descriptor(cwd.as_ptr(), cwd.len())); 115 | // 116 | descriptors.push(create_descriptor(addr_of!(mode), size_of_val(&mode))); 117 | // 118 | descriptors.push(create_descriptor( 119 | addr_of!(inherit_env), 120 | size_of_val(&inherit_env), 121 | )); 122 | // 123 | descriptors.push(create_descriptor( 124 | addr_of!(redirected), 125 | size_of_val(&redirected), 126 | )); 127 | // 128 | descriptors.push(create_descriptor(commandline.as_ptr(), commandline.len())); 129 | // 130 | descriptors.push(create_descriptor( 131 | addr_of!(request_id), 132 | size_of_val(&request_id), 133 | )); 134 | 135 | unsafe { 136 | // We're literally using the same data template for both requests and 137 | // responses. The only difference is the event ID's have different keywords 138 | // (to ID who sent the event). 139 | let event_id = if is_client { 140 | &SudoRequestRunEvent 141 | } else { 142 | &SudoRecieveRunRequestEvent 143 | }; 144 | EventWrite(*registration_handle, event_id, Some(&descriptors)); 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /sudo/src/messages.rs: -------------------------------------------------------------------------------- 1 | use crate::helpers::SudoMode; 2 | use windows::{core::GUID, Win32::Foundation::HANDLE}; 3 | 4 | pub struct ElevateRequest { 5 | pub parent_pid: u32, 6 | pub handles: [HANDLE; 3], // in, out, err 7 | pub sudo_mode: SudoMode, 8 | pub application: String, 9 | pub args: Vec, 10 | pub target_dir: String, 11 | pub env_vars: String, 12 | pub event_id: GUID, 13 | } 14 | -------------------------------------------------------------------------------- /sudo/src/r.rs: -------------------------------------------------------------------------------- 1 | //! This file includes all our resource IDs, and the code to load them. The 2 | //! handy string_resources macro does the magic to create a StaticStringResource 3 | //! for each of the resource IDs, and then we can use them in code. 4 | //! 5 | //! Example usage: 6 | //! let world = r::IDS_WORLD.get(); 7 | //! println!("Hello: {}", world); 8 | 9 | #![allow(dead_code)] 10 | use win32resources::StaticStringResource; 11 | macro_rules! string_resources { 12 | ( 13 | $( 14 | $name:ident = $value:expr ; 15 | )* 16 | ) => { 17 | $( 18 | pub static $name: StaticStringResource = StaticStringResource::new($value, stringify!($name)); 19 | )* 20 | } 21 | } 22 | 23 | include!("../../Generated Files/resource_ids.rs"); 24 | -------------------------------------------------------------------------------- /sudo/src/rpc_bindings.rs: -------------------------------------------------------------------------------- 1 | use std::cmp::min; 2 | use std::marker::PhantomData; 3 | use std::slice::from_raw_parts; 4 | use std::str::from_utf8; 5 | use windows::{core::*, Win32::Foundation::*}; 6 | 7 | #[repr(C)] 8 | #[derive(Copy, Clone)] 9 | pub struct Utf8Str<'a> { 10 | length: u32, 11 | data: *const u8, 12 | _marker: PhantomData<&'a str>, 13 | } 14 | 15 | impl<'a> Utf8Str<'a> { 16 | pub fn new(s: &str) -> Utf8Str { 17 | Utf8Str { 18 | length: min(s.len(), u32::MAX as usize) as u32, 19 | data: s.as_ptr(), 20 | _marker: PhantomData, 21 | } 22 | } 23 | 24 | pub fn as_str(&self) -> Result<&str> { 25 | from_utf8(unsafe { from_raw_parts(self.data, self.length as usize) }) 26 | .map_err(|_| ERROR_NO_UNICODE_TRANSLATION.to_hresult().into()) 27 | } 28 | } 29 | 30 | impl<'a> From<&'a str> for Utf8Str<'a> { 31 | fn from(value: &'a str) -> Self { 32 | Utf8Str::new(value) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /sudo/src/rpc_bindings_client.rs: -------------------------------------------------------------------------------- 1 | use crate::helpers::SudoMode; 2 | use crate::rpc_bindings::Utf8Str; 3 | use std::ffi::{c_void, CStr}; 4 | use windows::core::{s, GUID, HRESULT, PCSTR, PSTR}; 5 | use windows::Win32::Foundation::HANDLE; 6 | use windows::Win32::Storage::FileSystem::{GetFileType, FILE_TYPE_DISK, FILE_TYPE_PIPE}; 7 | use windows::Win32::System::Rpc::{ 8 | RpcBindingFree, RpcBindingFromStringBindingA, RpcMgmtIsServerListening, 9 | RpcStringBindingComposeA, RpcStringFreeA, RPC_STATUS, RPC_S_OK, 10 | }; 11 | 12 | extern "C" { 13 | static mut client_sudo_rpc_ClientIfHandle: *mut c_void; 14 | 15 | fn seh_wrapper_client_DoElevationRequest( 16 | binding: *mut c_void, 17 | parent_handle: HANDLE, 18 | pipe_handles: *const [HANDLE; 3], // in, out, err 19 | file_handles: *const [HANDLE; 3], // in, out, err 20 | sudo_mode: u32, 21 | application: Utf8Str, 22 | args: Utf8Str, 23 | target_dir: Utf8Str, 24 | env_vars: Utf8Str, 25 | event_id: GUID, 26 | child: *mut HANDLE, 27 | ) -> HRESULT; 28 | 29 | fn seh_wrapper_client_Shutdown(binding: *mut c_void) -> HRESULT; 30 | } 31 | 32 | pub fn rpc_client_setup(endpoint: &CStr) -> RPC_STATUS { 33 | unsafe { 34 | let mut string_binding = PSTR::null(); 35 | let status = RpcStringBindingComposeA( 36 | /* ObjUuid */ None, 37 | /* ProtSeq */ s!("ncalrpc"), 38 | /* NetworkAddr */ None, 39 | /* Endpoint */ PCSTR(endpoint.as_ptr() as _), 40 | /* Options */ None, 41 | /* StringBinding */ Some(&mut string_binding), 42 | ); 43 | if status != RPC_S_OK { 44 | return status; 45 | } 46 | 47 | let status = RpcBindingFromStringBindingA( 48 | PCSTR(string_binding.0), 49 | std::ptr::addr_of_mut!(client_sudo_rpc_ClientIfHandle), 50 | ); 51 | // Don't forget to free the previously allocated string before potentially returning. :) 52 | _ = RpcStringFreeA(&mut string_binding); 53 | if status != RPC_S_OK { 54 | return status; 55 | } 56 | 57 | RpcMgmtIsServerListening(Some(client_sudo_rpc_ClientIfHandle)) 58 | } 59 | } 60 | 61 | /// Cleans up the RPC server. This is implemented on the server-side in 62 | /// server_Shutdown. It will TerminateProcess the RPC server, really really 63 | /// making sure no one can use it anymore. 64 | pub fn rpc_client_cleanup() { 65 | unsafe { 66 | _ = seh_wrapper_client_Shutdown(client_sudo_rpc_ClientIfHandle); 67 | _ = RpcBindingFree(std::ptr::addr_of_mut!(client_sudo_rpc_ClientIfHandle)); 68 | } 69 | } 70 | 71 | #[allow(clippy::too_many_arguments)] 72 | pub fn rpc_client_do_elevation_request( 73 | parent_handle: HANDLE, 74 | handles: &[HANDLE; 3], // in, out, err 75 | sudo_mode: SudoMode, 76 | application: Utf8Str, 77 | args: Utf8Str, 78 | target_dir: Utf8Str, 79 | env_vars: Utf8Str, 80 | event_id: GUID, 81 | child: *mut HANDLE, 82 | ) -> HRESULT { 83 | let mut pipe_handles = [HANDLE::default(); 3]; 84 | let mut file_handles = [HANDLE::default(); 3]; 85 | 86 | for i in 0..3 { 87 | match unsafe { GetFileType(handles[i]) } { 88 | FILE_TYPE_PIPE => pipe_handles[i] = handles[i], 89 | FILE_TYPE_DISK => file_handles[i] = handles[i], 90 | _ => {} 91 | } 92 | } 93 | 94 | unsafe { 95 | seh_wrapper_client_DoElevationRequest( 96 | client_sudo_rpc_ClientIfHandle, 97 | parent_handle, 98 | &pipe_handles, 99 | &file_handles, 100 | sudo_mode.into(), 101 | application, 102 | args, 103 | target_dir, 104 | env_vars, 105 | event_id, 106 | child, 107 | ) 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /sudo/src/rpc_bindings_server.rs: -------------------------------------------------------------------------------- 1 | use crate::helpers::*; 2 | use crate::{ 3 | elevate_handler::handle_elevation_request, messages::ElevateRequest, rpc_bindings::Utf8Str, 4 | }; 5 | use std::ffi::{c_void, CStr}; 6 | use std::mem::{size_of, take}; 7 | use std::ptr::null_mut; 8 | use std::sync::atomic::{AtomicBool, Ordering}; 9 | use windows::Win32::Foundation::{ERROR_BUSY, GENERIC_ALL, HANDLE, PSID}; 10 | use windows::{ 11 | core::*, Win32::Security::Authorization::*, Win32::Security::*, Win32::System::Memory::*, 12 | Win32::System::Rpc::*, Win32::System::SystemServices::*, Win32::System::Threading::*, 13 | }; 14 | 15 | extern "C" { 16 | static mut server_sudo_rpc_ServerIfHandle: *mut c_void; 17 | } 18 | 19 | static mut EXPECTED_CLIENT_PID: u32 = 0; 20 | 21 | // Process-wide mutex to ensure that only one request is handled at a time. The 22 | // bool inside the atomic is true if we've already started handling a request. 23 | static RPC_SERVER_IN_USE: AtomicBool = AtomicBool::new(false); 24 | 25 | // * Context: The callback function may pass this handle to 26 | // RpcImpersonateClient, RpcBindingServerFromClient, 27 | // RpcGetAuthorizationContextForClient, or any other server side function that 28 | // accepts a client binding handle to obtain information about the client. 29 | // 30 | // The callback function should return RPC_S_OK, if the client is allowed to 31 | // call methods in this interface. 32 | unsafe extern "system" fn rpc_server_callback( 33 | _interface_uuid: *const c_void, 34 | context: *const c_void, 35 | ) -> RPC_STATUS { 36 | let mut client_handle = Owned::default(); 37 | let status = I_RpcOpenClientProcess( 38 | Some(context), 39 | PROCESS_QUERY_LIMITED_INFORMATION.0, 40 | &mut *client_handle as *mut _ as _, 41 | ); 42 | if status != RPC_S_OK { 43 | return status; 44 | } 45 | 46 | // Check #1: We'll check that the client process is the one we expected, 47 | // when we were first started. 48 | let client_pid = GetProcessId(*client_handle); // if this fails, it returns 0 49 | if client_pid == 0 || client_pid != EXPECTED_CLIENT_PID { 50 | return RPC_S_ACCESS_DENIED; 51 | } 52 | 53 | // Check #2: Check that the client process is the same as the server process. 54 | if check_client(*client_handle).is_err() { 55 | return RPC_S_ACCESS_DENIED; 56 | } 57 | 58 | RPC_S_OK 59 | } 60 | 61 | // MSDN regarding SetSecurityDescriptorSacl: 62 | // > The SACL is referenced by, not copied into, the security descriptor. 63 | // --> To return a SD we need to hold onto everything we allocated. Yay. 64 | #[derive(Default)] 65 | struct OwnedSecurityDescriptor { 66 | pub sd: SECURITY_DESCRIPTOR, 67 | sacl: OwnedLocalAlloc<*mut ACL>, 68 | dacl: OwnedLocalAlloc<*mut ACL>, 69 | } 70 | 71 | // Creates a descriptor of form 72 | // D:(A;;GA;;;)S:(ML;;NWNRNX;;;ME) 73 | fn create_security_descriptor_for_process(pid: u32) -> Result { 74 | unsafe { 75 | let mut s: OwnedSecurityDescriptor = Default::default(); 76 | let psd = PSECURITY_DESCRIPTOR(&mut s.sd as *mut _ as _); 77 | InitializeSecurityDescriptor(psd, SECURITY_DESCRIPTOR_REVISION)?; 78 | 79 | // SACL 80 | { 81 | let user = { 82 | let process = 83 | Owned::new(OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, pid)?); 84 | get_sid_for_process(*process)? 85 | }; 86 | 87 | let ea = [EXPLICIT_ACCESS_W { 88 | grfAccessPermissions: GENERIC_ALL.0, 89 | grfAccessMode: SET_ACCESS, 90 | grfInheritance: NO_INHERITANCE, 91 | Trustee: TRUSTEE_W { 92 | pMultipleTrustee: null_mut(), 93 | MultipleTrusteeOperation: NO_MULTIPLE_TRUSTEE, 94 | TrusteeForm: TRUSTEE_IS_SID, 95 | TrusteeType: TRUSTEE_IS_USER, 96 | ptstrName: PWSTR(&user.Sid as *const _ as _), 97 | }, 98 | }]; 99 | 100 | SetEntriesInAclW(Some(&ea), None, &mut *s.dacl).ok()?; 101 | SetSecurityDescriptorDacl(psd, true, Some(*s.dacl), false)?; 102 | } 103 | 104 | // DACL 105 | { 106 | // windows-rs doesn't have a definition for this macro. 107 | const SECURITY_MAX_SID_SIZE: usize = 88; 108 | 109 | let mut sid_buffer = [0u8; SECURITY_MAX_SID_SIZE]; 110 | let mut sid_len = sid_buffer.len() as u32; 111 | let sid = PSID(&mut sid_buffer as *mut _ as _); 112 | CreateWellKnownSid(WinMediumLabelSid, None, sid, &mut sid_len)?; 113 | 114 | const SACL_BUFFER_PREFIX_LEN: usize = 115 | size_of::() + size_of::(); 116 | let sacl_len = SACL_BUFFER_PREFIX_LEN as u32 + sid_len; 117 | s.sacl.0 = LocalAlloc(LMEM_FIXED, sacl_len as usize)?.0 as _; 118 | 119 | InitializeAcl(*s.sacl, sacl_len, ACL_REVISION)?; 120 | AddMandatoryAce( 121 | *s.sacl, 122 | ACL_REVISION, 123 | ACE_FLAGS(0), 124 | SYSTEM_MANDATORY_LABEL_NO_READ_UP 125 | | SYSTEM_MANDATORY_LABEL_NO_WRITE_UP 126 | | SYSTEM_MANDATORY_LABEL_NO_EXECUTE_UP, 127 | sid, 128 | )?; 129 | 130 | SetSecurityDescriptorSacl(psd, true, Some(*s.sacl), false)?; 131 | } 132 | 133 | Ok(s) 134 | } 135 | } 136 | 137 | pub fn rpc_server_setup(endpoint: &CStr, expected_client_pid: u32) -> Result<()> { 138 | let owned_sd = create_security_descriptor_for_process(expected_client_pid)?; 139 | 140 | unsafe { 141 | RpcServerUseProtseqEpA( 142 | /* Protseq */ s!("ncalrpc"), 143 | /* MaxCalls */ RPC_C_LISTEN_MAX_CALLS_DEFAULT, 144 | /* Endpoint */ PCSTR(endpoint.as_ptr() as _), 145 | /* SecurityDescriptor */ Some(&owned_sd.sd as *const _ as _), 146 | ) 147 | .ok()?; 148 | RpcServerRegisterIf3( 149 | /* IfSpec */ server_sudo_rpc_ServerIfHandle, 150 | /* MgrTypeUuid */ None, 151 | /* MgrEpv */ None, 152 | /* Flags */ RPC_IF_ALLOW_LOCAL_ONLY | RPC_IF_ALLOW_SECURE_ONLY, 153 | /* MaxCalls */ RPC_C_LISTEN_MAX_CALLS_DEFAULT, 154 | /* MaxRpcSize */ u32::MAX, 155 | /* IfCallback */ Some(rpc_server_callback), 156 | /* SecurityDescriptor */ Some(&owned_sd.sd as *const _ as _), 157 | ) 158 | .ok()?; 159 | 160 | EXPECTED_CLIENT_PID = expected_client_pid; 161 | 162 | let res = RpcServerListen( 163 | /* MinimumCallThreads */ 1, 164 | /* MaxCalls */ RPC_C_LISTEN_MAX_CALLS_DEFAULT, 165 | /* DontWait */ 0, 166 | ); 167 | if res.is_err() { 168 | _ = RpcServerUnregisterIf(None, None, 0); 169 | } 170 | res.ok() 171 | } 172 | } 173 | 174 | // This is the RPC's sudo_rpc::Shutdown callback function. 175 | #[no_mangle] 176 | unsafe extern "C" fn server_Shutdown(_binding: *const c_void) { 177 | _ = TerminateProcess(GetCurrentProcess(), 0); 178 | } 179 | 180 | // This is the RPC's sudo_rpc::DoElevationRequest callback function. 181 | #[no_mangle] 182 | pub extern "C" fn server_DoElevationRequest( 183 | _binding: *const c_void, 184 | parent_handle: HANDLE, 185 | pipe_handles: *const [HANDLE; 3], // in, out, err 186 | file_handles: *const [HANDLE; 3], // in, out, err 187 | sudo_mode: u32, 188 | application: Utf8Str, 189 | args: Utf8Str, 190 | target_dir: Utf8Str, 191 | env_vars: Utf8Str, 192 | event_id: GUID, 193 | child: *mut HANDLE, 194 | ) -> HRESULT { 195 | // Only the first caller will get their request handled. Everyone else will 196 | // be forced to bail out. 197 | if RPC_SERVER_IN_USE.swap(true, Ordering::Relaxed) { 198 | // We're already in the middle of handling a request. 199 | return ERROR_BUSY.to_hresult(); 200 | } 201 | 202 | // Here, we've locked the mutex and we're the only ones handling a request. 203 | // 204 | // And, we've set the atom to true, so if someone _does_ connect to us after 205 | // this function releases the lock, then they'll also bail out. 206 | 207 | // Immediately unregister ourself. This will prevent a future caller from 208 | // getting to us (but won't cancel the current request we're already in the 209 | // middle of replying to). 210 | unsafe { 211 | _ = RpcMgmtStopServerListening(None); 212 | _ = RpcServerUnregisterIf(None, None, 0); 213 | } 214 | 215 | let result = wrap_elevate_request( 216 | parent_handle, 217 | pipe_handles, 218 | file_handles, 219 | sudo_mode, 220 | application, 221 | args, 222 | target_dir, 223 | env_vars, 224 | event_id, 225 | ) 226 | .and_then(|req| handle_elevation_request(&req)); 227 | 228 | match result { 229 | Ok(mut handle) => { 230 | unsafe { child.write(take(&mut handle)) }; 231 | HRESULT::default() 232 | } 233 | Err(err) => err.into(), 234 | } 235 | } 236 | 237 | #[allow(clippy::too_many_arguments)] 238 | fn wrap_elevate_request( 239 | parent_handle: HANDLE, 240 | pipe_handles: *const [HANDLE; 3], // in, out, err 241 | file_handles: *const [HANDLE; 3], // in, out, err 242 | sudo_mode: u32, 243 | application: Utf8Str, 244 | args: Utf8Str, 245 | target_dir: Utf8Str, 246 | env_vars: Utf8Str, 247 | event_id: GUID, 248 | ) -> Result { 249 | let parent_pid = unsafe { GetProcessId(parent_handle) }; 250 | let handles = unsafe { 251 | let pipes = &*pipe_handles; 252 | let files = &*file_handles; 253 | std::array::from_fn(|i| if pipes[i].0 != 0 { pipes[i] } else { files[i] }) 254 | }; 255 | 256 | Ok(ElevateRequest { 257 | parent_pid, 258 | handles, 259 | sudo_mode: sudo_mode.try_into()?, 260 | application: application.as_str()?.to_owned(), 261 | args: unpack_string_list_from_rpc(args)?, 262 | target_dir: target_dir.as_str()?.to_owned(), 263 | env_vars: env_vars.as_str()?.to_owned(), 264 | event_id, 265 | }) 266 | } 267 | 268 | #[cfg(test)] 269 | mod tests { 270 | use super::*; 271 | 272 | #[test] 273 | fn test_create_security_descriptor_for_process() { 274 | fn sd_to_string(sd: PSECURITY_DESCRIPTOR) -> Result { 275 | unsafe { 276 | let mut buffer = PSTR::null(); 277 | ConvertSecurityDescriptorToStringSecurityDescriptorA( 278 | sd, 279 | SDDL_REVISION, 280 | DACL_SECURITY_INFORMATION 281 | | LABEL_SECURITY_INFORMATION 282 | | OWNER_SECURITY_INFORMATION, 283 | &mut buffer, 284 | None, 285 | )?; 286 | Ok(buffer.to_string()?) 287 | } 288 | } 289 | 290 | let s = create_security_descriptor_for_process(unsafe { GetCurrentProcessId() }).unwrap(); 291 | let str = sd_to_string(PSECURITY_DESCRIPTOR(&s.sd as *const _ as _)).unwrap(); 292 | assert!(str.starts_with("D:(A;;GA;;;")); 293 | assert!(str.ends_with(")S:(ML;;NWNRNX;;;ME)")); 294 | } 295 | } 296 | -------------------------------------------------------------------------------- /sudo/src/tests/mod.rs: -------------------------------------------------------------------------------- 1 | #[cfg(test)] 2 | mod tests { 3 | use crate::helpers::*; 4 | use windows::Win32::Foundation::*; 5 | 6 | #[test] 7 | fn test_try_from_u32_for_sudo_mode() { 8 | assert_eq!(SudoMode::try_from(0), Ok(SudoMode::Disabled)); 9 | assert_eq!(SudoMode::try_from(1), Ok(SudoMode::ForceNewWindow)); 10 | assert_eq!(SudoMode::try_from(2), Ok(SudoMode::DisableInput)); 11 | assert_eq!(SudoMode::try_from(3), Ok(SudoMode::Normal)); 12 | assert_eq!(SudoMode::try_from(4), Err(ERROR_INVALID_PARAMETER.into())); 13 | } 14 | #[test] 15 | fn test_try_sudo_mode_to_u32() { 16 | assert_eq!(u32::from(SudoMode::Disabled), 0); 17 | assert_eq!(u32::from(SudoMode::ForceNewWindow), 1); 18 | assert_eq!(u32::from(SudoMode::DisableInput), 2); 19 | assert_eq!(u32::from(SudoMode::Normal), 3); 20 | } 21 | 22 | #[test] 23 | fn test_generate_rpc_endpoint_name() { 24 | assert_eq!( 25 | generate_rpc_endpoint_name(1234, 2345), 26 | r"sudo_elevate_1234_2345" 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /sudo/src/tracing.rs: -------------------------------------------------------------------------------- 1 | use sudo_events::SudoEvents; 2 | 3 | // tl:{6ffdd42d-46d9-5efe-68a1-3b18cb73a607} 4 | static SUDO_EVENTS: std::sync::OnceLock = std::sync::OnceLock::new(); 5 | 6 | const PDT_PRODUCT_AND_SERVICE_PERFORMANCE: u64 = 0x0000000001000000; 7 | // const PDT_PRODUCT_AND_SERVICE_USAGE: u64 = 0x0000000002000000; 8 | 9 | pub fn sudo_events() -> &'static SudoEvents { 10 | SUDO_EVENTS.get_or_init(SudoEvents::new) 11 | } 12 | 13 | use crate::messages::*; 14 | 15 | pub fn enable_tracing() { 16 | sudo_events(); 17 | } 18 | 19 | pub fn trace_log_message(message: &str) { 20 | sudo_events().message(None, message); 21 | } 22 | 23 | pub fn trace_command_not_found(exe_name: &str) { 24 | sudo_events().command_not_found(None, exe_name); 25 | } 26 | 27 | pub fn trace_cmd_builtin_found(exe_name: &str) { 28 | sudo_events().cmd_builtin_found(None, exe_name); 29 | } 30 | 31 | pub fn trace_run(req: &ElevateRequest, redirected_input: bool, redirected_output: bool) { 32 | sudo_events().run( 33 | None, 34 | &req.application, 35 | req.sudo_mode as u32, 36 | req.parent_pid, 37 | redirected_input, 38 | redirected_output, 39 | ); 40 | } 41 | 42 | pub fn trace_modes(requested_mode: u32, allowed_mode: u32, policy_mode: u32) { 43 | // We manually set the privacy tag to PDT_PRODUCT_AND_SERVICE_PERFORMANCE so 44 | // that callers don't need to know that 45 | sudo_events().modes( 46 | None, 47 | requested_mode, 48 | allowed_mode, 49 | policy_mode, 50 | PDT_PRODUCT_AND_SERVICE_PERFORMANCE, 51 | ); 52 | } 53 | -------------------------------------------------------------------------------- /sudo/sudo.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | true 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /sudo/sudo.rc: -------------------------------------------------------------------------------- 1 | // Resource file (.rc) template for sudo. 2 | // 3 | // Our string resources are all auto-generated from our resw file. They'll be 4 | // consumed from a generated .rc file, which will start with the content of this file. 5 | 6 | #include 7 | 8 | // Here, you'd usually want to 9 | // 10 | // #include "resource.h" 11 | // 12 | // To include your resource ID's. That doesn't work for us! 13 | // We want to use the winres crate to auto-generate FILEVERSION et. al. If we 14 | // want that to work, then we need to append the content of our generated file 15 | // to the content winres generates (using append_rc_content). 16 | // However, when we do it that way, the ultimate .rc file we end up using is one 17 | // that's generated in our OUT_DIR, and that means it can't find the relative 18 | // resource.h 19 | // 20 | // Instead, we'll use append_rc_content to _also_ include the header literally 21 | // in the output .rc file. 22 | 23 | // Make sure to declare our exe icon here 24 | IDI_APPICON ICON "..\\img\\ico\\sudo.ico" 25 | -------------------------------------------------------------------------------- /sudo_events/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sudo_events" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | win_etw_macros.workspace = true 8 | win_etw_provider.workspace = true 9 | -------------------------------------------------------------------------------- /sudo_events/build.rs: -------------------------------------------------------------------------------- 1 | use std::{io, path::Path}; 2 | 3 | // BODGY 4 | // 5 | // * As a part of the build process, we need to replace the fake GUID in our 6 | // tracing lib with the real one. 7 | // * This build script here will take the value out of the env var 8 | // MAGIC_TRACING_GUID, and replace the fake GUID in the events_template.rs 9 | // file with that one. 10 | // * We'll write that file out to %OUT_DIR%/mangled_events.rs, and then include 11 | // _that mangled file_ in our lib.rs file. 12 | fn main() -> io::Result<()> { 13 | let input = std::fs::read_to_string("src/events_template.rs")?; 14 | // Is the MAGIC_TRACING_GUID env var set? If it is... 15 | let output = match std::env::var("MAGIC_TRACING_GUID") { 16 | Ok(guid) => { 17 | println!("MAGIC_TRACING_GUID: {}", guid); 18 | 19 | // Replace the fake guid (ffffffff-ffff-ffff-ffff-ffffffffffff) with this one. 20 | 21 | input.replace("ffffffff-ffff-ffff-ffff-ffffffffffff", &guid) 22 | } 23 | Err(_) => input, 24 | }; 25 | let path = Path::new(&std::env::var("OUT_DIR").unwrap()).join("mangled_events.rs"); 26 | println!( 27 | "cargo:rerun-if-changed={}", 28 | path.as_path().to_str().unwrap() 29 | ); 30 | std::fs::write(path.as_path(), output) 31 | } 32 | -------------------------------------------------------------------------------- /sudo_events/src/events_template.rs: -------------------------------------------------------------------------------- 1 | 2 | use win_etw_macros::trace_logging_provider; 3 | // Note: Generate GUID using TlgGuid.exe tool 4 | #[trace_logging_provider( 5 | name = "Microsoft.Windows.Sudo", 6 | guid = "6ffdd42d-46d9-5efe-68a1-3b18cb73a607", 7 | provider_group_guid = "ffffffff-ffff-ffff-ffff-ffffffffffff" 8 | )] 9 | // tl:{6ffdd42d-46d9-5efe-68a1-3b18cb73a607} 10 | 11 | pub trait SudoEvents { 12 | fn command_not_found(exe_name: &str); 13 | 14 | fn cmd_builtin_found(exe_name: &str); 15 | 16 | fn message(message: &str); 17 | 18 | fn run( 19 | exe_name: &str, 20 | requested_mode: u32, 21 | parent_pid: u32, 22 | redirected_input: bool, 23 | redirected_output: bool, 24 | ); 25 | 26 | // TRACELOGGING EVENTS: 27 | // 28 | // These events need to add a PartA_PrivTags: u64 parameter to the end of 29 | // the event. That should be filled with PDT_ProductAndServicePerformance or 30 | // PDT_ProductAndServiceUsage. Our wrappers in tracing.rs should abstract 31 | // that away. 32 | // 33 | // Additionally, we manually set the keyword to MICROSOFT_KEYWORD_MEASURES. 34 | // However, we can't use that constant here, because the macro needs an 35 | // actual _literal_. So, we use the value 0x0000400000000000 directly. 36 | // MICROSOFT_KEYWORD_TELEMETRY is 0x0000200000000000, but that... doesn't work? 37 | 38 | // requested_mode: 39 | // * 0: Use the allowed mode from the registry / policy 40 | // * 1: Manually request forceNewWindow 41 | // * 2: Manually request disableInput 42 | // * 3: ??? We shouldn't get these. Requested mode is set by the CLI flags 43 | // allowed_mode: Straightforward. The mode in the registry 44 | // policy_mode: The mode set by the policy. If the policy isn't set, this should be 0xffffffff 45 | #[event(keyword = 0x0000400000000000)] 46 | fn modes(requested_mode: u32, allowed_mode: u32, policy_mode: u32, PartA_PrivTags: u64); 47 | } 48 | -------------------------------------------------------------------------------- /sudo_events/src/lib.rs: -------------------------------------------------------------------------------- 1 | include!(concat!(env!("OUT_DIR"), "/mangled_events.rs")); 2 | -------------------------------------------------------------------------------- /tools/gen-lang-codes.ps1: -------------------------------------------------------------------------------- 1 | # This is a list of what I think all the languages we need to support are. At 2 | # the very least, it's all the languages that the Terminal's context menu are 3 | # localized into. If we need more than that, go ahead and add more. This has to 4 | # be the most complete list - the script that actually generates the .rc file 5 | # will use whatever subest of languages are actually available. 6 | 7 | $languageCodes = @( 8 | "af-ZA", 9 | "am-ET", 10 | "ar-SA", 11 | "as-IN", 12 | "az-Latn-AZ", 13 | "bg-BG", 14 | "bn-IN", 15 | "bs-Latn-BA", 16 | "ca-ES", 17 | "ca-Es-VALENCIA", 18 | "cs-CZ", 19 | "cy-GB", 20 | "da-DK", 21 | "de-DE", 22 | "el-GR", 23 | "en-GB", 24 | "en-US", 25 | "es-ES", 26 | "es-MX", 27 | "et-EE", 28 | "eu-ES", 29 | "fa-IR", 30 | "fi-FI", 31 | "fil-PH", 32 | "fr-CA", 33 | "fr-FR", 34 | "ga-IE", 35 | "gd-gb", 36 | "gl-ES", 37 | "gu-IN", 38 | "he-IL", 39 | "hi-IN", 40 | "hr-HR", 41 | "hu-HU", 42 | "hy-AM", 43 | "id-ID", 44 | "is-IS", 45 | "it-IT", 46 | "ja-JP", 47 | "ka-GE", 48 | "kk-KZ", 49 | "km-KH", 50 | "kn-IN", 51 | "ko-KR", 52 | "kok-IN", 53 | "lb-LU", 54 | "lo-LA", 55 | "lt-LT", 56 | "lv-LV", 57 | "mi-NZ", 58 | "mk-MK", 59 | "ml-IN", 60 | "mr-IN", 61 | "ms-MY", 62 | "mt-MT", 63 | "nb-NO", 64 | "ne-NP", 65 | "nl-NL", 66 | "nn-NO", 67 | "or-IN", 68 | "pa-IN", 69 | "pl-PL", 70 | "pt-BR", 71 | "pt-PT", 72 | "qps-ploc", 73 | "qps-ploca", 74 | "qps-plocm", 75 | "quz-PE", 76 | "ro-RO", 77 | "ru-RU", 78 | "sk-SK", 79 | "sl-SI", 80 | "sq-AL", 81 | "sr-Cyrl-BA", 82 | "sr-Cyrl-RS", 83 | "sr-Latn-RS", 84 | "sv-SE", 85 | "ta-IN", 86 | "te-IN", 87 | "th-TH", 88 | "tr-TR", 89 | "tt-RU", 90 | "ug-CN", 91 | "uk-UA", 92 | "ur-PK", 93 | "uz-Latn-UZ", 94 | "vi-VN", 95 | "zh-CN", 96 | "zh-TW" 97 | ) 98 | 99 | function Get-Language-Sublanguage-Constants { 100 | param ( 101 | [int]$lcid 102 | ) 103 | 104 | $language = $lcid -band 0xFFFF 105 | $sublanguage = ($lcid -shr 16) -band 0x3F 106 | 107 | # Language Constants 108 | $languageConstant = "LANG_" + ([System.Globalization.CultureInfo]::GetCultureInfo($lcid).TwoLetterISOLanguageName).ToUpper() 109 | 110 | # Sublanguage Constants 111 | $sublanguageConstant = "SUBLANG_" + ([System.Globalization.CultureInfo]::GetCultureInfo($lcid).Name.Split('-')[1]).ToUpper() 112 | 113 | return $language, $sublanguage, $languageConstant, $sublanguageConstant, ([System.Globalization.CultureInfo]::GetCultureInfo($lcid).ThreeLetterISOLanguageName).ToUpper() 114 | } 115 | 116 | $languageHashTable = @{} 117 | 118 | foreach ($code in $languageCodes) { 119 | $cultureInfo = New-Object System.Globalization.CultureInfo $code 120 | $displayName = $cultureInfo.DisplayName 121 | $neutralCulture = $cultureInfo.Parent.Name 122 | $lcid = $cultureInfo.LCID 123 | $language, $sublanguage, $languageConstant, $sublanguageConstant, $threeLetter = Get-Language-Sublanguage-Constants -lcid $lcid 124 | 125 | # trim out "LANG_" and "SUBLANG_ 126 | $languageConstant = $languageConstant.Substring(5) 127 | $sublanguageConstant = $sublanguageConstant.Substring(8) 128 | 129 | $hashTableValue = @( 130 | # $cultureInfo.Name.ToUpper(), 131 | # "", 132 | $threeLetter, 133 | $language, 134 | $sublanguage, # $cultureInfo.Name.ToUpper() + '_' + $cultureInfo.Parent.Name.ToUpper(), 135 | $displayName 136 | ) 137 | 138 | $languageHashTable[$code] = $hashTableValue 139 | } 140 | # write list like: 141 | # 142 | # "eu-ES" = @("EUQ", "BASQUE", "DEFAULT", "Basque (Basque)"); 143 | # $languageHashTable | % { 144 | 145 | foreach ($code in $languageCodes) { 146 | $lang = $languageHashTable[$code] 147 | # Get language and sublanguage constants 148 | 149 | write-host " `"$($code)`" = @(`"$($lang[0])`", `"$($lang[1])`", `"$($lang[2])`", `"$($lang[3])`");" 150 | 151 | # if ($_.Value -ne $null ) { 152 | # write-host " `"$($_.Key)`" = @(`"$($_.Value[0])`", `"$($_.Value[1])`", `"$($_.Value[2])`", `"$($_.Value[3])`");" } 153 | } 154 | -------------------------------------------------------------------------------- /tools/sudo.tvpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | LocalLive 4 | sudo for windows 5 | 6 | tl:{6ffdd42d-46d9-5efe-68a1-3b18cb73a607} 7 | 8 | 9 | 10 | 6ffdd42d-46d9-5efe-68a1-3b18cb73a607 11 | 0 12 | 0 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /win32resources/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "win32resources" 3 | version = "0.1.0" 4 | edition = "2021" 5 | -------------------------------------------------------------------------------- /win32resources/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Provides APIs for accessing Win32 resources, mainly string resources. 2 | use std::borrow::Cow; 3 | use std::ffi::c_void; 4 | use std::ops::Deref; 5 | use std::ptr::null_mut; 6 | use std::slice::from_raw_parts; 7 | use std::sync::OnceLock; 8 | 9 | #[allow(clippy::upper_case_acronyms)] 10 | type HINSTANCE = *const c_void; 11 | 12 | extern "system" { 13 | fn LoadStringW(hInstance: HINSTANCE, uID: u32, lpBuffer: *mut u16, cchBufferMax: i32) -> i32; 14 | } 15 | 16 | extern "C" { 17 | static __ImageBase: [u8; 0]; 18 | } 19 | 20 | fn module_base() -> *const c_void { 21 | unsafe { (&__ImageBase) as *const [u8; 0] as *const c_void } 22 | } 23 | 24 | /* 25 | #[macro_export] 26 | macro_rules! def_image_base { 27 | ( 28 | $fn_name:ident 29 | ) => { 30 | fn $fn_name() -> &'static ModuleAddress { 31 | extern "C" { 32 | static _ImageBase: (); 33 | } 34 | (&_ImageBase) as *const () as *const core::ffi::c_void 35 | } 36 | } 37 | } 38 | */ 39 | 40 | pub struct StaticStringResource { 41 | id: u32, 42 | value: OnceLock>, 43 | fallback: &'static str, 44 | } 45 | 46 | impl StaticStringResource { 47 | pub const fn new(id: u32, fallback: &'static str) -> Self { 48 | Self { 49 | id, 50 | value: OnceLock::new(), 51 | fallback, 52 | } 53 | } 54 | 55 | pub fn get(&self) -> &str { 56 | self.value.get_or_init(|| { 57 | let image_base = module_base(); 58 | 59 | // If this returns 0, then the string was not found. 60 | let mut base: *const u16 = null_mut(); 61 | let len = unsafe { LoadStringW(image_base, self.id, &mut base as *mut _ as *mut _, 0) }; 62 | if len <= 0 { 63 | return Cow::Borrowed(self.fallback); 64 | } 65 | 66 | Cow::Owned(String::from_utf16_lossy(unsafe { 67 | from_raw_parts(base, len as usize) 68 | })) 69 | }) 70 | } 71 | } 72 | 73 | impl Deref for StaticStringResource { 74 | type Target = str; 75 | 76 | fn deref(&self) -> &Self::Target { 77 | self.get() 78 | } 79 | } 80 | --------------------------------------------------------------------------------