├── .azuredevops
└── dependabot.yml
├── .config
└── dotnet-tools.json
├── .devcontainer
├── Dockerfile
└── devcontainer.json
├── .editorconfig
├── .gitattributes
├── .github
├── .editorconfig
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
├── actions
│ └── publish-artifacts
│ │ └── action.yaml
├── renovate.json
└── workflows
│ ├── docs.yml
│ ├── docs_validate.yml
│ ├── libtemplate-update.yml
│ └── release.yml
├── .gitignore
├── .prettierrc.yaml
├── .vscode
├── extensions.json
├── launch.json
├── settings.json
└── tasks.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── COPYRIGHT
├── Directory.Build.props
├── Directory.Build.rsp
├── Directory.Build.targets
├── Directory.Packages.Analyzers.props
├── Directory.Packages.props
├── LICENSE
├── Microsoft.Windows.CsWin32.sln
├── NOTICE.txt
├── README.md
├── SECURITY.md
├── SUPPORT.md
├── azure-pipelines.yml
├── azure-pipelines
├── Archive-SourceCode.ps1
├── BuildStageVariables.yml
├── Get-InsertionPRId.ps1
├── GlobalVariables.yml
├── Install-NuGetPackage.ps1
├── Merge-CodeCoverage.ps1
├── NuGetSbom.targets
├── OptProf.yml
├── OptProf_part2.yml
├── PoliCheckExclusions.xml
├── PostPRMessage.ps1
├── TSAOptions.json
├── WIFtoPATauth.yml
├── apiscan.yml
├── archive-sourcecode.yml
├── build.yml
├── dotnet.yml
├── falsepositives.gdnsuppress
├── install-dependencies.yml
├── integration-test.yml
├── libtemplate-update.yml
├── microbuild.after.yml
├── microbuild.before.yml
├── no_authenticode.txt
├── no_strongname.txt
├── official.yml
├── prepare-insertion-stages.yml
├── publish-codecoverage.yml
├── publish-symbols.yml
├── publish_artifacts.ps1
├── release-deployment-prep.yml
├── release.yml
├── schedule-only-steps.yml
├── unofficial.yml
├── vs-insertion.yml
└── vs-validation.yml
├── azurepipelines-coverage.yml
├── docfx
├── .gitignore
├── docfx.json
├── docs
│ ├── 3rdPartyMetadata.md
│ ├── ArchSpecificAPIs.md
│ ├── features.md
│ ├── getting-started.md
│ └── toc.yml
├── images
│ ├── ConfigurationManager_x64.png
│ ├── StandardToolbarPlatformSwitcher.png
│ └── demo.gif
├── index.md
└── toc.yml
├── global.json
├── init.cmd
├── init.ps1
├── integration-tests
├── Directory.Build.props
├── Directory.Build.targets
├── nonsdk
│ ├── App.config
│ ├── NativeMethods.json
│ ├── NativeMethods.txt
│ ├── Program.cs
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ └── nonsdk.csproj
├── nuget.config
└── sdk
│ ├── NativeMethods.json
│ ├── NativeMethods.txt
│ ├── Program.cs
│ └── sdk.csproj
├── nuget.config
├── settings.VisualStudio.json
├── src
├── .editorconfig
├── AssemblyInfo.cs
├── AssemblyInfo.vb
├── Directory.Build.props
├── Directory.Build.targets
├── Microsoft.Windows.CsWin32
│ ├── AnalyzerReleases.Shipped.md
│ ├── AnalyzerReleases.Unshipped.md
│ ├── ArrayTypeHandleInfo.cs
│ ├── BannedSymbols.txt
│ ├── BindingRedirects.cs
│ ├── CustomAttributeTypeProvider.cs
│ ├── Docs.cs
│ ├── FastSyntaxFactory.cs
│ ├── GenerationFailedException.cs
│ ├── Generator.ApiDocs.cs
│ ├── Generator.Com.cs
│ ├── Generator.Constant.cs
│ ├── Generator.Delegate.cs
│ ├── Generator.Enum.cs
│ ├── Generator.Extern.cs
│ ├── Generator.Features.cs
│ ├── Generator.FriendlyOverloads.cs
│ ├── Generator.GeneratedCode.cs
│ ├── Generator.Handle.cs
│ ├── Generator.InlineArrays.cs
│ ├── Generator.Invariants.cs
│ ├── Generator.MetadataHelpers.cs
│ ├── Generator.Struct.cs
│ ├── Generator.Templates.cs
│ ├── Generator.TypeDef.cs
│ ├── Generator.WhitespaceRewriter.cs
│ ├── Generator.cs
│ ├── GeneratorExtensions.cs
│ ├── GeneratorOptions.cs
│ ├── GlobalUsings.cs
│ ├── HandleTypeHandleInfo.cs
│ ├── IGenerator.cs
│ ├── ITypeHandleContainer.cs
│ ├── MetadataCache.cs
│ ├── MetadataFile.cs
│ ├── MetadataIndex.cs
│ ├── MetadataQualifiedTokens.cs
│ ├── MetadataUtilities.cs
│ ├── Microsoft.Windows.CsWin32.csproj
│ ├── Microsoft.Windows.CsWin32.nuspec
│ ├── Microsoft.Windows.CsWin32.targets
│ ├── ModuleInitializerAttribute.cs
│ ├── NamespaceMetadata.cs
│ ├── PlatformIncompatibleException.cs
│ ├── PointerTypeHandleInfo.cs
│ ├── PrimitiveTypeHandleInfo.cs
│ ├── README.md
│ ├── Rental.cs
│ ├── SignatureHandleProvider.cs
│ ├── SimpleSyntaxFactory.cs
│ ├── SourceGenerator.cs
│ ├── SuperGenerator.cs
│ ├── TypeHandleInfo.cs
│ ├── TypeSyntaxAndMarshaling.cs
│ ├── TypeSyntaxSettings.cs
│ ├── build
│ │ ├── Microsoft.Windows.CsWin32.props
│ │ ├── net20
│ │ │ └── Microsoft.Windows.CsWin32.props
│ │ └── netstandard1.0
│ │ │ └── Microsoft.Windows.CsWin32.props
│ ├── readme.txt
│ ├── settings.schema.json
│ ├── templates
│ │ ├── .editorconfig
│ │ ├── BOOL.cs
│ │ ├── BOOLEAN.cs
│ │ ├── BSTR.cs
│ │ ├── ComHelpers.cs
│ │ ├── DECIMAL.cs
│ │ ├── HRESULT.cs
│ │ ├── IUnknownHelperMethods.cs
│ │ ├── IVTable.cs
│ │ ├── IVTable`2.cs
│ │ ├── NTSTATUS.cs
│ │ ├── OverloadResolutionPriorityAttribute.cs
│ │ ├── PCSTR.cs
│ │ ├── PCWSTR.cs
│ │ ├── PCZZSTR.cs
│ │ ├── PCZZWSTR.cs
│ │ ├── PInvokeClassHelperMethods.cs
│ │ ├── PInvokeClassMacros.cs
│ │ ├── PSTR.cs
│ │ ├── PWSTR.cs
│ │ ├── PZZSTR.cs
│ │ ├── PZZWSTR.cs
│ │ ├── RECT.cs
│ │ ├── SIZE.cs
│ │ ├── SYSTEMTIME.cs
│ │ ├── VARIANT_BOOL.cs
│ │ ├── VariableLengthInlineArray`1.cs
│ │ ├── VariableLengthInlineArray`2.cs
│ │ ├── WinRTCustomMarshaler.cs
│ │ ├── marshaling
│ │ │ └── CoCreateInstance.cs
│ │ └── no_marshaling
│ │ │ └── CoCreateInstance.cs
│ ├── tools
│ │ ├── install.ps1
│ │ └── uninstall.ps1
│ └── version.json
├── OptProf.targets
└── VSInsertionMetadata
│ ├── Library.VSInsertionMetadata.proj
│ ├── ProfilingInputs.props
│ └── VSInsertionMetadata.targets
├── stylecop.json
├── test
├── .editorconfig
├── CsWin32User.props
├── Directory.Build.props
├── Directory.Build.targets
├── GenerationSandbox.Tests
│ ├── BasicTests.cs
│ ├── BitFieldTests.cs
│ ├── BoolTests.cs
│ ├── BooleanTests.cs
│ ├── ComRuntimeTests.cs
│ ├── FILE_CREATE_FLAGS.cs
│ ├── FlexibleArrayTests.cs
│ ├── GeneratedForm.cs
│ ├── GenerationSandbox.Tests.csproj
│ ├── MacroTests.cs
│ ├── NativeMethods.json
│ ├── NativeMethods.txt
│ ├── StringTests.cs
│ ├── SystemDrawingStructTests.cs
│ ├── TestUtils.cs
│ ├── VARIANT_BOOLTests.cs
│ └── xunit.runner.json
├── GenerationSandbox.Unmarshalled.Tests
│ ├── COMTests.cs
│ ├── ComHelpers.cs
│ ├── GeneratedForm.cs
│ ├── GenerationSandbox.Unmarshalled.Tests.csproj
│ ├── NativeMethods.json
│ └── NativeMethods.txt
├── GenerationSandbox.props
├── Microsoft.Windows.CsWin32.Tests
│ ├── COMTests.cs
│ ├── CSharpSourceGeneratorVerifier.cs
│ ├── ConstantsTests.cs
│ ├── DelegateTests.cs
│ ├── EnumTests.cs
│ ├── ExternMethodTests.cs
│ ├── ExternalMetadata
│ │ ├── NOTICE.md
│ │ └── ServiceFabric.winmd
│ ├── FriendlyOverloadTests.cs
│ ├── FullGenerationTests.cs
│ ├── GeneratorConfiguration.cs
│ ├── GeneratorOptionsTests.cs
│ ├── GeneratorTestBase.cs
│ ├── GeneratorTests.cs
│ ├── GlobalUsings.cs
│ ├── HandleTests.cs
│ ├── InlineArrayTests.cs
│ ├── MacrosTests.cs
│ ├── Microsoft.Windows.CsWin32.Tests.csproj
│ ├── MultiMetadataTests.cs
│ ├── MyReferenceAssemblies.cs
│ ├── NumberedLineWriter.cs
│ ├── SourceGeneratorTests.cs
│ ├── StructTests.cs
│ ├── TestUtils.cs
│ └── xunit.runner.json
├── SpellChecker
│ ├── NativeMethods.json
│ ├── NativeMethods.txt
│ ├── Program.cs
│ └── SpellChecker.csproj
└── WinRTInteropTest
│ ├── CompositionHost.cs
│ ├── NativeMethods.txt
│ ├── Program.cs
│ └── WinRTInteropTest.csproj
├── tools
├── Check-DotNetRuntime.ps1
├── Check-DotNetSdk.ps1
├── Convert-PDB.ps1
├── Get-ArtifactsStagingDirectory.ps1
├── Get-CodeCovTool.ps1
├── Get-LibTemplateBasis.ps1
├── Get-NuGetTool.ps1
├── Get-ProcDump.ps1
├── Get-SymbolFiles.ps1
├── Get-TempToolsPath.ps1
├── Install-DotNetSdk.ps1
├── Install-NuGetCredProvider.ps1
├── MergeFrom-Template.ps1
├── Prepare-Legacy-Symbols.ps1
├── Set-EnvVars.ps1
├── artifacts
│ ├── APIScanInputs.ps1
│ ├── LocBin.ps1
│ ├── VSInsertion.ps1
│ ├── Variables.ps1
│ ├── _all.ps1
│ ├── _stage_all.ps1
│ ├── build_logs.ps1
│ ├── coverageResults.ps1
│ ├── deployables.ps1
│ ├── projectAssetsJson.ps1
│ ├── symbols.ps1
│ ├── testResults.ps1
│ └── test_symbols.ps1
├── dotnet-test-cloud.ps1
├── publish-CodeCov.ps1
├── test.runsettings
└── variables
│ ├── BusinessGroupName.ps1
│ ├── DotNetSdkVersion.ps1
│ ├── InsertJsonValues.ps1
│ ├── InsertPropsValues.ps1
│ ├── InsertTargetBranch.ps1
│ ├── InsertVersionsValues.ps1
│ ├── IsSigned.ps1
│ ├── LocLanguages.ps1
│ ├── ProfilingInputsDropName.ps1
│ ├── SymbolsFeatureName.ps1
│ ├── VstsDropNames.ps1
│ ├── _all.ps1
│ └── _define.ps1
└── version.json
/.azuredevops/dependabot.yml:
--------------------------------------------------------------------------------
1 | # Please see the documentation for all configuration options:
2 | # https://eng.ms/docs/products/dependabot/configuration/version_updates
3 |
4 | version: 2
5 | updates:
6 | - package-ecosystem: nuget
7 | directory: /
8 | schedule:
9 | interval: monthly
10 |
--------------------------------------------------------------------------------
/.config/dotnet-tools.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": 1,
3 | "isRoot": true,
4 | "tools": {
5 | "powershell": {
6 | "version": "7.5.0",
7 | "commands": [
8 | "pwsh"
9 | ],
10 | "rollForward": false
11 | },
12 | "dotnet-coverage": {
13 | "version": "17.14.2",
14 | "commands": [
15 | "dotnet-coverage"
16 | ],
17 | "rollForward": false
18 | },
19 | "nbgv": {
20 | "version": "3.7.115",
21 | "commands": [
22 | "nbgv"
23 | ],
24 | "rollForward": false
25 | },
26 | "docfx": {
27 | "version": "2.78.3",
28 | "commands": [
29 | "docfx"
30 | ],
31 | "rollForward": false
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/.devcontainer/Dockerfile:
--------------------------------------------------------------------------------
1 | # Refer to https://hub.docker.com/_/microsoft-dotnet-sdk for available versions
2 | FROM mcr.microsoft.com/dotnet/sdk:9.0.200-noble
3 |
4 | # Installing mono makes `dotnet test` work without errors even for net472.
5 | # But installing it takes a long time, so it's excluded by default.
6 | #RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF
7 | #RUN echo "deb https://download.mono-project.com/repo/ubuntu stable-bionic main" | tee /etc/apt/sources.list.d/mono-official-stable.list
8 | #RUN apt-get update
9 | #RUN DEBIAN_FRONTEND=noninteractive apt-get install -y mono-devel
10 |
11 | # Clear the NUGET_XMLDOC_MODE env var so xml api doc files get unpacked, allowing a rich experience in Intellisense.
12 | # See https://github.com/dotnet/dotnet-docker/issues/2790 for a discussion on this, where the prioritized use case
13 | # was *not* devcontainers, sadly.
14 | ENV NUGET_XMLDOC_MODE=
15 |
--------------------------------------------------------------------------------
/.devcontainer/devcontainer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Dev space",
3 | "dockerFile": "Dockerfile",
4 | "customizations": {
5 | "vscode": {
6 | "settings": {
7 | "terminal.integrated.shell.linux": "/usr/bin/pwsh"
8 | },
9 | "extensions": [
10 | "ms-azure-devops.azure-pipelines",
11 | "ms-dotnettools.csharp",
12 | "k--kato.docomment",
13 | "editorconfig.editorconfig",
14 | "esbenp.prettier-vscode",
15 | "pflannery.vscode-versionlens",
16 | "davidanson.vscode-markdownlint",
17 | "dotjoshjohnson.xml",
18 | "ms-vscode-remote.remote-containers",
19 | "ms-azuretools.vscode-docker",
20 | "tintoy.msbuild-project-tools"
21 | ]
22 | }
23 | },
24 | "postCreateCommand": "./init.ps1 -InstallLocality machine"
25 | }
26 |
--------------------------------------------------------------------------------
/.github/.editorconfig:
--------------------------------------------------------------------------------
1 | [renovate.json*]
2 | indent_style = tab
3 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Actual behavior
11 |
12 | [A clear and concise description of what the bug is.]
13 |
14 | ## Expected behavior
15 |
16 | A clear and concise description of what you expected to happen.
17 |
18 | ## Repro steps
19 |
20 | 1. `NativeMethods.txt` content:
21 | ```
22 |
23 | ```
24 |
25 | 2. `NativeMethods.json` content (if present):
26 | ```json
27 | ```
28 |
29 | 3. Any of your own code that should be shared?
30 |
31 | ### Context
32 |
33 | - CsWin32 version: [e.g. `0.4.422-beta`]
34 | - Win32Metadata version (if explicitly set by project):
35 | - Target Framework: [e.g. `netstandard2.0`]
36 | - `LangVersion` (if explicitly set by project): [e.g. `9`]
37 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: enhancement
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/actions/publish-artifacts/action.yaml:
--------------------------------------------------------------------------------
1 | name: Publish artifacts
2 | description: Publish artifacts
3 |
4 | runs:
5 | using: composite
6 | steps:
7 | - name: 📥 Collect artifacts
8 | run: tools/artifacts/_stage_all.ps1
9 | shell: pwsh
10 | if: always()
11 |
12 | # TODO: replace this hard-coded list with a loop that utilizes the NPM package at
13 | # https://github.com/actions/toolkit/tree/main/packages/artifact (or similar) to push the artifacts.
14 |
15 | - name: 📢 Upload project.assets.json files
16 | if: always()
17 | uses: actions/upload-artifact@v4
18 | with:
19 | name: projectAssetsJson-${{ runner.os }}
20 | path: ${{ runner.temp }}/_artifacts/projectAssetsJson
21 | continue-on-error: true
22 | - name: 📢 Upload variables
23 | uses: actions/upload-artifact@v4
24 | with:
25 | name: variables-${{ runner.os }}
26 | path: ${{ runner.temp }}/_artifacts/Variables
27 | continue-on-error: true
28 | - name: 📢 Upload build_logs
29 | if: always()
30 | uses: actions/upload-artifact@v4
31 | with:
32 | name: build_logs-${{ runner.os }}
33 | path: ${{ runner.temp }}/_artifacts/build_logs
34 | continue-on-error: true
35 | - name: 📢 Upload testResults
36 | if: always()
37 | uses: actions/upload-artifact@v4
38 | with:
39 | name: testResults-${{ runner.os }}
40 | path: ${{ runner.temp }}/_artifacts/testResults
41 | continue-on-error: true
42 | - name: 📢 Upload coverageResults
43 | if: always()
44 | uses: actions/upload-artifact@v4
45 | with:
46 | name: coverageResults-${{ runner.os }}
47 | path: ${{ runner.temp }}/_artifacts/coverageResults
48 | continue-on-error: true
49 | - name: 📢 Upload symbols
50 | uses: actions/upload-artifact@v4
51 | with:
52 | name: symbols-${{ runner.os }}
53 | path: ${{ runner.temp }}/_artifacts/symbols
54 | continue-on-error: true
55 | - name: 📢 Upload deployables
56 | uses: actions/upload-artifact@v4
57 | with:
58 | name: deployables-${{ runner.os }}
59 | path: ${{ runner.temp }}/_artifacts/deployables
60 | if: always()
61 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "github>microsoft/vs-renovate-presets:microbuild",
5 | "github>microsoft/vs-renovate-presets:vs_main_dependencies"
6 | ],
7 | "packageRules": [
8 | {
9 | "matchPackageNames": ["MessagePack", "MessagePackAnalyzer"],
10 | "enabled": false
11 | },
12 | {
13 | "matchFileNames": ["Directory.Packages.Analyzers.props"],
14 | "enabled": false
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: 📚 Docs
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
9 | permissions:
10 | actions: read
11 | pages: write
12 | id-token: write
13 | contents: read
14 |
15 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
16 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
17 | concurrency:
18 | group: pages
19 | cancel-in-progress: false
20 |
21 | jobs:
22 | publish-docs:
23 | environment:
24 | name: github-pages
25 | url: ${{ steps.deployment.outputs.page_url }}
26 | runs-on: ubuntu-latest
27 | steps:
28 | - uses: actions/checkout@v4
29 | with:
30 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
31 | - name: ⚙ Install prerequisites
32 | run: ./init.ps1 -UpgradePrerequisites
33 |
34 | - run: dotnet docfx docfx/docfx.json
35 | name: 📚 Generate documentation
36 |
37 | - name: Upload artifact
38 | uses: actions/upload-pages-artifact@v3
39 | with:
40 | path: docfx/_site
41 |
42 | - name: Deploy to GitHub Pages
43 | id: deployment
44 | uses: actions/deploy-pages@v4
45 |
--------------------------------------------------------------------------------
/.github/workflows/docs_validate.yml:
--------------------------------------------------------------------------------
1 | name: 📃 Docfx Validate
2 |
3 | on:
4 | pull_request:
5 | workflow_dispatch:
6 | push:
7 | branches:
8 | - main
9 | - microbuild
10 |
11 | jobs:
12 | build:
13 | name: 📚 Doc validation
14 | runs-on: ubuntu-24.04
15 | steps:
16 | - uses: actions/checkout@v4
17 | with:
18 | fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
19 | - name: 🔗 Markup Link Checker (mlc)
20 | uses: becheran/mlc@v0.21.0
21 | with:
22 | args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx -i https://aka.ms/onboardsupport,https://aka.ms/spot,https://msrc.microsoft.com/*,https://www.microsoft.com/msrc*,https://microsoft.com/msrc*
23 | - name: ⚙ Install prerequisites
24 | run: |
25 | ./init.ps1 -UpgradePrerequisites
26 | dotnet --info
27 | shell: pwsh
28 | - name: 📚 Verify docfx build
29 | run: dotnet docfx docfx/docfx.json --warningsAsErrors --disableGitFeatures
30 | if: runner.os == 'Linux'
31 |
--------------------------------------------------------------------------------
/.prettierrc.yaml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CsWin32/10ff614acb54f6d5a5dbb77c59bd8786e5c99097/.prettierrc.yaml
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4 | // List of extensions which should be recommended for users of this workspace.
5 | "recommendations": [
6 | "ms-azure-devops.azure-pipelines",
7 | "ms-dotnettools.csharp",
8 | "k--kato.docomment",
9 | "editorconfig.editorconfig",
10 | "esbenp.prettier-vscode",
11 | "pflannery.vscode-versionlens",
12 | "davidanson.vscode-markdownlint",
13 | "dotjoshjohnson.xml",
14 | "ms-vscode-remote.remote-containers",
15 | "ms-azuretools.vscode-docker",
16 | "tintoy.msbuild-project-tools"
17 | ],
18 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace.
19 | "unwantedRecommendations": []
20 | }
21 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to find out which attributes exist for C# debugging
3 | // Use hover for the description of the existing attributes
4 | // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
5 | "version": "0.2.0",
6 | "configurations": [
7 | {
8 | "name": ".NET Core Attach",
9 | "type": "coreclr",
10 | "request": "attach",
11 | "processId": "${command:pickProcess}"
12 | }
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "files.trimTrailingWhitespace": true,
3 | "files.insertFinalNewline": true,
4 | "files.trimFinalNewlines": true,
5 | "azure-pipelines.1ESPipelineTemplatesSchemaFile": true,
6 | "omnisharp.enableEditorConfigSupport": true,
7 | "omnisharp.enableRoslynAnalyzers": true,
8 | "dotnet.completion.showCompletionItemsFromUnimportedNamespaces": true,
9 | "editor.formatOnSave": true,
10 | "[xml]": {
11 | "editor.wordWrap": "off"
12 | },
13 | // Treat these files as Azure Pipelines files
14 | "files.associations": {
15 | "**/azure-pipelines/**/*.yml": "azure-pipelines",
16 | "azure-pipelines.yml": "azure-pipelines"
17 | },
18 | // Use Prettier as the default formatter for Azure Pipelines files.
19 | // Needs to be explicitly configured: https://github.com/Microsoft/azure-pipelines-vscode#document-formatting
20 | "[azure-pipelines]": {
21 | "editor.defaultFormatter": "esbenp.prettier-vscode",
22 | "editor.formatOnSave": false // enable this when they conform
23 | },
24 | }
25 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "2.0.0",
3 | "tasks": [
4 | {
5 | "label": "build",
6 | "command": "dotnet",
7 | "type": "process",
8 | "args": [
9 | "build",
10 | "${workspaceFolder}",
11 | "/property:GenerateFullPaths=true",
12 | "/consoleloggerparameters:NoSummary"
13 | ],
14 | "problemMatcher": "$msCompile"
15 | }
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/COPYRIGHT:
--------------------------------------------------------------------------------
1 | Copyright (c) Microsoft Corporation. All rights reserved.
2 | Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
--------------------------------------------------------------------------------
/Directory.Build.rsp:
--------------------------------------------------------------------------------
1 | #------------------------------------------------------------------------------
2 | # This file contains command-line options that MSBuild will process as part of
3 | # every build, unless the "/noautoresponse" switch is specified.
4 | #
5 | # MSBuild processes the options in this file first, before processing the
6 | # options on the command line. As a result, options on the command line can
7 | # override the options in this file. However, depending on the options being
8 | # set, the overriding can also result in conflicts.
9 | #
10 | # NOTE: The "/noautoresponse" switch cannot be specified in this file, nor in
11 | # any response file that is referenced by this file.
12 | #------------------------------------------------------------------------------
13 | /nr:false
14 | /m
15 | /verbosity:minimal
16 | /clp:Summary;ForceNoAlign
17 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 13
5 | 16.9
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Directory.Packages.Analyzers.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | 3.11.0
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Microsoft Corporation
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 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # C#/Win32 P/Invoke Source Generator
2 |
3 | ***A source generator to add a user-defined set of Win32 P/Invoke methods and supporting types to a C# project.***
4 |
5 | [](https://www.nuget.org/packages/Microsoft.Windows.CsWin32)
6 | [](https://dev.azure.com/azure-public/winsdk/_packaging?_a=package&feed=CI%40Local&package=Microsoft.Windows.CsWin32&protocolType=NuGet)
7 |
8 | [](https://dev.azure.com/azure-public/winsdk/_build/latest?definitionId=47&branchName=main)
9 |
10 | ## Features
11 |
12 | * Rapidly add P/Invoke methods and supporting types to your C# project.
13 | * No bulky assemblies to ship alongside your application.
14 | * `SafeHandle`-types automatically generated.
15 | * Generates xml documentation based on and links back to docs.microsoft.com
16 |
17 | 
18 |
19 | ## Usage
20 |
21 | [Check out our product documentation](https://microsoft.github.io/CsWin32/docs/getting-started.html).
22 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # Support
2 |
3 | ## How to file issues and get help
4 |
5 | This project uses GitHub Issues to track bugs and feature requests. Please search the existing
6 | issues before filing new issues to avoid duplicates. For new issues, file your bug or
7 | feature request as a new Issue.
8 |
9 | For help and questions about using this project, please file a GitHub issue.
10 |
11 | ## Microsoft Support Policy
12 |
13 | Support for this C# projection generator is limited to the resources listed above.
14 |
--------------------------------------------------------------------------------
/azure-pipelines.yml:
--------------------------------------------------------------------------------
1 | trigger:
2 | batch: true
3 | branches:
4 | include:
5 | - main
6 | - 'v*.*'
7 | - 'validate/*'
8 | paths:
9 | exclude:
10 | - doc/
11 | - '*.md'
12 | - .vscode/
13 | - .github/
14 | - azure-pipelines/release.yml
15 |
16 | parameters:
17 | - name: EnableMacOSBuild
18 | displayName: Build on macOS
19 | type: boolean
20 | default: false # macOS is often bogged down in Azure Pipelines
21 | - name: RunTests
22 | displayName: Run tests
23 | type: boolean
24 | default: true
25 |
26 | variables:
27 | - template: /azure-pipelines/BuildStageVariables.yml@self
28 |
29 | jobs:
30 | - template: azure-pipelines/build.yml
31 | parameters:
32 | Is1ESPT: false
33 | EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }}
34 | RunTests: ${{ parameters.RunTests }}
35 |
--------------------------------------------------------------------------------
/azure-pipelines/BuildStageVariables.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
3 | BuildConfiguration: Release
4 | NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages/
5 | # codecov_token: 4dc9e7e2-6b01-4932-a180-847b52b43d35 # Get a new one from https://codecov.io/
6 |
--------------------------------------------------------------------------------
/azure-pipelines/Get-InsertionPRId.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Look up the pull request URL of the insertion PR.
4 | #>
5 | $stagingFolder = $env:BUILD_STAGINGDIRECTORY
6 | if (!$stagingFolder) {
7 | $stagingFolder = $env:SYSTEM_DEFAULTWORKINGDIRECTORY
8 | if (!$stagingFolder) {
9 | Write-Error "This script must be run in an Azure Pipeline."
10 | exit 1
11 | }
12 | }
13 | $markdownFolder = Join-Path $stagingFolder (Join-Path 'MicroBuild' 'Output')
14 | $markdownFile = Join-Path $markdownFolder 'PullRequestUrl.md'
15 | if (!(Test-Path $markdownFile)) {
16 | Write-Error "This script should be run after the MicroBuildInsertVsPayload task."
17 | exit 2
18 | }
19 |
20 | $insertionPRUrl = Get-Content $markdownFile
21 | if (!($insertionPRUrl -match 'https:.+?/pullrequest/(\d+)')) {
22 | Write-Error "Failed to parse pull request URL: $insertionPRUrl"
23 | exit 3
24 | }
25 |
26 | $Matches[1]
27 |
--------------------------------------------------------------------------------
/azure-pipelines/GlobalVariables.yml:
--------------------------------------------------------------------------------
1 | variables:
2 | # These variables are required for MicroBuild tasks
3 | TeamName: VS IDE
4 | TeamEmail: vsidemicrobuild@microsoft.com
5 | # These variables influence insertion pipelines
6 | ContainsVsix: false # This should be true when the repo builds a VSIX that should be inserted to VS.
7 |
--------------------------------------------------------------------------------
/azure-pipelines/Install-NuGetPackage.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Installs a NuGet package.
4 | .PARAMETER PackageID
5 | The Package ID to install.
6 | .PARAMETER Version
7 | The version of the package to install. If unspecified, the latest stable release is installed.
8 | .PARAMETER Source
9 | The package source feed to find the package to install from.
10 | .PARAMETER PackagesDir
11 | The directory to install the package to. By default, it uses the Packages folder at the root of the repo.
12 | .PARAMETER ConfigFile
13 | The nuget.config file to use. By default, it uses :/nuget.config.
14 | .OUTPUTS
15 | System.String. The path to the installed package.
16 | #>
17 | [CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact='Low')]
18 | Param(
19 | [Parameter(Position=1,Mandatory=$true)]
20 | [string]$PackageId,
21 | [Parameter()]
22 | [string]$Version,
23 | [Parameter()]
24 | [string]$Source,
25 | [Parameter()]
26 | [switch]$Prerelease,
27 | [Parameter()]
28 | [string]$PackagesDir="$PSScriptRoot\..\packages",
29 | [Parameter()]
30 | [string]$ConfigFile="$PSScriptRoot\..\nuget.config",
31 | [Parameter()]
32 | [ValidateSet('Quiet','Normal','Detailed')]
33 | [string]$Verbosity='normal'
34 | )
35 |
36 | $nugetPath = & "$PSScriptRoot\..\tools\Get-NuGetTool.ps1"
37 |
38 | try {
39 | Write-Verbose "Installing $PackageId..."
40 | $nugetArgs = "Install",$PackageId,"-OutputDirectory",$PackagesDir,'-ConfigFile',$ConfigFile
41 | if ($Version) { $nugetArgs += "-Version",$Version }
42 | if ($Source) { $nugetArgs += "-FallbackSource",$Source }
43 | if ($Prerelease) { $nugetArgs += "-Prerelease" }
44 | $nugetArgs += '-Verbosity',$Verbosity
45 |
46 | if ($PSCmdlet.ShouldProcess($PackageId, 'nuget install')) {
47 | $p = Start-Process $nugetPath $nugetArgs -NoNewWindow -Wait -PassThru
48 | if ($null -ne $p.ExitCode -and $p.ExitCode -ne 0) { throw }
49 | }
50 |
51 | # Provide the path to the installed package directory to our caller.
52 | Write-Output (Get-ChildItem "$PackagesDir\$PackageId.*")[0].FullName
53 | } finally {
54 | Pop-Location
55 | }
56 |
--------------------------------------------------------------------------------
/azure-pipelines/Merge-CodeCoverage.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env pwsh
2 |
3 | <#
4 | .SYNOPSIS
5 | Merges code coverage reports.
6 | .PARAMETER Path
7 | The path(s) to search for Cobertura code coverage reports.
8 | .PARAMETER Format
9 | The format for the merged result. The default is Cobertura
10 | .PARAMETER OutputDir
11 | The directory the merged result will be written to. The default is `coveragereport` in the root of this repo.
12 | #>
13 | [CmdletBinding()]
14 | Param(
15 | [Parameter(Mandatory=$true)]
16 | [string[]]$Path,
17 | [ValidateSet('Badges', 'Clover', 'Cobertura', 'CsvSummary', 'Html', 'Html_Dark', 'Html_Light', 'HtmlChart', 'HtmlInline', 'HtmlInline_AzurePipelines', 'HtmlInline_AzurePipelines_Dark', 'HtmlInline_AzurePipelines_Light', 'HtmlSummary', 'JsonSummary', 'Latex', 'LatexSummary', 'lcov', 'MarkdownSummary', 'MHtml', 'PngChart', 'SonarQube', 'TeamCitySummary', 'TextSummary', 'Xml', 'XmlSummary')]
18 | [string]$Format='Cobertura',
19 | [string]$OutputFile=("$PSScriptRoot/../coveragereport/merged.cobertura.xml")
20 | )
21 |
22 | $RepoRoot = [string](Resolve-Path $PSScriptRoot/..)
23 | Push-Location $RepoRoot
24 | try {
25 | Write-Verbose "Searching $Path for *.cobertura.xml files"
26 | $reports = Get-ChildItem -Recurse $Path -Filter *.cobertura.xml
27 |
28 | if ($reports) {
29 | $reports |% { $_.FullName } |% {
30 | # In addition to replacing {reporoot}, we also normalize on one kind of slash so that the report aggregates data for a file whether data was collected on Windows or not.
31 | $xml = [xml](Get-Content -LiteralPath $_)
32 | $xml.coverage.packages.package.classes.class |? { $_.filename} |% {
33 | $_.filename = $_.filename.Replace('{reporoot}', $RepoRoot).Replace([IO.Path]::AltDirectorySeparatorChar, [IO.Path]::DirectorySeparatorChar)
34 | }
35 |
36 | $xml.Save($_)
37 | }
38 |
39 | $Inputs = $reports |% { Resolve-Path -relative $_.FullName }
40 |
41 | if ((Split-Path $OutputFile) -and -not (Test-Path (Split-Path $OutputFile))) {
42 | New-Item -Type Directory -Path (Split-Path $OutputFile) | Out-Null
43 | }
44 |
45 | & dotnet dotnet-coverage merge $Inputs -o $OutputFile -f cobertura
46 | } else {
47 | Write-Error "No reports found to merge."
48 | }
49 | } finally {
50 | Pop-Location
51 | }
52 |
--------------------------------------------------------------------------------
/azure-pipelines/NuGetSbom.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 | $(TargetsForTfmSpecificBuildOutput);IncludeSbomInNupkg
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/azure-pipelines/PoliCheckExclusions.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | NODE_MODULES|.STORE
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/azure-pipelines/PostPRMessage.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding(SupportsShouldProcess = $true)]
2 | param(
3 | [Parameter(Mandatory=$true)]
4 | $AccessToken,
5 | [Parameter(Mandatory=$true)]
6 | $Markdown,
7 | [ValidateSet('Active','ByDesign','Closed','Fixed','Pending','Unknown','WontFix')]
8 | $CommentState='Active'
9 | )
10 |
11 | # See https://docs.microsoft.com/en-us/dotnet/api/microsoft.teamfoundation.sourcecontrol.webapi.commentthreadstatus?view=azure-devops-dotnet
12 | if ($CommentState -eq 'Active') {
13 | $StatusCode = 1
14 | } elseif ($CommentState -eq 'ByDesign') {
15 | $StatusCode = 5
16 | } elseif ($CommentState -eq 'Closed') {
17 | $StatusCode = 4
18 | } elseif ($CommentState -eq 'Fixed') {
19 | $StatusCode = 2
20 | } elseif ($CommentState -eq 'Pending') {
21 | $StatusCode = 6
22 | } elseif ($CommentState -eq 'Unknown') {
23 | $StatusCode = 0
24 | } elseif ($CommentState -eq 'WontFix') {
25 | $StatusCode = 3
26 | }
27 |
28 | # Build the JSON body up
29 | $body = ConvertTo-Json @{
30 | comments = @(@{
31 | parentCommentId = 0
32 | content = $Markdown
33 | commentType = 1
34 | })
35 | status = $StatusCode
36 | }
37 |
38 | Write-Verbose "Posting JSON payload: `n$Body"
39 |
40 | # Post the message to the Pull Request
41 | # https://docs.microsoft.com/en-us/rest/api/azure/devops/git/pull%20request%20threads?view=azure-devops-rest-5.1
42 | $url = "$($env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI)$env:SYSTEM_TEAMPROJECTID/_apis/git/repositories/$($env:BUILD_REPOSITORY_NAME)/pullRequests/$($env:SYSTEM_PULLREQUEST_PULLREQUESTID)/threads?api-version=5.1"
43 | if ($PSCmdlet.ShouldProcess($url, 'Post comment via REST call')) {
44 | try {
45 | if (!$env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI) {
46 | Write-Error "Posting to the pull request requires that the script is running in an Azure Pipelines context."
47 | exit 1
48 | }
49 | Write-Host "Posting PR comment to: $url"
50 | Invoke-RestMethod -Uri $url -Method POST -Headers @{Authorization = "Bearer $AccessToken"} -Body $Body -ContentType application/json
51 | }
52 | catch {
53 | Write-Error $_
54 | Write-Error $_.Exception.Message
55 | exit 2
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/azure-pipelines/TSAOptions.json:
--------------------------------------------------------------------------------
1 | {
2 | "tsaVersion": "TsaV2",
3 | "codebase": "NewOrUpdate",
4 | "codebaseName": "LibraryName",
5 | "tsaStamp": "DevDiv",
6 | "tsaEnvironment": "PROD",
7 | "notificationAliases": [
8 | "vsidemicrobuild@microsoft.com"
9 | ],
10 | "codebaseAdmins": [
11 | "REDMOND\\andarno"
12 | ],
13 | "instanceUrl": "https://devdiv.visualstudio.com",
14 | "projectName": "DevDiv",
15 | "areaPath": "DevDiv\\VS Core",
16 | "iterationPath": "DevDiv",
17 | "alltools": true,
18 | "repositoryName": "Library.Template"
19 | }
20 |
--------------------------------------------------------------------------------
/azure-pipelines/WIFtoPATauth.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: deadPATServiceConnectionId # The GUID of the PAT-based service connection whose access token must be replaced.
3 | type: string
4 | - name: wifServiceConnectionName # The name of the WIF service connection to use to get the access token.
5 | type: string
6 | - name: resource # The scope for which the access token is requested.
7 | type: string
8 | default: 499b84ac-1321-427f-aa17-267ca6975798 # Azure Artifact feeds (any of them)
9 |
10 | steps:
11 | - task: AzureCLI@2
12 | displayName: 🔏 Authenticate with WIF service connection
13 | inputs:
14 | azureSubscription: ${{ parameters.wifServiceConnectionName }}
15 | scriptType: pscore
16 | scriptLocation: inlineScript
17 | inlineScript: |
18 | $accessToken = az account get-access-token --query accessToken --resource '${{ parameters.resource }}' -o tsv
19 | # Set the access token as a secret, so it doesn't get leaked in the logs
20 | Write-Host "##vso[task.setsecret]$accessToken"
21 | # Override the apitoken of the nuget service connection, for the duration of this stage
22 | Write-Host "##vso[task.setendpoint id=${{ parameters.deadPATServiceConnectionId }};field=authParameter;key=apitoken]$accessToken"
23 |
--------------------------------------------------------------------------------
/azure-pipelines/apiscan.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: windowsPool
3 | type: object
4 | - name: RealSign
5 | type: boolean
6 |
7 | jobs:
8 | - job: apiscan
9 | displayName: APIScan
10 | dependsOn: Windows
11 | pool: ${{ parameters.windowsPool }}
12 | timeoutInMinutes: 120
13 | templateContext:
14 | ${{ if not(parameters.RealSign) }}:
15 | mb:
16 | signing: # if the build is test-signed, install the signing plugin so that CSVTestSignPolicy.xml is available
17 | enabled: true
18 | zipSources: false
19 | signType: test
20 | outputs:
21 | - output: pipelineArtifact
22 | displayName: 📢 collect apiscan artifact
23 | targetPath: $(Pipeline.Workspace)/.gdn/.r/apiscan/001/Logs
24 | artifactName: apiscan-logs
25 | condition: succeededOrFailed()
26 | variables:
27 | - name: SymbolsFeatureName
28 | value: $[ dependencies.Windows.outputs['SetPipelineVariables.SymbolsFeatureName'] ]
29 | - name: NBGV_MajorMinorVersion
30 | value: $[ dependencies.Windows.outputs['nbgv.NBGV_MajorMinorVersion'] ]
31 | - ${{ if eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9') }}:
32 | # https://dev.azure.com/devdiv/DevDiv/_wiki/wikis/DevDiv.wiki/25351/APIScan-step-by-step-guide-to-setting-up-a-Pipeline
33 | - group: VSEng sponsored APIScan # Expected to provide ApiScanClientId
34 | steps:
35 | # We need TSAOptions.json
36 | - checkout: self
37 | fetchDepth: 1
38 |
39 | - download: current
40 | artifact: APIScanInputs
41 | displayName: 🔻 Download APIScanInputs artifact
42 |
43 | - task: APIScan@2
44 | displayName: 🔍 Run APIScan
45 | inputs:
46 | softwareFolder: $(Pipeline.Workspace)/APIScanInputs
47 | softwareName: $(SymbolsFeatureName)
48 | softwareVersionNum: $(NBGV_MajorMinorVersion)
49 | isLargeApp: false
50 | toolVersion: Latest
51 | preserveLogsFolder: true
52 | env:
53 | AzureServicesAuthConnectionString: runAs=App;AppId=$(ApiScanClientId)
54 |
55 | # File bugs when APIScan finds issues
56 | - task: TSAUpload@2
57 | displayName: 🪳 TSA upload
58 | inputs:
59 | GdnPublishTsaOnboard: True
60 | GdnPublishTsaConfigFile: $(Build.SourcesDirectory)\azure-pipelines\TSAOptions.json
61 | condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
62 |
--------------------------------------------------------------------------------
/azure-pipelines/dotnet.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: RunTests
3 | - name: IsOptProf
4 | type: boolean
5 | default: false
6 | - name: Is1ESPT
7 | type: boolean
8 |
9 | steps:
10 |
11 | - script: dotnet build -t:build,pack --no-restore -c $(BuildConfiguration) -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog"
12 | displayName: 🛠 dotnet build
13 |
14 | - ${{ if not(parameters.IsOptProf) }}:
15 | - powershell: tools/dotnet-test-cloud.ps1 -Configuration $(BuildConfiguration) -Agent $(Agent.JobName) -PublishResults
16 | displayName: 🧪 dotnet test
17 | condition: and(succeeded(), ${{ parameters.RunTests }})
18 |
19 | - ${{ if parameters.IsOptProf }}:
20 | - script: dotnet pack src\VSInsertionMetadata -c $(BuildConfiguration) -warnaserror /bl:"$(Build.ArtifactStagingDirectory)/build_logs/VSInsertion-Pack.binlog"
21 | displayName: 🔧 dotnet pack VSInsertionMetadata
22 |
23 | - powershell: tools/variables/_define.ps1
24 | failOnStderr: true
25 | displayName: ⚙ Update pipeline variables based on build outputs
26 | condition: succeededOrFailed()
27 |
28 | - ${{ if parameters.Is1ESPT }}:
29 | - powershell: azure-pipelines/publish_artifacts.ps1 -StageOnly -AvoidSymbolicLinks -ArtifactNameSuffix "-$(Agent.JobName)" -Verbose
30 | failOnStderr: true
31 | displayName: 📢 Stage artifacts
32 | condition: succeededOrFailed()
33 | - ${{ else }}:
34 | - powershell: azure-pipelines/publish_artifacts.ps1 -ArtifactNameSuffix "-$(Agent.JobName)" -Verbose
35 | failOnStderr: true
36 | displayName: 📢 Publish artifacts
37 | condition: succeededOrFailed()
38 |
39 | - ${{ if and(ne(variables['codecov_token'], ''), parameters.RunTests) }}:
40 | - powershell: |
41 | $ArtifactStagingFolder = & "tools/Get-ArtifactsStagingDirectory.ps1"
42 | $CoverageResultsFolder = Join-Path $ArtifactStagingFolder "coverageResults-$(Agent.JobName)"
43 | tools/publish-CodeCov.ps1 -CodeCovToken "$(codecov_token)" -PathToCodeCoverage "$CoverageResultsFolder" -Name "$(Agent.JobName) Coverage Results" -Flags "$(Agent.JobName)"
44 | displayName: 📢 Publish code coverage results to codecov.io
45 | timeoutInMinutes: 3
46 | continueOnError: true
47 |
--------------------------------------------------------------------------------
/azure-pipelines/falsepositives.gdnsuppress:
--------------------------------------------------------------------------------
1 | {
2 | "version": "latest",
3 | "suppressionSets": {
4 | "falsepositives": {
5 | "name": "falsepositives",
6 | "createdDate": "2021-12-03 00:23:08Z",
7 | "lastUpdatedDate": "2021-12-03 00:23:08Z"
8 | }
9 | },
10 | "results": {
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/azure-pipelines/install-dependencies.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: initArgs
3 | type: string
4 | default: ''
5 | - name: needsAzurePublicFeeds
6 | type: boolean
7 | default: true # If nuget.config pulls from the azure-public account, we need to authenticate when building on the devdiv account.
8 |
9 | steps:
10 | - ${{ if and(parameters.needsAzurePublicFeeds, eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9')) }}:
11 | - template: WIFtoPATauth.yml
12 | parameters:
13 | wifServiceConnectionName: azure-public/vside package pull
14 | deadPATServiceConnectionId: 0ae39abc-4d06-4436-a7b5-865833df49db # azure-public/msft_consumption
15 |
16 | - task: NuGetAuthenticate@1
17 | displayName: 🔏 Authenticate NuGet feeds
18 | inputs:
19 | ${{ if and(parameters.needsAzurePublicFeeds, eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9')) }}:
20 | nuGetServiceConnections: azure-public/msft_consumption
21 |
22 | - powershell: |
23 | $AccessToken = '$(System.AccessToken)' # Avoid specifying the access token directly on the init.ps1 command line to avoid it showing up in errors
24 | .\init.ps1 -AccessToken $AccessToken ${{ parameters['initArgs'] }} -UpgradePrerequisites -NoNuGetCredProvider
25 | dotnet --info
26 |
27 | # Print mono version if it is present.
28 | if (Get-Command mono -ErrorAction SilentlyContinue) {
29 | mono --version
30 | }
31 | displayName: ⚙ Install prerequisites
32 |
33 | - powershell: tools/variables/_define.ps1
34 | failOnStderr: true
35 | displayName: ⚙ Set pipeline variables based on source
36 | name: SetPipelineVariables
37 |
--------------------------------------------------------------------------------
/azure-pipelines/integration-test.yml:
--------------------------------------------------------------------------------
1 | jobs:
2 | # Matrix over VS 2019 and VS 2022
3 |
4 | - job: integrationtest
5 | displayName: 🧪 Integration tests
6 | strategy:
7 | matrix:
8 | vs2019:
9 | vmImage: windows-2019
10 | currentSdk: false
11 | vs2022:
12 | vmImage: windows-2022
13 | currentSdk: true
14 | pool:
15 | vmImage: $[ variables['vmImage'] ]
16 | dependsOn: Windows
17 | steps:
18 | - checkout: self
19 | fetchDepth: 1 # no need for git history here
20 | clean: true
21 | - task: CopyFiles@2
22 | inputs:
23 | SourceFolder: integration-tests
24 | Contents: '**'
25 | TargetFolder: $(Pipeline.Workspace)/integration-tests
26 | Overwrite: true
27 | displayName: 🔧 Copy integration tests out of the repo
28 | - download: current
29 | artifact: deployables-Windows
30 | displayName: 🔻 Download nupkg
31 | - pwsh: |
32 | $nupkg = (Get-ChildItem -Path $(Pipeline.Workspace)/deployables-Windows/NuGet -Filter *.nupkg)[0].Name
33 | if ($nupkg -match 'Microsoft\.Windows\.CsWin32\.(.+)\.nupkg') {
34 | $version = $Matches[1]
35 | Write-Host "Will consume Microsoft.Windows.CsWin32 $version"
36 | Write-Host "##vso[task.setvariable variable=NuGetPackageVersion]$version"
37 | }
38 | displayName: 🔧 Consume nupkg
39 | - task: MSBuild@1
40 | displayName: 🧪 MSBuild non-sdk style
41 | inputs:
42 | solution: $(Pipeline.Workspace)\integration-tests\nonsdk\nonsdk.csproj
43 | msbuildArguments: /r
44 | - task: MSBuild@1
45 | displayName: 🧪 MSBuild sdk-style
46 | inputs:
47 | solution: $(Pipeline.Workspace)\integration-tests\sdk\sdk.csproj
48 | msbuildArguments: /r
49 | condition: eq(variables.currentSdk, 'true')
50 | - pwsh: dotnet build
51 | displayName: 🧪 dotnet build
52 | workingDirectory: $(Pipeline.Workspace)\integration-tests\sdk
53 | condition: eq(variables.currentSdk, 'true')
54 |
--------------------------------------------------------------------------------
/azure-pipelines/microbuild.after.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: EnableOptProf
3 | type: boolean
4 | default: false
5 | - name: IsOptProf
6 | type: boolean
7 | default: false
8 | - name: SkipCodesignVerify
9 | type: boolean
10 |
11 | steps:
12 | - ${{ if not(parameters.SkipCodesignVerify) }}: # skip CodesignVerify on validation builds because we don't even test-sign nupkg's.
13 | - task: MicroBuildCodesignVerify@3
14 | displayName: 🔍 Verify Signed Files
15 | inputs:
16 | ApprovalListPathForSigs: $(Build.SourcesDirectory)\azure-pipelines\no_strongname.txt
17 | ApprovalListPathForCerts: $(Build.SourcesDirectory)\azure-pipelines\no_authenticode.txt
18 | TargetFolders: |
19 | $(Build.SourcesDirectory)/bin/Packages/$(BuildConfiguration)
20 | condition: and(succeeded(), eq(variables['Agent.OS'], 'Windows_NT'))
21 |
22 | - ${{ if parameters.IsOptProf }}:
23 | - task: ms-vscs-artifact.build-tasks.artifactDropTask-1.artifactDropTask@0
24 | inputs:
25 | dropServiceURI: https://devdiv.artifacts.visualstudio.com
26 | buildNumber: $(ProfilingInputsDropName)
27 | sourcePath: $(Build.ArtifactStagingDirectory)\OptProf\ProfilingInputs
28 | toLowerCase: false
29 | usePat: true
30 | displayName: 📢 Publish to Artifact Services - ProfilingInputs
31 | condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest'))
32 |
33 | - task: PublishBuildArtifacts@1
34 | inputs:
35 | PathtoPublish: $(Build.ArtifactStagingDirectory)/InsertionOutputs
36 | ArtifactName: InsertionOutputs
37 | ArtifactType: Container
38 | displayName: 📢 Publish InsertionOutputs as Azure DevOps artifacts
39 |
--------------------------------------------------------------------------------
/azure-pipelines/microbuild.before.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: EnableLocalization
3 | type: boolean
4 | default: false
5 | - name: EnableOptProf
6 | type: boolean
7 | default: false
8 | - name: IsOptProf
9 | type: boolean
10 | default: false
11 | - name: ShouldSkipOptimize
12 | type: boolean
13 | default: false
14 | - name: RealSign
15 | type: boolean
16 |
17 | steps:
18 | - ${{ if and(not(parameters.IsOptProf), ne(variables['Build.Reason'], 'PullRequest')) }}:
19 | # notice@0 requires CG detection to run first, and non-default branches don't inject it automatically.
20 | - ${{ if ne(variables['Build.SourceBranch'], 'refs/heads/main') }}:
21 | - task: ComponentGovernanceComponentDetection@0
22 | displayName: 🔍 Component Detection
23 |
24 | - task: notice@0
25 | displayName: 🛠️ Generate NOTICE file
26 | inputs:
27 | outputfile: $(System.DefaultWorkingDirectory)/obj/NOTICE
28 | outputformat: text
29 | retryCountOnTaskFailure: 3 # fails when the cloud service is overloaded
30 | continueOnError: ${{ not(parameters.RealSign) }} # Tolerate failures when we're not building something that may ship.
31 |
32 | - ${{ if parameters.IsOptProf }}:
33 | # We have to install these plugins ourselves for Optprof runs because those pipelines haven't migrated to 1ES PT yet.
34 | - task: MicroBuildOptProfPlugin@6
35 | inputs:
36 | ProfilingInputsDropName: $(ProfilingInputsDropName)
37 | OptimizationInputsLookupMethod: DropPrefix
38 | DropNamePrefix: OptimizationInputs/$(System.TeamProject)/$(Build.Repository.Name)
39 | ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }}
40 | AccessToken: $(System.AccessToken)
41 | displayName: 🔧 Install OptProf Plugin
42 |
43 | - task: MicroBuildSigningPlugin@4
44 | inputs:
45 | signType: Real
46 | zipSources: false
47 | displayName: 🔧 Install MicroBuild Signing Plugin
48 |
49 | - ${{ if parameters.EnableLocalization }}:
50 | - task: MicroBuildLocalizationPlugin@4
51 | inputs:
52 | languages: $(LocLanguages)
53 | displayName: 🔧 Install MicroBuild Localization Plugin
54 |
--------------------------------------------------------------------------------
/azure-pipelines/no_authenticode.txt:
--------------------------------------------------------------------------------
1 | bin\packages\release\vsix\_manifest\manifest.cat,sbom signed
2 | bin\packages\release\vsix\_manifest\spdx_2.2\manifest.cat,sbom signed
3 | *\yamldotnet.dll,oss
4 |
--------------------------------------------------------------------------------
/azure-pipelines/no_strongname.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CsWin32/10ff614acb54f6d5a5dbb77c59bd8786e5c99097/azure-pipelines/no_strongname.txt
--------------------------------------------------------------------------------
/azure-pipelines/publish-codecoverage.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: EnableMacOSBuild
3 | type: boolean
4 | - name: EnableLinuxBuild
5 | type: boolean
6 |
7 | steps:
8 | - download: current
9 | artifact: coverageResults-Windows
10 | displayName: 🔻 Download Windows code coverage results
11 | continueOnError: true
12 | - ${{ if parameters.EnableLinuxBuild }}:
13 | - download: current
14 | artifact: coverageResults-Linux
15 | displayName: 🔻 Download Linux code coverage results
16 | continueOnError: true
17 | - ${{ if parameters.EnableMacOSBuild }}:
18 | - download: current
19 | artifact: coverageResults-macOS
20 | displayName: 🔻 Download macOS code coverage results
21 | continueOnError: true
22 | - powershell: azure-pipelines/Merge-CodeCoverage.ps1 -Path '$(Pipeline.Workspace)' -OutputFile coveragereport/merged.cobertura.xml -Format Cobertura -Verbose
23 | displayName: ⚙ Merge coverage
24 | - task: PublishCodeCoverageResults@2
25 | displayName: 📢 Publish code coverage results to Azure DevOps
26 | inputs:
27 | summaryFileLocation: coveragereport/merged.cobertura.xml
28 | failIfCoverageEmpty: true
29 |
--------------------------------------------------------------------------------
/azure-pipelines/publish-symbols.yml:
--------------------------------------------------------------------------------
1 | parameters:
2 | - name: EnableMacOSBuild
3 | type: boolean
4 | - name: EnableLinuxBuild
5 | type: boolean
6 |
7 | steps:
8 | - task: DownloadPipelineArtifact@2
9 | inputs:
10 | artifact: symbols-Windows
11 | path: $(Pipeline.Workspace)/symbols/Windows
12 | displayName: 🔻 Download Windows symbols
13 | continueOnError: true
14 | - ${{ if parameters.EnableLinuxBuild }}:
15 | - task: DownloadPipelineArtifact@2
16 | inputs:
17 | artifact: symbols-Linux
18 | path: $(Pipeline.Workspace)/symbols/Linux
19 | displayName: 🔻 Download Linux symbols
20 | continueOnError: true
21 | - ${{ if parameters.EnableMacOSBuild }}:
22 | - task: DownloadPipelineArtifact@2
23 | inputs:
24 | artifact: symbols-macOS
25 | path: $(Pipeline.Workspace)/symbols/macOS
26 | displayName: 🔻 Download macOS symbols
27 | continueOnError: true
28 |
29 | - task: DownloadPipelineArtifact@2
30 | inputs:
31 | artifact: test_symbols-Windows
32 | path: $(Pipeline.Workspace)/test_symbols/Windows
33 | displayName: 🔻 Download Windows test symbols
34 | continueOnError: true
35 | - ${{ if parameters.EnableLinuxBuild }}:
36 | - task: DownloadPipelineArtifact@2
37 | inputs:
38 | artifact: test_symbols-Linux
39 | path: $(Pipeline.Workspace)/test_symbols/Linux
40 | displayName: 🔻 Download Linux test symbols
41 | continueOnError: true
42 | - ${{ if parameters.EnableMacOSBuild }}:
43 | - task: DownloadPipelineArtifact@2
44 | inputs:
45 | artifact: test_symbols-macOS
46 | path: $(Pipeline.Workspace)/test_symbols/macOS
47 | displayName: 🔻 Download macOS test symbols
48 | continueOnError: true
49 |
50 | - task: PublishSymbols@2
51 | inputs:
52 | SymbolsFolder: $(Pipeline.Workspace)/symbols
53 | SearchPattern: '**/*.pdb'
54 | IndexSources: false
55 | SymbolServerType: TeamServices
56 | displayName: 📢 Publish symbols
57 |
58 | - task: PublishSymbols@2
59 | inputs:
60 | SymbolsFolder: $(Pipeline.Workspace)/test_symbols
61 | SearchPattern: '**/*.pdb'
62 | IndexSources: false
63 | SymbolServerType: TeamServices
64 | displayName: 📢 Publish test symbols
65 |
66 | - powershell: tools/Prepare-Legacy-Symbols.ps1 -Path $(Pipeline.Workspace)/symbols/Windows
67 | displayName: ⚙ Prepare symbols for symbol archival
68 |
--------------------------------------------------------------------------------
/azure-pipelines/publish_artifacts.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This script translates all the artifacts described by _all.ps1
4 | into commands that instruct Azure Pipelines to actually collect those artifacts.
5 | #>
6 |
7 | [CmdletBinding()]
8 | param (
9 | [string]$ArtifactNameSuffix,
10 | [switch]$StageOnly,
11 | [switch]$AvoidSymbolicLinks
12 | )
13 |
14 | Function Set-PipelineVariable($name, $value) {
15 | if ((Test-Path "Env:\$name") -and (Get-Item "Env:\$name").Value -eq $value) {
16 | return # already set
17 | }
18 |
19 | #New-Item -LiteralPath "Env:\$name".ToUpper() -Value $value -Force | Out-Null
20 | Write-Host "##vso[task.setvariable variable=$name]$value"
21 | }
22 |
23 | Function Test-ArtifactUploaded($artifactName) {
24 | $varName = "ARTIFACTUPLOADED_$($artifactName.ToUpper())"
25 | Test-Path "env:$varName"
26 | }
27 |
28 | & "$PSScriptRoot/../tools/artifacts/_stage_all.ps1" -ArtifactNameSuffix $ArtifactNameSuffix -AvoidSymbolicLinks:$AvoidSymbolicLinks |% {
29 | # Set a variable which will out-live this script so that a subsequent attempt to collect and upload artifacts
30 | # will skip this one from a check in the _all.ps1 script.
31 | Set-PipelineVariable "ARTIFACTSTAGED_$($_.Name.ToUpper())" 'true'
32 | Write-Host "Staged artifact $($_.Name) to $($_.Path)"
33 |
34 | if (!$StageOnly) {
35 | if (Test-ArtifactUploaded $_.Name) {
36 | Write-Host "Skipping $($_.Name) because it has already been uploaded." -ForegroundColor DarkGray
37 | } else {
38 | Write-Host "##vso[artifact.upload containerfolder=$($_.Name);artifactname=$($_.Name);]$($_.Path)"
39 |
40 | # Set a variable which will out-live this script so that a subsequent attempt to collect and upload artifacts
41 | # will skip this one from a check in the _all.ps1 script.
42 | Set-PipelineVariable "ARTIFACTUPLOADED_$($_.Name.ToUpper())" 'true'
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/azure-pipelines/release-deployment-prep.yml:
--------------------------------------------------------------------------------
1 | steps:
2 | - download: CI
3 | artifact: Variables-Windows
4 | displayName: 🔻 Download Variables-Windows artifact
5 | - powershell: $(Pipeline.Workspace)/CI/Variables-Windows/_define.ps1
6 | displayName: ⚙️ Set pipeline variables based on artifacts
7 |
--------------------------------------------------------------------------------
/azure-pipelines/schedule-only-steps.yml:
--------------------------------------------------------------------------------
1 | steps:
2 | - powershell: echo "##vso[build.addbuildtag]auto-insertion"
3 | displayName: Tag for auto-insertion
4 |
--------------------------------------------------------------------------------
/azurepipelines-coverage.yml:
--------------------------------------------------------------------------------
1 | # https://learn.microsoft.com/azure/devops/pipelines/test/codecoverage-for-pullrequests?view=azure-devops
2 | coverage:
3 | status:
4 | comments: on # add comment to PRs reporting diff in coverage of modified files
5 | diff: # diff coverage is code coverage only for the lines changed in a pull request.
6 | target: 70% # set this to a desired %. Default is 70%
7 |
--------------------------------------------------------------------------------
/docfx/.gitignore:
--------------------------------------------------------------------------------
1 | _site/
2 | api/
3 |
--------------------------------------------------------------------------------
/docfx/docfx.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": [
3 | {
4 | "src": [
5 | {
6 | "src": "../src/Microsoft.Windows.CsWin32",
7 | "files": [
8 | "**/*.csproj"
9 | ]
10 | }
11 | ],
12 | "dest": "api"
13 | }
14 | ],
15 | "build": {
16 | "content": [
17 | {
18 | "files": [
19 | "**/*.{md,yml}"
20 | ],
21 | "exclude": [
22 | "_site/**"
23 | ]
24 | }
25 | ],
26 | "resource": [
27 | {
28 | "files": [
29 | "images/**"
30 | ]
31 | }
32 | ],
33 | "xref": [
34 | "https://learn.microsoft.com/en-us/dotnet/.xrefmap.json"
35 | ],
36 | "output": "_site",
37 | "template": [
38 | "default",
39 | "modern"
40 | ],
41 | "globalMetadata": {
42 | "_appName": "CsWin32",
43 | "_appTitle": "CsWin32",
44 | "_enableSearch": true,
45 | "pdf": false
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/docfx/docs/3rdPartyMetadata.md:
--------------------------------------------------------------------------------
1 | # 3rd party metadata
2 |
3 | CsWin32 comes with dependencies on Windows metadata for the SDK and WDK, allowing C# programs to generate interop code for Windows applications.
4 | But the general transformation from metadata to C# code may be applied to other metadata inputs, allowing you to generate similar metadata for 3rd party native libraries and use CsWin32 to generate C# interop APIs for it.
5 |
6 | ## Constructing metadata for other libraries
7 |
8 | Constructing metadata is outside the scope of this document.
9 | However you may find [the win32metadata architecture](https://github.com/microsoft/win32metadata/blob/main/docs/architecture.md) document instructive.
10 |
11 | ## Hooking metadata into CsWin32
12 |
13 | Metadata is fed into CsWin32 through MSBuild items.
14 |
15 | Item Type | Purpose
16 | --|--
17 | `ProjectionMetadataWinmd` | Path to the .winmd file.
18 | `ProjectionDocs` | Path to an optional msgpack data file that contains API-level documentation.
19 | `AppLocalAllowedLibraries` | The filename (including extension) of a native library that is allowed to ship in the app directory (as opposed to only %windir%\system32).
20 |
21 | ## Packaging up metadata
22 |
23 | Build a NuGet package with the following layout:
24 |
25 | ```
26 | buildTransitive\
27 | YourPackageId.props
28 | yournativelib.winmd
29 | runtimes\
30 | win-x86\
31 | yournativelib.dll
32 | win-x64\
33 | yournativelib.dll
34 | win-arm64\
35 | yournativelib.dll
36 | ...
37 | ```
38 |
39 | Your package metadata may want to express a dependency on the Microsoft.Windows.CsWin32 package.
40 |
41 | The `YourPackageId.props` file should include the msbuild items above, as appropriate.
42 | For example:
43 |
44 | ```xml
45 |
46 |
47 |
48 |
49 |
50 |
51 | ```
52 |
53 | ## Consuming your package
54 |
55 | A project can reference your NuGet package to get both the native dll deployed with their app and the C# interop APIs generated as they require through NativeMethods.txt using CsWin32, just like they can for Win32 APIs.
56 |
--------------------------------------------------------------------------------
/docfx/docs/features.md:
--------------------------------------------------------------------------------
1 | # Features
2 |
3 | * Rapidly add P/Invoke methods and supporting types to your C# project.
4 | * No bulky assemblies to ship alongside your application.
5 | * Generate the optimal code for your target framework and C# language version.
6 | * `SafeHandle`-types automatically generated.
7 | * Generates xml documentation based on and links back to docs.microsoft.com
8 |
9 | 
10 |
--------------------------------------------------------------------------------
/docfx/docs/toc.yml:
--------------------------------------------------------------------------------
1 | items:
2 | - href: features.md
3 | - href: getting-started.md
4 | - href: 3rdPartyMetadata.md
5 |
6 |
--------------------------------------------------------------------------------
/docfx/images/ConfigurationManager_x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CsWin32/10ff614acb54f6d5a5dbb77c59bd8786e5c99097/docfx/images/ConfigurationManager_x64.png
--------------------------------------------------------------------------------
/docfx/images/StandardToolbarPlatformSwitcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CsWin32/10ff614acb54f6d5a5dbb77c59bd8786e5c99097/docfx/images/StandardToolbarPlatformSwitcher.png
--------------------------------------------------------------------------------
/docfx/images/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CsWin32/10ff614acb54f6d5a5dbb77c59bd8786e5c99097/docfx/images/demo.gif
--------------------------------------------------------------------------------
/docfx/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | _layout: landing
3 | ---
4 |
5 | # Overview
6 |
7 | This is your docfx landing page.
8 |
9 | Click "Docs" across the top to get started.
10 |
--------------------------------------------------------------------------------
/docfx/toc.yml:
--------------------------------------------------------------------------------
1 | items:
2 | - name: Docs
3 | href: docs/
4 | - name: Source Generator API
5 | href: api/
6 | - name: GitHub
7 | href: https://github.com/microsoft/CsWin32
8 |
--------------------------------------------------------------------------------
/global.json:
--------------------------------------------------------------------------------
1 | {
2 | "sdk": {
3 | "version": "9.0.200",
4 | "rollForward": "patch",
5 | "allowPrerelease": false
6 | },
7 | "msbuild-sdks": {
8 | "Microsoft.Build.NoTargets": "3.7.56"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/init.cmd:
--------------------------------------------------------------------------------
1 | @echo off
2 | SETLOCAL
3 | set PS1UnderCmd=1
4 |
5 | :: Get the datetime in a format that can go in a filename.
6 | set _my_datetime=%date%_%time%
7 | set _my_datetime=%_my_datetime: =_%
8 | set _my_datetime=%_my_datetime::=%
9 | set _my_datetime=%_my_datetime:/=_%
10 | set _my_datetime=%_my_datetime:.=_%
11 | set CmdEnvScriptPath=%temp%\envvarscript_%_my_datetime%.cmd
12 |
13 | powershell.exe -NoProfile -NoLogo -ExecutionPolicy bypass -Command "try { & '%~dpn0.ps1' %*; exit $LASTEXITCODE } catch { write-host $_; exit 1 }"
14 |
15 | :: Set environment variables in the parent cmd.exe process.
16 | IF EXIST "%CmdEnvScriptPath%" (
17 | ENDLOCAL
18 | CALL "%CmdEnvScriptPath%"
19 | DEL "%CmdEnvScriptPath%"
20 | )
21 |
--------------------------------------------------------------------------------
/integration-tests/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/integration-tests/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/integration-tests/nonsdk/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/integration-tests/nonsdk/NativeMethods.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file may be blank, but it exercises the analyzer's System.Text.Json and dependencies.
3 | }
--------------------------------------------------------------------------------
/integration-tests/nonsdk/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | GetTickCount
2 |
--------------------------------------------------------------------------------
/integration-tests/nonsdk/Program.cs:
--------------------------------------------------------------------------------
1 | class Program
2 | {
3 | static void Main(string[] args)
4 | {
5 | Windows.Win32.PInvoke.GetTickCount();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/integration-tests/nonsdk/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ConsoleApp1")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ConsoleApp1")]
13 | [assembly: AssemblyCopyright("Copyright © 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("9765d95c-6df9-4cbf-91ee-ad70986830b6")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/integration-tests/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/integration-tests/sdk/NativeMethods.json:
--------------------------------------------------------------------------------
1 | {
2 | // This file may be blank, but it exercises the analyzer's System.Text.Json and dependencies.
3 | }
--------------------------------------------------------------------------------
/integration-tests/sdk/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | GetTickCount
2 |
--------------------------------------------------------------------------------
/integration-tests/sdk/Program.cs:
--------------------------------------------------------------------------------
1 | class Program
2 | {
3 | static void Main(string[] args)
4 | {
5 | Windows.Win32.PInvoke.GetTickCount();
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/integration-tests/sdk/sdk.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net8.0-windows
6 | 9
7 |
8 |
9 |
10 |
11 | $(NuGetPackageVersion)
12 | runtime; build; native; contentfiles; analyzers; buildtransitive
13 | all
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/nuget.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/settings.VisualStudio.json:
--------------------------------------------------------------------------------
1 | {
2 | "textEditor.codeCleanup.profile": "profile1"
3 | }
4 |
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # SA1600: Elements should be documented
4 | dotnet_diagnostic.SA1600.severity = silent
5 |
--------------------------------------------------------------------------------
/src/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | #pragma warning disable IDE0005 // Using directive is unnecessary.
5 | using System.Runtime.InteropServices;
6 | #pragma warning restore IDE0005 // Using directive is unnecessary.
7 |
8 | [assembly: DefaultDllImportSearchPaths(DllImportSearchPath.SafeDirectories)]
9 |
--------------------------------------------------------------------------------
/src/AssemblyInfo.vb:
--------------------------------------------------------------------------------
1 | ' Copyright (c) Microsoft Corporation. All rights reserved.
2 | ' Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | Imports System.Runtime.InteropServices
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | README.md
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/src/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/AnalyzerReleases.Shipped.md:
--------------------------------------------------------------------------------
1 | ; Shipped analyzer releases
2 | ; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
3 |
4 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/AnalyzerReleases.Unshipped.md:
--------------------------------------------------------------------------------
1 | ; Unshipped analyzer release
2 | ; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
3 |
4 | ### New Rules
5 | Rule ID | Category | Severity | Notes
6 | --------|----------|----------|-------
7 | PInvoke000 | Functionality | Error | SourceGenerator
8 | PInvoke001 | Functionality | Warning | SourceGenerator
9 | PInvoke002 | Functionality | Warning | SourceGenerator
10 | PInvoke003 | Functionality | Warning | SourceGenerator
11 | PInvoke004 | Functionality | Warning | SourceGenerator
12 | PInvoke005 | Functionality | Warning | SourceGenerator
13 | PInvoke006 | Configuration | Warning | SourceGenerator
14 | PInvoke007 | Functionality | Error | SourceGenerator
15 | PInvoke008 | Configuration | Error | SourceGenerator
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/ArrayTypeHandleInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal record ArrayTypeHandleInfo(TypeHandleInfo ElementType, ArrayShape Shape) : TypeHandleInfo, ITypeHandleContainer
7 | {
8 | public override string ToString() => this.ToTypeSyntaxForDisplay().ToString();
9 |
10 | internal override TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, Generator.GeneratingElement forElement, CustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes)
11 | {
12 | TypeSyntaxAndMarshaling element = this.ElementType.ToTypeSyntax(inputs, forElement, customAttributes);
13 | if (inputs.AllowMarshaling || inputs.IsField)
14 | {
15 | ArrayTypeSyntax arrayType = ArrayType(element.Type, SingletonList(ArrayRankSpecifier().AddSizes(this.Shape.Sizes.Select(size => LiteralExpression(SyntaxKind.NumericLiteralExpression, Literal(size))).ToArray())));
16 | MarshalAsAttribute? marshalAs = element.MarshalAsAttribute is object ? new MarshalAsAttribute(UnmanagedType.LPArray) { ArraySubType = element.MarshalAsAttribute.Value } : null;
17 | return new TypeSyntaxAndMarshaling(arrayType, marshalAs, element.NativeArrayInfo);
18 | }
19 | else
20 | {
21 | return new TypeSyntaxAndMarshaling(PointerType(element.Type));
22 | }
23 | }
24 |
25 | internal override bool? IsValueType(TypeSyntaxSettings inputs) => false;
26 | }
27 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/BindingRedirects.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal static class BindingRedirects
7 | {
8 | private static readonly string SourceGeneratorAssemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
9 | private static readonly Lazy> LocalAssemblies;
10 |
11 | static BindingRedirects()
12 | {
13 | LocalAssemblies = new Lazy>(
14 | () => Directory.GetFiles(SourceGeneratorAssemblyDirectory, "*.dll").ToDictionary(Path.GetFileNameWithoutExtension, StringComparer.OrdinalIgnoreCase));
15 | }
16 |
17 | private static bool IsNetFramework => RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework", StringComparison.OrdinalIgnoreCase);
18 |
19 | #pragma warning disable CA2255 // The 'ModuleInitializer' attribute should not be used in libraries
20 | [ModuleInitializer]
21 | #pragma warning restore CA2255 // The 'ModuleInitializer' attribute should not be used in libraries
22 | internal static void ApplyBindingRedirects()
23 | {
24 | if (IsNetFramework)
25 | {
26 | AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
27 | }
28 | }
29 |
30 | private static Assembly? CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
31 | {
32 | AssemblyName expected = new(args.Name);
33 | if (LocalAssemblies.Value.TryGetValue(expected.Name, out string? path))
34 | {
35 | var actual = AssemblyName.GetAssemblyName(path);
36 | if (actual.Version >= expected.Version)
37 | {
38 | return Assembly.LoadFile(path);
39 | }
40 | }
41 |
42 | return null;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/CustomAttributeTypeProvider.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
5 |
6 | namespace Microsoft.Windows.CsWin32;
7 |
8 | internal class CustomAttributeTypeProvider : ICustomAttributeTypeProvider
9 | {
10 | internal static readonly CustomAttributeTypeProvider Instance = new CustomAttributeTypeProvider();
11 |
12 | private CustomAttributeTypeProvider()
13 | {
14 | }
15 |
16 | public TypeSyntax GetPrimitiveType(PrimitiveTypeCode typeCode) => PrimitiveTypeHandleInfo.ToTypeSyntax(typeCode, preferNativeInt: false);
17 |
18 | public TypeSyntax GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
19 | {
20 | // CONSIDER: reuse GetNestingQualifiedName (with namespace support added) here.
21 | TypeReference tr = reader.GetTypeReference(handle);
22 | string name = reader.GetString(tr.Name);
23 | string ns = reader.GetString(tr.Namespace);
24 | return ParseName(ns + "." + name);
25 | }
26 |
27 | public TypeSyntax GetTypeFromSerializedName(string name) => ParseName(name.IndexOf(',') is int index && index >= 0 ? name.Substring(0, index) : name);
28 |
29 | public PrimitiveTypeCode GetUnderlyingEnumType(TypeSyntax type) => PrimitiveTypeCode.Int32; // an assumption that works for now.
30 |
31 | public bool IsSystemType(TypeSyntax type) => type is QualifiedNameSyntax { Left: IdentifierNameSyntax { Identifier: { ValueText: "System" } }, Right: { Identifier: { ValueText: "Type" } } };
32 |
33 | public TypeSyntax GetSystemType() => throw new NotImplementedException();
34 |
35 | public TypeSyntax GetSZArrayType(TypeSyntax elementType) => throw new NotImplementedException();
36 |
37 | public TypeSyntax GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => throw new NotImplementedException();
38 | }
39 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/GenerationFailedException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | ///
7 | /// An exception thrown when code generation fails.
8 | ///
9 | [Serializable]
10 | public class GenerationFailedException : Exception
11 | {
12 | ///
13 | /// Initializes a new instance of the class.
14 | ///
15 | public GenerationFailedException()
16 | {
17 | }
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | ///
23 | public GenerationFailedException(string message)
24 | : base(message)
25 | {
26 | }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | ///
32 | public GenerationFailedException(string message, Exception inner)
33 | : base(message, inner)
34 | {
35 | }
36 |
37 | ///
38 | /// Initializes a new instance of the class.
39 | ///
40 | ///
41 | protected GenerationFailedException(
42 | System.Runtime.Serialization.SerializationInfo info,
43 | System.Runtime.Serialization.StreamingContext context)
44 | : base(info, context)
45 | {
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/GeneratorExtensions.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | ///
7 | /// Extension methods for the interface.
8 | ///
9 | public static class GeneratorExtensions
10 | {
11 | ///
12 | public static bool TryGenerate(this IGenerator generator, string apiNameOrModuleWildcard, CancellationToken cancellationToken) => generator.TryGenerate(apiNameOrModuleWildcard, out _, cancellationToken);
13 |
14 | ///
15 | public static bool TryGenerateType(this IGenerator generator, string possiblyQualifiedName) => generator.TryGenerateType(possiblyQualifiedName, out _);
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | global using System.Collections.Immutable;
5 | global using System.Diagnostics;
6 | global using System.Diagnostics.CodeAnalysis;
7 | global using System.Globalization;
8 | global using System.Reflection;
9 | global using System.Reflection.Metadata;
10 | global using System.Runtime.CompilerServices;
11 | global using System.Runtime.InteropServices;
12 | global using System.Text;
13 | global using Microsoft.CodeAnalysis;
14 | global using Microsoft.CodeAnalysis.CSharp;
15 | global using Microsoft.CodeAnalysis.CSharp.Syntax;
16 | global using Microsoft.Windows.SDK.Win32Docs;
17 | global using static System.FormattableString;
18 | global using static Microsoft.Windows.CsWin32.FastSyntaxFactory;
19 | global using static Microsoft.Windows.CsWin32.SimpleSyntaxFactory;
20 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/ITypeHandleContainer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal interface ITypeHandleContainer
7 | {
8 | TypeHandleInfo ElementType { get; }
9 | }
10 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/MetadataCache.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal class MetadataCache
7 | {
8 | internal static readonly MetadataCache Default = new();
9 |
10 | private readonly Dictionary metadataFiles = new(StringComparer.OrdinalIgnoreCase);
11 |
12 | ///
13 | /// Gets a file accessor for the given path that supports many concurrent readers.
14 | ///
15 | /// The path to the .winmd file.
16 | /// The file accessor.
17 | internal MetadataFile GetMetadataFile(string path)
18 | {
19 | lock (this.metadataFiles)
20 | {
21 | MetadataFile? metadataFile;
22 | DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(path);
23 | if (this.metadataFiles.TryGetValue(path, out metadataFile))
24 | {
25 | if (metadataFile.LastWriteTimeUtc == lastWriteTimeUtc)
26 | {
27 | // We already have the file, and it is still current. Happy path.
28 | return metadataFile;
29 | }
30 |
31 | // Stale file. Evict from the cache.
32 | this.metadataFiles.Remove(path);
33 | metadataFile.Dispose();
34 | }
35 |
36 | // New or updated file. Re-open.
37 | this.metadataFiles.Add(path, metadataFile = new MetadataFile(path));
38 | return metadataFile;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/MetadataQualifiedTokens.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal record struct QualifiedTypeReferenceHandle(Generator Generator, TypeReferenceHandle ReferenceHandle)
7 | {
8 | internal MetadataReader Reader => this.Generator.Reader;
9 |
10 | internal QualifiedTypeReference Resolve() => new(this.Generator, this.Generator.Reader.GetTypeReference(this.ReferenceHandle));
11 | }
12 |
13 | internal record struct QualifiedTypeReference(Generator Generator, TypeReference Reference)
14 | {
15 | internal MetadataReader Reader => this.Generator.Reader;
16 | }
17 |
18 | internal record struct QualifiedTypeDefinitionHandle(Generator Generator, TypeDefinitionHandle DefinitionHandle)
19 | {
20 | internal MetadataReader Reader => this.Generator.Reader;
21 |
22 | internal QualifiedTypeDefinition Resolve() => new(this.Generator, this.Generator.Reader.GetTypeDefinition(this.DefinitionHandle));
23 | }
24 |
25 | internal record struct QualifiedTypeDefinition(Generator Generator, TypeDefinition Definition)
26 | {
27 | internal MetadataReader Reader => this.Generator.Reader;
28 | }
29 |
30 | internal record struct QualifiedMethodDefinitionHandle(Generator Generator, MethodDefinitionHandle MethodHandle)
31 | {
32 | internal MetadataReader Reader => this.Generator.Reader;
33 |
34 | internal QualifiedMethodDefinition Resolve() => new(this.Generator, this.Generator.Reader.GetMethodDefinition(this.MethodHandle));
35 | }
36 |
37 | internal record struct QualifiedMethodDefinition(Generator Generator, MethodDefinition Method)
38 | {
39 | internal MetadataReader Reader => this.Generator.Reader;
40 | }
41 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/Microsoft.Windows.CsWin32.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | netstandard2.0
6 | enable
7 |
8 |
9 | false
10 | false
11 | true
12 | $(NoWarn);NU5128;NU5127;NU5104
13 | Microsoft.Windows.CsWin32.nuspec
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | true
24 | build\
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | all
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/ModuleInitializerAttribute.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace System.Runtime.CompilerServices;
5 |
6 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
7 | internal sealed class ModuleInitializerAttribute : Attribute
8 | {
9 | }
10 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/NamespaceMetadata.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | ///
7 | /// An immutable index into metadata.
8 | ///
9 | ///
10 | /// This class must not contain definitions. It may contain handles. See devremarks for details.
11 | ///
12 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + ",nq}")]
13 | internal class NamespaceMetadata
14 | {
15 | internal NamespaceMetadata(string name)
16 | {
17 | this.Name = name;
18 | }
19 |
20 | public string Name { get; }
21 |
22 | public bool IsEmpty => this.Fields.Count == 0 && this.Methods.Count == 0 && this.Types.Count == 0;
23 |
24 | internal Dictionary Fields { get; } = new(StringComparer.Ordinal);
25 |
26 | internal Dictionary Methods { get; } = new(StringComparer.Ordinal);
27 |
28 | internal Dictionary Types { get; } = new(StringComparer.Ordinal);
29 |
30 | internal HashSet MethodsForOtherPlatform { get; } = new HashSet(StringComparer.Ordinal);
31 |
32 | internal HashSet TypesForOtherPlatform { get; } = new HashSet(StringComparer.Ordinal);
33 |
34 | private string DebuggerDisplay => $"{this.Name} (Constants: {this.Fields.Count}, Methods: {this.Methods.Count}, Types: {this.Types.Count}";
35 | }
36 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/PlatformIncompatibleException.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | ///
7 | /// An exception thrown when code generation fails because the requested type or member is not available given the target CPU architecture.
8 | ///
9 | [Serializable]
10 | public class PlatformIncompatibleException : GenerationFailedException
11 | {
12 | ///
13 | /// Initializes a new instance of the class.
14 | ///
15 | public PlatformIncompatibleException()
16 | {
17 | }
18 |
19 | ///
20 | /// Initializes a new instance of the class.
21 | ///
22 | ///
23 | public PlatformIncompatibleException(string message)
24 | : base(message)
25 | {
26 | }
27 |
28 | ///
29 | /// Initializes a new instance of the class.
30 | ///
31 | ///
32 | public PlatformIncompatibleException(string message, Exception inner)
33 | : base(message, inner)
34 | {
35 | }
36 |
37 | ///
38 | /// Initializes a new instance of the class.
39 | ///
40 | ///
41 | protected PlatformIncompatibleException(
42 | System.Runtime.Serialization.SerializationInfo info,
43 | System.Runtime.Serialization.StreamingContext context)
44 | : base(info, context)
45 | {
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/README.md:
--------------------------------------------------------------------------------
1 | # Automated generation of C# bindings for the Win32 API
2 |
3 | Get immediate access to the full Win32 API from C#, just by naming the APIs you require.
4 | Generated APIs will be accurate for your CPU architecture and target Windows version.
5 | All APIs are generated directly into your project, allowing you to ship without any additional runtime dependencies.
6 |
7 | Reach functionality that .NET doesn't expose via the Base Class Library (BCL) to give your library or application that feature that really sets it apart.
8 |
9 | Install this package, then create a NativeMethods.txt file with a list of any APIs you need for example:
10 |
11 | NativeMethods.txt:
12 |
13 | ```
14 | CreateFile
15 | IUIRibbon
16 | S_OK
17 | NTSTATUS
18 | IsPwrHibernateAllowed
19 | ISpellChecker
20 | ``````
21 |
22 | Any supporting APIs (e.g. enums, structs) are automatically generated when they are required by what you've directly asked for.
23 |
24 | Call extern methods through the `PInvoke` class
25 |
26 | ```cs
27 | using SafeHandle f = PInvoke.CreateFile(
28 | "some.txt",
29 | (uint)GENERIC_ACCESS_RIGHTS.GENERIC_READ,
30 | FILE_SHARE_MODE.FILE_SHARE_READ,
31 | lpSecurityAttributes: null,
32 | FILE_CREATION_DISPOSITION.CREATE_ALWAYS,
33 | FILE_FLAGS_AND_ATTRIBUTES.FILE_ATTRIBUTE_NORMAL,
34 | hTemplateFile: null);
35 | ```
36 |
37 | Learn more from [our README on GitHub](https://github.com/microsoft/CsWin32#readme).
38 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/Rental.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal struct Rental : IDisposable
7 | where T : class
8 | {
9 | private Action? disposeAction;
10 | private T? value;
11 | private object? state;
12 |
13 | internal Rental(T value, Action disposeAction, object? state)
14 | {
15 | this.value = value;
16 | this.disposeAction = disposeAction;
17 | this.state = state;
18 | }
19 |
20 | public T Value => this.value ?? throw new ObjectDisposedException(this.GetType().FullName);
21 |
22 | public void Dispose()
23 | {
24 | T? value = this.value;
25 | this.value = null;
26 | if (value is not null)
27 | {
28 | this.disposeAction?.Invoke(value, this.state);
29 | }
30 |
31 | this.disposeAction = null;
32 | this.state = null;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/TypeHandleInfo.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal abstract record TypeHandleInfo
7 | {
8 | private static readonly TypeSyntaxSettings DebuggerDisplaySettings = new TypeSyntaxSettings(null, PreferNativeInt: false, PreferMarshaledTypes: false, AllowMarshaling: false, QualifyNames: true);
9 |
10 | internal bool IsConstantField { get; init; }
11 |
12 | internal abstract TypeSyntaxAndMarshaling ToTypeSyntax(TypeSyntaxSettings inputs, Generator.GeneratingElement forElement, CustomAttributeHandleCollection? customAttributes, ParameterAttributes parameterAttributes = default);
13 |
14 | internal abstract bool? IsValueType(TypeSyntaxSettings inputs);
15 |
16 | protected static bool TryGetSimpleName(TypeSyntax nameSyntax, [NotNullWhen(true)] out string? simpleName)
17 | {
18 | if (nameSyntax is QualifiedNameSyntax qname)
19 | {
20 | simpleName = qname.Right.Identifier.ValueText;
21 | }
22 | else if (nameSyntax is SimpleNameSyntax simple)
23 | {
24 | simpleName = simple.Identifier.ValueText;
25 | }
26 | else
27 | {
28 | simpleName = null;
29 | return false;
30 | }
31 |
32 | return true;
33 | }
34 |
35 | protected TypeSyntax ToTypeSyntaxForDisplay() => this.ToTypeSyntax(DebuggerDisplaySettings, Generator.GeneratingElement.Other, null).Type;
36 |
37 | protected Generator.Context GetContext(TypeSyntaxSettings inputs) => inputs.Generator is not null
38 | ? inputs.Generator.DefaultContext with { AllowMarshaling = inputs.AllowMarshaling }
39 | : new() { AllowMarshaling = inputs.AllowMarshaling };
40 | }
41 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/TypeSyntaxSettings.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.CsWin32;
5 |
6 | internal record TypeSyntaxSettings(
7 | Generator? Generator,
8 | bool PreferNativeInt,
9 | bool PreferMarshaledTypes,
10 | bool AllowMarshaling,
11 | bool QualifyNames,
12 | bool IsField = false,
13 | bool PreferInOutRef = false,
14 | bool AvoidWinmdRootAlias = false)
15 | {
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/build/Microsoft.Windows.CsWin32.props:
--------------------------------------------------------------------------------
1 |
2 |
3 | true
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | @(ProjectionMetadataWinmd->'%(FullPath)','|')
24 | @(ProjectionDocs->'%(FullPath)','|')
25 | @(AppLocalAllowedLibraries->'%(FullPath)','|')
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/build/net20/Microsoft.Windows.CsWin32.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/build/netstandard1.0/Microsoft.Windows.CsWin32.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/readme.txt:
--------------------------------------------------------------------------------
1 | Microsoft Windows SDK Win32 API Source Generator
2 | ==================================================
3 |
4 | This package contains a source generator to add a user-defined set of Win32 P/Invoke
5 | methods and supporting types to a C# project.
6 |
7 | To get started, create a "NativeMethods.txt" file in your project directory
8 | that lists the names of Win32 APIs for which you need to have generated, one per line.
9 |
10 | You should also install the `System.Memory` package when targeting .NET Framework 4.5+ or .NET Standard 2.0,
11 | as that adds APIs that significantly improve much of the code generated by CsWin32:
12 |
13 | ```ps1
14 | dotnet add package System.Memory
15 | dotnet add package System.Runtime.CompilerServices.Unsafe
16 | ```
17 |
18 | Projects targeting .NET Core 2.1+ or .NET 5+ do *not* need to add these package references,
19 | although it is harmless to do so.
20 |
21 | Note that while the `System.Memory` package depends on the `System.Runtime.CompilerServices.Unsafe` package,
22 | referencing the latter directly is still important to get the latest version of the APIs it provides.
23 |
24 | Your project must allow unsafe code to support the generated code that will likely use pointers.
25 |
26 | Learn more from our README on GitHub: https://github.com/microsoft/CsWin32#readme
27 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 | indent_style = tab
3 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/BOOL.cs:
--------------------------------------------------------------------------------
1 | partial struct BOOL
2 | {
3 | internal BOOL(bool value) => this.Value = value ? 1 : 0;
4 | public static implicit operator bool(BOOL value) => value.Value != 0;
5 | public static implicit operator BOOL(bool value) => new BOOL(value);
6 | }
7 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/BOOLEAN.cs:
--------------------------------------------------------------------------------
1 | partial struct BOOLEAN
2 | {
3 | internal BOOLEAN(bool value) => this.Value = value ? (byte)1 : (byte)0;
4 | public static implicit operator bool(BOOLEAN value) => value.Value != 0;
5 | public static implicit operator BOOLEAN(bool value) => new BOOLEAN(value);
6 | }
7 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/BSTR.cs:
--------------------------------------------------------------------------------
1 | internal partial struct BSTR
2 | {
3 | ///
4 | /// Gets the length of the BSTR in characters.
5 | ///
6 | internal unsafe int Length => this.Value is null ? 0 : checked((int)(*(((uint*)this.Value) - 1) / sizeof(char)));
7 |
8 | public override string ToString() => this.Value != null ? Marshal.PtrToStringBSTR(new IntPtr(this.Value)) : null;
9 |
10 | #if canUseSpan
11 | public static unsafe implicit operator ReadOnlySpan(BSTR bstr) => bstr.Value != null ? new ReadOnlySpan(bstr.Value, *((int*)bstr.Value - 1) / 2) : default(ReadOnlySpan);
12 |
13 | internal ReadOnlySpan AsSpan() => this;
14 | #endif
15 | }
16 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/ComHelpers.cs:
--------------------------------------------------------------------------------
1 | internal static unsafe partial class ComHelpers
2 | {
3 | private static readonly winmdroot.Foundation.HRESULT COR_E_OBJECTDISPOSED = (winmdroot.Foundation.HRESULT)unchecked((int)0x80131622);
4 | private static readonly winmdroot.Foundation.HRESULT S_OK = (winmdroot.Foundation.HRESULT)0;
5 |
6 | internal static winmdroot.Foundation.HRESULT UnwrapCCW(TThis* @this, out TInterface @object)
7 | where TThis : unmanaged
8 | where TInterface : class
9 | {
10 | @object = ComWrappers.ComInterfaceDispatch.GetInstance((ComWrappers.ComInterfaceDispatch*)@this);
11 | return @object is null ? COR_E_OBJECTDISPOSED : S_OK;
12 | }
13 |
14 | #if canUseInterfaceStaticMembers
15 | internal static void PopulateIUnknown(System.Com.IUnknown.Vtbl* vtable)
16 | where TComInterface : unmanaged
17 | {
18 | PopulateIUnknownImpl(vtable);
19 | if (vtable->QueryInterface_1 is null)
20 | {
21 | throw new NotImplementedException("v-tables cannot be accessed unless the Windows.Win32.ComHelpers.PopulateIUnknownImpl partial method is implemented.");
22 | }
23 | }
24 |
25 | static partial void PopulateIUnknownImpl(System.Com.IUnknown.Vtbl* vtable)
26 | where TComInterface : unmanaged;
27 | #endif
28 | }
29 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/DECIMAL.cs:
--------------------------------------------------------------------------------
1 | internal partial struct DECIMAL
2 | {
3 | public DECIMAL(decimal value)
4 | {
5 | unchecked
6 | {
7 | const int SignMask = (int)0x80000000;
8 | #if NET5_0_OR_GREATER
9 | Span bits = stackalloc int[4];
10 | decimal.GetBits(value, bits);
11 | #else
12 | int[] bits = decimal.GetBits(value);
13 | #endif
14 | uint lo32 = (uint)bits[0];
15 | uint mid32 = (uint)bits[1];
16 | uint hi32 = (uint)bits[2];
17 | byte scale = (byte)(bits[3] >> 16);
18 | byte sign = (bits[3] & SignMask) == SignMask ? (byte)0x80 : (byte)0x00;
19 | this.Anonymous2 = new _Anonymous2_e__Union() { Anonymous = new _Anonymous2_e__Union._Anonymous_e__Struct() { Lo32 = lo32, Mid32 = mid32 } };
20 | this.Hi32 = hi32;
21 | this.Anonymous1 = new _Anonymous1_e__Union() { Anonymous = new _Anonymous1_e__Union._Anonymous_e__Struct() { scale = scale, sign = sign } };
22 | this.wReserved = 0;
23 | }
24 | }
25 |
26 | public static implicit operator decimal(DECIMAL value)
27 | {
28 | return new decimal(
29 | (int)value.Anonymous2.Anonymous.Lo32,
30 | (int)value.Anonymous2.Anonymous.Mid32,
31 | (int)value.Hi32,
32 | value.Anonymous1.Anonymous.sign == 0x80,
33 | value.Anonymous1.Anonymous.scale);
34 | }
35 |
36 | #if NET5_0_OR_GREATER
37 | public static implicit operator DECIMAL(decimal value) => new DECIMAL(value);
38 | #endif
39 | }
40 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/IUnknownHelperMethods.cs:
--------------------------------------------------------------------------------
1 | internal class IUnknownHelperMethods
2 | {
3 | internal unsafe global::Windows.Win32.Foundation.HRESULT QueryInterface(out T* ppv)
4 | where T : unmanaged
5 | {
6 | Guid guid = typeof(T).GUID;
7 | void* pv;
8 | var hr = this.QueryInterface(&guid, &pv);
9 | if (hr.Succeeded)
10 | {
11 | ppv = (T*)pv;
12 | }
13 | else
14 | {
15 | ppv = null;
16 | }
17 |
18 | return hr;
19 | }
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/IVTable.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// Non generic interface that allows constraining against a COM wrapper type directly. COM structs should
3 | /// implement .
4 | ///
5 | internal unsafe interface IVTable
6 | {
7 | static abstract System.Com.IUnknown.Vtbl* VTable { get; }
8 | }
9 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/IVTable`2.cs:
--------------------------------------------------------------------------------
1 | internal unsafe interface IVTable : IVTable
2 | where TVTable : unmanaged
3 | where TComInterface : unmanaged, IVTable
4 | {
5 | private protected static abstract void PopulateVTable(TVTable* vtable);
6 |
7 | static System.Com.IUnknown.Vtbl* IVTable.VTable { get; } = (System.Com.IUnknown.Vtbl*)CreateVTable();
8 |
9 | private static TVTable* CreateVTable()
10 | {
11 | TVTable* vtbl = (TVTable*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(TVTable), sizeof(TVTable));
12 | ComHelpers.PopulateIUnknown((System.Com.IUnknown.Vtbl*)vtbl);
13 | TComInterface.PopulateVTable(vtbl);
14 | return vtbl;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/NTSTATUS.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// Win32 return error codes.
3 | ///
4 | ///
5 | /// This values come from https://msdn.microsoft.com/en-us/library/cc704588.aspx
6 | /// Values are 32 bit values laid out as follows:
7 | /// 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
8 | /// 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
9 | /// +---+-+-+-----------------------+-------------------------------+
10 | /// |Sev|C|R| Facility | Code |
11 | /// +---+-+-+-----------------------+-------------------------------+
12 | /// where
13 | /// Sev - is the severity code
14 | /// 00 - Success
15 | /// 01 - Informational
16 | /// 10 - Warning
17 | /// 11 - Error
18 | /// C - is the Customer code flag
19 | /// R - is a reserved bit
20 | /// Facility - is the facility code
21 | /// Code - is the facility's status code
22 | ///
23 | /// FacilityCodes 0x5 - 0xF have been allocated by various drivers.
24 | /// The success status codes 0 - 63 are reserved for wait completion status.
25 | ///
26 | partial struct NTSTATUS
27 | {
28 | public static implicit operator uint(NTSTATUS value) => (uint)value.Value;
29 | public static explicit operator NTSTATUS(uint value) => new NTSTATUS((int)value);
30 |
31 | internal Severity SeverityCode => (Severity)(((uint)this.Value & 0xc0000000) >> 30);
32 |
33 | internal enum Severity
34 | {
35 | Success,
36 | Informational,
37 | Warning,
38 | Error,
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/OverloadResolutionPriorityAttribute.cs:
--------------------------------------------------------------------------------
1 | namespace System.Runtime.CompilerServices
2 | {
3 | ///
4 | /// Specifies the priority of a member in overload resolution.
5 | /// When unspecified, the default priority is 0.
6 | ///
7 | [global::System.AttributeUsage(global::System.AttributeTargets.Constructor | global::System.AttributeTargets.Method | global::System.AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
8 | internal sealed class OverloadResolutionPriorityAttribute : global::System.Attribute
9 | {
10 | ///
11 | /// Initializes a new instance of the class.
12 | ///
13 | /// The priority of the attributed member. Higher numbers are prioritized, lower numbers are deprioritized. 0 is the default if no attribute is present.
14 | public OverloadResolutionPriorityAttribute(int priority)
15 | {
16 | this.Priority = priority;
17 | }
18 |
19 | ///
20 | /// The priority of the member.
21 | ///
22 | public int Priority { get; }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PCSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to a null-terminated, constant, ANSI character string.
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | internal unsafe readonly partial struct PCSTR
6 | : IEquatable
7 | {
8 | ///
9 | /// A pointer to the first character in the string. The content should be considered readonly, as it was typed as constant in the SDK.
10 | ///
11 | internal readonly byte* Value;
12 | internal PCSTR(byte* value) => this.Value = value;
13 | public static implicit operator byte*(PCSTR value) => value.Value;
14 | public static explicit operator PCSTR(byte* value) => new PCSTR(value);
15 | public bool Equals(PCSTR other) => this.Value == other.Value;
16 | public override bool Equals(object obj) => obj is PCSTR other && this.Equals(other);
17 | public override int GetHashCode() => unchecked((int)this.Value);
18 |
19 | ///
20 | /// Gets the number of characters up to the first null character (exclusive).
21 | ///
22 | internal int Length
23 | {
24 | get
25 | {
26 | byte* p = this.Value;
27 | if (p is null)
28 | return 0;
29 | while (*p != 0)
30 | p++;
31 | return checked((int)(p - this.Value));
32 | }
33 | }
34 |
35 | ///
36 | /// Returns a with a copy of this character array, decoding as UTF-8.
37 | ///
38 | /// A , or if is .
39 | public override string ToString() => this.Value is null ? null : new string((sbyte*)this.Value, 0, this.Length, global::System.Text.Encoding.Default);
40 |
41 | #if canUseSpan
42 | ///
43 | /// Returns a span of the characters in this string, up to the first null character (exclusive).
44 | ///
45 | internal ReadOnlySpan AsSpan() => this.Value is null ? default(ReadOnlySpan) : new ReadOnlySpan(this.Value, this.Length);
46 | #endif
47 |
48 | private string DebuggerDisplay => this.ToString();
49 | }
50 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PCWSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to a null-terminated, constant character string.
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | internal unsafe readonly partial struct PCWSTR
6 | : IEquatable
7 | {
8 | ///
9 | /// A pointer to the first character in the string. The content should be considered readonly, as it was typed as constant in the SDK.
10 | ///
11 | internal readonly char* Value;
12 | internal PCWSTR(char* value) => this.Value = value;
13 | public static explicit operator char*(PCWSTR value) => value.Value;
14 | public static implicit operator PCWSTR(char* value) => new PCWSTR(value);
15 | public bool Equals(PCWSTR other) => this.Value == other.Value;
16 | public override bool Equals(object obj) => obj is PCWSTR other && this.Equals(other);
17 | public override int GetHashCode() => unchecked((int)this.Value);
18 |
19 | ///
20 | /// Gets the number of characters up to the first null character (exclusive).
21 | ///
22 | internal int Length
23 | {
24 | get
25 | {
26 | char* p = this.Value;
27 | if (p is null)
28 | return 0;
29 | while (*p != '\0')
30 | p++;
31 | return checked((int)(p - this.Value));
32 | }
33 | }
34 |
35 | ///
36 | /// Returns a with a copy of this character array, up to the first null character (exclusive).
37 | ///
38 | /// A , or if is .
39 | public override string ToString() => this.Value is null ? null : new string(this.Value);
40 |
41 | #if canUseSpan
42 | ///
43 | /// Returns a span of the characters in this string, up to the first null character (exclusive).
44 | ///
45 | internal ReadOnlySpan AsSpan() => this.Value is null ? default(ReadOnlySpan) : new ReadOnlySpan(this.Value, this.Length);
46 | #endif
47 |
48 | private string DebuggerDisplay => this.ToString();
49 | }
50 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PCZZSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to a constant, empty-string terminated list of null-terminated strings with 1-byte characters (often UTF-8).
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | internal unsafe readonly partial struct PCZZSTR
6 | : IEquatable
7 | {
8 | ///
9 | /// A pointer to the first character in the string. The content should be considered readonly, as it was typed as constant in the SDK.
10 | ///
11 | internal readonly byte* Value;
12 | internal PCZZSTR(byte* value) => this.Value = value;
13 | public static implicit operator byte*(PCZZSTR value) => value.Value;
14 | public static explicit operator PCZZSTR(byte* value) => new PCZZSTR(value);
15 | public bool Equals(PCZZSTR other) => this.Value == other.Value;
16 | public override bool Equals(object obj) => obj is PCZZSTR other && this.Equals(other);
17 | public override int GetHashCode() => unchecked((int)this.Value);
18 |
19 | ///
20 | /// Gets the number of characters in this null-terminated string list, excluding the final null terminator.
21 | ///
22 | internal int Length
23 | {
24 | get
25 | {
26 | PCSTR str = new PCSTR(this.Value);
27 | while (true)
28 | {
29 | int len = str.Length;
30 | if (len > 0)
31 | {
32 | str = new PCSTR(str.Value + len + 1);
33 | }
34 | else
35 | {
36 | break;
37 | }
38 | }
39 |
40 | return checked((int)(str.Value - this.Value));
41 | }
42 | }
43 |
44 | ///
45 | /// Returns a with a copy of this character array, decoding as UTF-8.
46 | ///
47 | /// A , or if is .
48 | public override string ToString() => this.Value is null ? null : new string((sbyte*)this.Value, 0, this.Length, global::System.Text.Encoding.Default);
49 |
50 | #if canUseSpan
51 | ///
52 | /// Returns a span of the characters in this string.
53 | ///
54 | internal ReadOnlySpan AsSpan() => this.Value is null ? default(ReadOnlySpan) : new ReadOnlySpan(this.Value, this.Length);
55 | #endif
56 |
57 | private string DebuggerDisplay => this.ToString();
58 | }
59 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PCZZWSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to a constant, empty-string terminated list of null-terminated strings that uses UTF-16 encoding.
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | internal unsafe readonly partial struct PCZZWSTR
6 | : IEquatable
7 | {
8 | ///
9 | /// A pointer to the first character in the string. The content should be considered readonly, as it was typed as constant in the SDK.
10 | ///
11 | internal readonly char* Value;
12 | internal PCZZWSTR(char* value) => this.Value = value;
13 | public static explicit operator char*(PCZZWSTR value) => value.Value;
14 | public static implicit operator PCZZWSTR(char* value) => new PCZZWSTR(value);
15 | public bool Equals(PCZZWSTR other) => this.Value == other.Value;
16 | public override bool Equals(object obj) => obj is PCZZWSTR other && this.Equals(other);
17 | public override int GetHashCode() => unchecked((int)this.Value);
18 |
19 | ///
20 | /// Gets the number of characters in this null-terminated string list, excluding the final null terminator.
21 | ///
22 | internal int Length
23 | {
24 | get
25 | {
26 | PCWSTR str = new PCWSTR(this.Value);
27 | while (true)
28 | {
29 | int len = str.Length;
30 | if (len > 0)
31 | {
32 | str = new PCWSTR(str.Value + len + 1);
33 | }
34 | else
35 | {
36 | break;
37 | }
38 | }
39 |
40 | return checked((int)(str.Value - this.Value));
41 | }
42 | }
43 |
44 | ///
45 | /// Returns a with a copy of this character array.
46 | ///
47 | /// A , or if is .
48 | public override string ToString() => this.Value is null ? null : new string(this.Value, 0, this.Length);
49 |
50 | #if canUseSpan
51 | ///
52 | /// Returns a span of the characters in this string.
53 | ///
54 | internal ReadOnlySpan AsSpan() => this.Value is null ? default(ReadOnlySpan) : new ReadOnlySpan(this.Value, this.Length);
55 | #endif
56 |
57 | private string DebuggerDisplay => this.ToString();
58 | }
59 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PInvokeClassHelperMethods.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// This class wrapper is stripped so that individual helper methods may be injected into the generated PInvoke class.
3 | ///
4 | internal class PInvokeClassHelperMethods
5 | {
6 | private static void EnsureNullTerminated(Span buffer, string parameterName)
7 | {
8 | if (buffer != null && buffer.LastIndexOf('\0') == -1)
9 | {
10 | throw new ArgumentException("Required null terminator is missing.", parameterName);
11 | }
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to a null-terminated, ANSI character string.
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | partial struct PSTR
6 | {
7 | public static implicit operator PCSTR(PSTR value) => new PCSTR(value.Value);
8 |
9 | ///
10 | internal int Length => new PCSTR(this.Value).Length;
11 |
12 | ///
13 | public override string ToString() => new PCSTR(this.Value).ToString();
14 |
15 | #if canUseSpan
16 | ///
17 | /// Returns a span of the characters in this string, up to the first null character (exclusive).
18 | ///
19 | internal Span AsSpan() => this.Value is null ? default(Span) : new Span(this.Value, this.Length);
20 | #endif
21 |
22 | private string DebuggerDisplay => this.ToString();
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PWSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to a null-terminated character string.
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | partial struct PWSTR
6 | {
7 | public static implicit operator PCWSTR(PWSTR value) => new PCWSTR(value.Value);
8 |
9 | ///
10 | internal int Length => new PCWSTR(this.Value).Length;
11 |
12 | ///
13 | public override string ToString() => new PCWSTR(this.Value).ToString();
14 |
15 | #if canUseSpan
16 | ///
17 | /// Returns a span of the characters in this string, up to the first null character (exclusive).
18 | ///
19 | internal Span AsSpan() => this.Value is null ? default(Span) : new Span(this.Value, this.Length);
20 | #endif
21 |
22 | private string DebuggerDisplay => this.ToString();
23 | }
24 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PZZSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to an empty-string terminated list of null-terminated strings with 1-byte characters (often UTF-8).
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | internal unsafe readonly partial struct PZZSTR
6 | : IEquatable
7 | {
8 | ///
9 | /// A pointer to the first character in the string.
10 | ///
11 | internal readonly byte* Value;
12 | internal PZZSTR(byte* value) => this.Value = value;
13 | public static implicit operator byte*(PZZSTR value) => value.Value;
14 | public static explicit operator PZZSTR(byte* value) => new PZZSTR(value);
15 | public static implicit operator PCZZSTR(PZZSTR value) => new PCZZSTR(value.Value);
16 | public bool Equals(PZZSTR other) => this.Value == other.Value;
17 | public override bool Equals(object obj) => obj is PZZSTR other && this.Equals(other);
18 | public override int GetHashCode() => unchecked((int)this.Value);
19 |
20 | ///
21 | internal int Length => new PCZZSTR(this.Value).Length;
22 |
23 | ///
24 | public override string ToString() => new PCZZSTR(this.Value).ToString();
25 |
26 | #if canUseSpan
27 | ///
28 | /// Returns a span of the characters in this string.
29 | ///
30 | internal Span AsSpan() => this.Value is null ? default(Span) : new Span(this.Value, this.Length);
31 | #endif
32 |
33 | private string DebuggerDisplay => this.ToString();
34 | }
35 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/PZZWSTR.cs:
--------------------------------------------------------------------------------
1 | ///
2 | /// A pointer to an empty-string terminated list of null-terminated strings that uses UTF-16 encoding.
3 | ///
4 | [DebuggerDisplay("{" + nameof(DebuggerDisplay) + "}")]
5 | internal unsafe readonly partial struct PZZWSTR
6 | : IEquatable
7 | {
8 | ///
9 | /// A pointer to the first character in the string.
10 | ///
11 | internal readonly char* Value;
12 | internal PZZWSTR(char* value) => this.Value = value;
13 | public static explicit operator char*(PZZWSTR value) => value.Value;
14 | public static implicit operator PZZWSTR(char* value) => new PZZWSTR(value);
15 | public static implicit operator PCZZWSTR(PZZWSTR value) => new PCZZWSTR(value.Value);
16 | public bool Equals(PZZWSTR other) => this.Value == other.Value;
17 | public override bool Equals(object obj) => obj is PZZWSTR other && this.Equals(other);
18 | public override int GetHashCode() => unchecked((int)this.Value);
19 |
20 | ///
21 | internal int Length => new PCZZWSTR(this.Value).Length;
22 |
23 | ///
24 | public override string ToString() => new PCZZWSTR(this.Value).ToString();
25 |
26 | #if canUseSpan
27 | ///
28 | /// Returns a span of the characters in this string.
29 | ///
30 | internal Span AsSpan() => this.Value is null ? default(Span) : new Span(this.Value, this.Length);
31 | #endif
32 |
33 | private string DebuggerDisplay => this.ToString();
34 | }
35 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/RECT.cs:
--------------------------------------------------------------------------------
1 | partial struct RECT
2 | {
3 | #if canUseSystemDrawing
4 | internal RECT(global::System.Drawing.Rectangle value) :
5 | this(value.Left, value.Top, value.Right, value.Bottom) { }
6 | internal RECT(global::System.Drawing.Point location, global::System.Drawing.Size size) :
7 | this(location.X, location.Y, unchecked(location.X + size.Width), unchecked(location.Y + size.Height)) { }
8 | #endif
9 | internal RECT(int left, int top, int right, int bottom)
10 | {
11 | this.left = left;
12 | this.top = top;
13 | this.right = right;
14 | this.bottom = bottom;
15 | }
16 |
17 | internal static RECT FromXYWH(int x, int y, int width, int height) =>
18 | new RECT(x, y, unchecked(x + width), unchecked(y + height));
19 | internal readonly int Width => unchecked(this.right - this.left);
20 | internal readonly int Height => unchecked(this.bottom - this.top);
21 | internal readonly bool IsEmpty => this.left == 0 && this.top == 0 && this.right == 0 && this.bottom == 0;
22 | internal readonly int X => this.left;
23 | internal readonly int Y => this.top;
24 | #if canUseSystemDrawing
25 | internal readonly global::System.Drawing.Size Size => new global::System.Drawing.Size(this.Width, this.Height);
26 | public static implicit operator global::System.Drawing.Rectangle(RECT value) => new global::System.Drawing.Rectangle(value.left, value.top, value.Width, value.Height);
27 | public static implicit operator global::System.Drawing.RectangleF(RECT value) => new global::System.Drawing.RectangleF(value.left, value.top, value.Width, value.Height);
28 | public static implicit operator RECT(global::System.Drawing.Rectangle value) => new RECT(value);
29 | #endif
30 | }
31 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/SIZE.cs:
--------------------------------------------------------------------------------
1 | partial struct SIZE
2 | {
3 | #if canUseSystemDrawing
4 | internal SIZE(global::System.Drawing.Size value) : this(value.Width, value.Height) { }
5 | #endif
6 | internal SIZE(int width, int height)
7 | {
8 | this.cx = width;
9 | this.cy = height;
10 | }
11 |
12 | internal readonly int Width => this.cx;
13 | internal readonly int Height => this.cy;
14 | internal readonly bool IsEmpty => this.cx == 0 && this.cy == 0;
15 | #if canUseSystemDrawing
16 | public static implicit operator global::System.Drawing.Size(SIZE value) => new global::System.Drawing.Size(value.cx, value.cy);
17 | public static implicit operator SIZE(global::System.Drawing.Size value) => new SIZE(value);
18 | #endif
19 | }
20 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/SYSTEMTIME.cs:
--------------------------------------------------------------------------------
1 | partial struct SYSTEMTIME
2 | : IEquatable
3 | {
4 | public bool Equals(SYSTEMTIME other) => this.wYear == other.wYear && this.wMonth == other.wMonth && this.wDayOfWeek == other.wDayOfWeek && this.wDay == other.wDay && this.wHour == other.wHour && this.wMinute == other.wMinute && this.wSecond == other.wSecond && this.wMilliseconds == other.wMilliseconds;
5 | public override bool Equals(object obj) => obj is SYSTEMTIME other && this.Equals(other);
6 | public override int GetHashCode() => (this.wYear, this.wMonth, this.wDayOfWeek, this.wDay, this.wHour, this.wMinute, this.wSecond, this.wMilliseconds).GetHashCode();
7 | public static bool operator ==(SYSTEMTIME d1, SYSTEMTIME d2) => d1.Equals(d2);
8 | public static bool operator !=(SYSTEMTIME d1, SYSTEMTIME d2) => !(d1 == d2);
9 |
10 | public static explicit operator global::System.DateTime(SYSTEMTIME sysTime)
11 | {
12 | if (sysTime == default)
13 | {
14 | return default;
15 | }
16 |
17 | return new global::System.DateTime(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
18 | }
19 |
20 | public static explicit operator SYSTEMTIME(global::System.DateTime time)
21 | {
22 | if (time == default)
23 | {
24 | return default;
25 | }
26 |
27 | checked
28 | {
29 | return new SYSTEMTIME
30 | {
31 | wYear = (ushort)time.Year,
32 | wMonth = (ushort)time.Month,
33 | wDayOfWeek = (ushort)time.DayOfWeek,
34 | wDay = (ushort)time.Day,
35 | wHour = (ushort)time.Hour,
36 | wMinute = (ushort)time.Minute,
37 | wSecond = (ushort)time.Second,
38 | wMilliseconds = (ushort)time.Millisecond,
39 | };
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/VARIANT_BOOL.cs:
--------------------------------------------------------------------------------
1 | partial struct VARIANT_BOOL
2 | {
3 | internal VARIANT_BOOL(bool value) => this.Value = value ? VARIANT_TRUE : VARIANT_FALSE;
4 | public static implicit operator bool(VARIANT_BOOL value) => value != VARIANT_FALSE;
5 | public static implicit operator VARIANT_BOOL(bool value) => value ? VARIANT_TRUE : VARIANT_FALSE;
6 | }
7 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/VariableLengthInlineArray`1.cs:
--------------------------------------------------------------------------------
1 | internal struct VariableLengthInlineArray
2 | where T : unmanaged
3 | {
4 | internal T e0;
5 |
6 | #if canUseUnscopedRef
7 |
8 | #if canUseUnsafeAdd
9 | internal ref T this[int index]
10 | {
11 | [UnscopedRef]
12 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
13 | get => ref Unsafe.Add(ref this.e0, index);
14 | }
15 | #endif
16 |
17 | #if canUseSpan
18 | [UnscopedRef]
19 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
20 | internal Span AsSpan(int length)
21 | {
22 | #if canCallCreateSpan
23 | return MemoryMarshal.CreateSpan(ref this.e0, length);
24 | #else
25 | unsafe
26 | {
27 | fixed (void* p = &this.e0)
28 | {
29 | return new Span(p, length);
30 | }
31 | }
32 | #endif
33 | }
34 | #endif
35 |
36 | #endif
37 | }
38 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/VariableLengthInlineArray`2.cs:
--------------------------------------------------------------------------------
1 | internal struct VariableLengthInlineArray
2 | where T : unmanaged
3 | where TBlittable : unmanaged
4 | {
5 | #if canUseUnscopedRef
6 | private TBlittable _e0;
7 |
8 | [UnscopedRef]
9 | internal ref T e0 => ref Unsafe.As(ref this._e0);
10 |
11 | #if canUseUnsafeAdd
12 | internal ref T this[int index]
13 | {
14 | [UnscopedRef]
15 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
16 | get => ref Unsafe.Add(ref this.e0, index);
17 | }
18 | #endif
19 |
20 | #if canUseSpan
21 | [UnscopedRef]
22 | [MethodImpl(MethodImplOptions.AggressiveInlining)]
23 | internal Span AsSpan(int length)
24 | {
25 | #if canCallCreateSpan
26 | return MemoryMarshal.CreateSpan(ref this.e0, length);
27 | #else
28 | unsafe
29 | {
30 | fixed (void* p = &this.e0)
31 | {
32 | return new Span(p, length);
33 | }
34 | }
35 | #endif
36 | }
37 | #endif
38 |
39 | #else
40 | internal TBlittable e0;
41 | #endif
42 | }
43 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/WinRTCustomMarshaler.cs:
--------------------------------------------------------------------------------
1 | namespace Windows.Win32.CsWin32.InteropServices
2 | {
3 | internal class WinRTCustomMarshaler : global::System.Runtime.InteropServices.ICustomMarshaler
4 | {
5 | private string winrtClassName;
6 | private bool lookedForFromAbi;
7 | private global::System.Reflection.MethodInfo fromAbi;
8 |
9 | private WinRTCustomMarshaler(string cookie)
10 | {
11 | this.winrtClassName = cookie;
12 | }
13 |
14 | ///
15 | /// Gets an instance of the marshaler given a cookie
16 | ///
17 | /// Cookie used to create marshaler
18 | /// Marshaler
19 | public static global::System.Runtime.InteropServices.ICustomMarshaler GetInstance(string cookie)
20 | {
21 | return new WinRTCustomMarshaler(cookie);
22 | }
23 |
24 | void global::System.Runtime.InteropServices.ICustomMarshaler.CleanUpManagedData(object ManagedObj)
25 | {
26 | }
27 |
28 | void global::System.Runtime.InteropServices.ICustomMarshaler.CleanUpNativeData(global::System.IntPtr pNativeData)
29 | {
30 | global::System.Runtime.InteropServices.Marshal.Release(pNativeData);
31 | }
32 |
33 | int global::System.Runtime.InteropServices.ICustomMarshaler.GetNativeDataSize()
34 | {
35 | throw new global::System.NotImplementedException();
36 | }
37 |
38 | global::System.IntPtr global::System.Runtime.InteropServices.ICustomMarshaler.MarshalManagedToNative(object ManagedObj)
39 | {
40 | throw new global::System.NotImplementedException();
41 | }
42 |
43 | object global::System.Runtime.InteropServices.ICustomMarshaler.MarshalNativeToManaged(global::System.IntPtr pNativeData)
44 | {
45 | if (!this.lookedForFromAbi)
46 | {
47 | var assembly = typeof(global::Windows.Foundation.IMemoryBuffer).Assembly;
48 | var type = global::System.Type.GetType($"{this.winrtClassName}, {assembly.FullName}");
49 |
50 | this.fromAbi = type.GetMethod("FromAbi");
51 | this.lookedForFromAbi = true;
52 | }
53 |
54 | if (this.fromAbi != null)
55 | {
56 | return this.fromAbi.Invoke(null, new object[] { pNativeData });
57 | }
58 | else
59 | {
60 | return global::System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(pNativeData);
61 | }
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/marshaling/CoCreateInstance.cs:
--------------------------------------------------------------------------------
1 | ///
2 | internal static unsafe global::Windows.Win32.Foundation.HRESULT CoCreateInstance(in Guid rclsid, object pUnkOuter, global::Windows.Win32.System.Com.CLSCTX dwClsContext, out T ppv)
3 | where T : class
4 | {
5 | global::Windows.Win32.Foundation.HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, typeof(T).GUID, out object o);
6 | ppv = (T)o;
7 | return hr;
8 | }
9 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/templates/no_marshaling/CoCreateInstance.cs:
--------------------------------------------------------------------------------
1 | ///
2 | internal static unsafe global::Windows.Win32.Foundation.HRESULT CoCreateInstance(in Guid rclsid, global::Windows.Win32.System.Com.IUnknown* pUnkOuter, global::Windows.Win32.System.Com.CLSCTX dwClsContext, out T* ppv)
3 | where T : unmanaged
4 | {
5 | global::Windows.Win32.Foundation.HRESULT hr = CoCreateInstance(rclsid, pUnkOuter, dwClsContext, typeof(T).GUID, out void* o);
6 | ppv = (T*)o;
7 | return hr;
8 | }
9 |
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/tools/install.ps1:
--------------------------------------------------------------------------------
1 | param($installPath, $toolsPath, $package, $project)
2 |
3 | $analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve
4 |
5 | foreach($analyzersPath in $analyzersPaths)
6 | {
7 | # Install the language agnostic analyzers.
8 | if (Test-Path $analyzersPath)
9 | {
10 | foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll)
11 | {
12 | if($project.Object.AnalyzerReferences)
13 | {
14 | $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
15 | }
16 | }
17 | }
18 | }
19 |
20 | # $project.Type gives the language name like (C# or VB.NET)
21 | $languageFolder = ""
22 | if($project.Type -eq "C#")
23 | {
24 | $languageFolder = "cs"
25 | }
26 | if($project.Type -eq "VB.NET")
27 | {
28 | $languageFolder = "vb"
29 | }
30 | if($languageFolder -eq "")
31 | {
32 | return
33 | }
34 |
35 | foreach($analyzersPath in $analyzersPaths)
36 | {
37 | # Install language specific analyzers.
38 | $languageAnalyzersPath = join-path $analyzersPath $languageFolder
39 | if (Test-Path $languageAnalyzersPath)
40 | {
41 | foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll)
42 | {
43 | if($project.Object.AnalyzerReferences)
44 | {
45 | $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName)
46 | }
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/tools/uninstall.ps1:
--------------------------------------------------------------------------------
1 | param($installPath, $toolsPath, $package, $project)
2 |
3 | $analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve
4 |
5 | foreach($analyzersPath in $analyzersPaths)
6 | {
7 | # Uninstall the language agnostic analyzers.
8 | if (Test-Path $analyzersPath)
9 | {
10 | foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll)
11 | {
12 | if($project.Object.AnalyzerReferences)
13 | {
14 | $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
15 | }
16 | }
17 | }
18 | }
19 |
20 | # $project.Type gives the language name like (C# or VB.NET)
21 | $languageFolder = ""
22 | if($project.Type -eq "C#")
23 | {
24 | $languageFolder = "cs"
25 | }
26 | if($project.Type -eq "VB.NET")
27 | {
28 | $languageFolder = "vb"
29 | }
30 | if($languageFolder -eq "")
31 | {
32 | return
33 | }
34 |
35 | foreach($analyzersPath in $analyzersPaths)
36 | {
37 | # Uninstall language specific analyzers.
38 | $languageAnalyzersPath = join-path $analyzersPath $languageFolder
39 | if (Test-Path $languageAnalyzersPath)
40 | {
41 | foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll)
42 | {
43 | if($project.Object.AnalyzerReferences)
44 | {
45 | try
46 | {
47 | $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName)
48 | }
49 | catch
50 | {
51 |
52 | }
53 | }
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/Microsoft.Windows.CsWin32/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "inherit": true,
3 | "assemblyVersion": {
4 | "precision": "revision"
5 | }
6 | }
--------------------------------------------------------------------------------
/src/OptProf.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | IBC
5 | Common7\IDE\PrivateAssemblies\$(TargetFileName)
6 | /ExeConfig:"%VisualStudio.InstallationUnderTest.Path%\Common7\IDE\vsn.exe"
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/VSInsertionMetadata/Library.VSInsertionMetadata.proj:
--------------------------------------------------------------------------------
1 |
2 |
3 | netstandard2.0
4 | true
5 | $(RepoRootPath)bin\Packages\$(Configuration)\VSRepo\
6 | false
7 | false
8 | Contains metadata for insertion into VS.
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/VSInsertionMetadata/ProfilingInputs.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/stylecop.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/DotNetAnalyzers/StyleCopAnalyzers/master/StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json",
3 | "settings": {
4 | "documentationRules": {
5 | "companyName": "Microsoft Corporation",
6 | "copyrightText": "Copyright (c) {companyName}. All rights reserved.\nLicensed under the {licenseName} license. See {licenseFile} file in the project root for full license information.",
7 | "variables": {
8 | "licenseName": "MIT",
9 | "licenseFile": "LICENSE"
10 | },
11 | "fileNamingConvention": "metadata",
12 | "xmlHeader": false
13 | },
14 | "orderingRules": {
15 | "usingDirectivesPlacement": "outsideNamespace"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/test/.editorconfig:
--------------------------------------------------------------------------------
1 | [*.cs]
2 |
3 | # SA1600: Elements should be documented
4 | dotnet_diagnostic.SA1600.severity = silent
5 |
6 | # SA1601: Partial elements should be documented
7 | dotnet_diagnostic.SA1601.severity = silent
8 |
9 | # SA1602: Enumeration items should be documented
10 | dotnet_diagnostic.SA1602.severity = silent
11 |
12 | # SA1615: Element return value should be documented
13 | dotnet_diagnostic.SA1615.severity = silent
14 |
15 | # VSTHRD103: Call async methods when in an async method
16 | dotnet_diagnostic.VSTHRD103.severity = silent
17 |
18 | # VSTHRD111: Use .ConfigureAwait(bool)
19 | dotnet_diagnostic.VSTHRD111.severity = none
20 |
21 | # VSTHRD200: Use Async suffix for async methods
22 | dotnet_diagnostic.VSTHRD200.severity = silent
23 |
24 | # CA1014: Mark assemblies with CLSCompliant
25 | dotnet_diagnostic.CA1014.severity = none
26 |
27 | # CA1050: Declare types in namespaces
28 | dotnet_diagnostic.CA1050.severity = none
29 |
30 | # CA1303: Do not pass literals as localized parameters
31 | dotnet_diagnostic.CA1303.severity = none
32 |
33 | # CS1591: Missing XML comment for publicly visible type or member
34 | dotnet_diagnostic.CS1591.severity = silent
35 |
36 | # CA1707: Identifiers should not contain underscores
37 | dotnet_diagnostic.CA1707.severity = silent
38 |
39 | # CA1062: Validate arguments of public methods
40 | dotnet_diagnostic.CA1062.severity = suggestion
41 |
42 | # CA1063: Implement IDisposable Correctly
43 | dotnet_diagnostic.CA1063.severity = silent
44 |
45 | # CA1816: Dispose methods should call SuppressFinalize
46 | dotnet_diagnostic.CA1816.severity = silent
47 |
48 | # CA2007: Consider calling ConfigureAwait on the awaited task
49 | dotnet_diagnostic.CA2007.severity = none
50 |
51 | # SA1310: Field names should not contain underscore
52 | dotnet_diagnostic.SA1310.severity = silent
53 |
54 | # SA1133: Do not combine attributes
55 | dotnet_diagnostic.SA1133.severity = silent
56 |
57 | # SA1401: Fields should be private
58 | dotnet_diagnostic.SA1401.severity = silent
59 |
60 | # SA1133: Do not combine attributes
61 | dotnet_diagnostic.SA1133.severity = silent
62 |
63 | # SA1611: Element parameters should be documented
64 | dotnet_diagnostic.SA1611.severity = suggestion
65 |
--------------------------------------------------------------------------------
/test/CsWin32User.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/test/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | true
7 | false
8 | true
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/test/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/BoolTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using Windows.Win32.Foundation;
5 |
6 | public class BoolTests
7 | {
8 | [Fact]
9 | public void Ctor_bool()
10 | {
11 | BOOL b = true;
12 | bool b2 = b;
13 | Assert.True(b);
14 | Assert.True(b2);
15 |
16 | Assert.False(default(BOOL));
17 | }
18 |
19 | [Fact]
20 | public void Ctor_int()
21 | {
22 | Assert.Equal(2, new BOOL(2).Value);
23 | }
24 |
25 | [Fact]
26 | public void ExplicitCast()
27 | {
28 | Assert.Equal(2, ((BOOL)2).Value);
29 | }
30 |
31 | [Theory]
32 | [InlineData(3)]
33 | [InlineData(-1)]
34 | [InlineData(0)]
35 | [InlineData(1)]
36 | [InlineData(0xfffff)]
37 | public void LossyConversionFromBOOLtoBool(int ordinal)
38 | {
39 | BOOL nativeBool = new BOOL(ordinal);
40 | bool managedBool = nativeBool;
41 | Assert.Equal(ordinal != 0, managedBool);
42 | BOOLEAN roundtrippedNativeBool = managedBool;
43 | Assert.Equal(managedBool ? 1 : 0, roundtrippedNativeBool);
44 | }
45 |
46 | [Fact]
47 | public void BOOLEqualsComparesExactValue()
48 | {
49 | BOOL b1 = new BOOL(1);
50 | BOOL b2 = new BOOL(2);
51 | Assert.Equal(b1, b1);
52 | Assert.NotEqual(b1, b2);
53 | }
54 |
55 | [Fact]
56 | public void BOOL_OverridesEqualityOperator()
57 | {
58 | var @true = new BOOL(true);
59 | var @false = new BOOL(false);
60 | Assert.True(@true == new BOOL(true));
61 | Assert.False(@true != new BOOL(true));
62 | Assert.True(@true != @false);
63 | Assert.False(@true == @false);
64 |
65 | var two = new BOOL(2);
66 | Assert.False(two == @true);
67 | Assert.True(two != @true);
68 | }
69 |
70 | [Fact]
71 | public void LogicalOperators_And()
72 | {
73 | BOOL @true = true, @false = false;
74 | Assert.False(@false && @false);
75 | Assert.False(@true && @false);
76 | Assert.True(@true && @true);
77 | }
78 |
79 | [Fact]
80 | public void LogicalOperators_Or()
81 | {
82 | BOOL @true = true, @false = false;
83 | Assert.True(@true || @false);
84 | Assert.False(@false || @false);
85 | Assert.True(@true || @true);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/BooleanTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using Windows.Win32.Foundation;
5 |
6 | public class BooleanTests
7 | {
8 | [Fact]
9 | public void Ctor_Bool()
10 | {
11 | BOOLEAN b = true;
12 | bool b2 = b;
13 | Assert.True(b);
14 | Assert.True(b2);
15 |
16 | Assert.False(default(BOOLEAN));
17 | }
18 |
19 | [Fact]
20 | public void Ctor_byte()
21 | {
22 | Assert.Equal(2, new BOOLEAN(2).Value);
23 | }
24 |
25 | [Fact]
26 | public void ExplicitCast()
27 | {
28 | Assert.Equal(2, ((BOOLEAN)2).Value);
29 | }
30 |
31 | [Theory]
32 | [InlineData(3)]
33 | [InlineData(0xff)]
34 | [InlineData(0x80)]
35 | [InlineData(0x00)]
36 | [InlineData(0x01)]
37 | public void LossyConversionFromBOOLEANtoBool(byte ordinal)
38 | {
39 | BOOLEAN nativeBool = new BOOLEAN(ordinal);
40 | bool managedBool = nativeBool;
41 | Assert.Equal(ordinal != 0, managedBool);
42 | BOOLEAN roundtrippedNativeBool = managedBool;
43 | Assert.Equal(managedBool ? 1 : 0, roundtrippedNativeBool);
44 | }
45 |
46 | [Fact]
47 | public void BOOLEANEqualsComparesExactValue()
48 | {
49 | BOOLEAN b1 = new BOOLEAN(1);
50 | BOOLEAN b2 = new BOOLEAN(2);
51 | Assert.Equal(b1, b1);
52 | Assert.NotEqual(b1, b2);
53 | }
54 |
55 | [Fact]
56 | public void BOOLEAN_OverridesEqualityOperator()
57 | {
58 | var @true = new BOOLEAN(true);
59 | var @false = new BOOLEAN(false);
60 | Assert.True(@true == new BOOLEAN(true));
61 | Assert.False(@true != new BOOLEAN(true));
62 | Assert.True(@true != @false);
63 | Assert.False(@true == @false);
64 |
65 | var two = new BOOLEAN(2);
66 | Assert.False(two == @true);
67 | Assert.True(two != @true);
68 | }
69 |
70 | [Fact]
71 | public void LogicalOperators_And()
72 | {
73 | BOOLEAN @true = true, @false = false;
74 | Assert.False(@false && @false);
75 | Assert.False(@true && @false);
76 | Assert.True(@true && @true);
77 | }
78 |
79 | [Fact]
80 | public void LogicalOperators_Or()
81 | {
82 | BOOLEAN @true = true, @false = false;
83 | Assert.True(@true || @false);
84 | Assert.False(@false || @false);
85 | Assert.True(@true || @true);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/ComRuntimeTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using Windows.Win32;
5 | using Windows.Win32.UI.Shell;
6 | using IServiceProvider = Windows.Win32.System.Com.IServiceProvider;
7 |
8 | public class ComRuntimeTests
9 | {
10 | [Fact]
11 | [Trait("TestCategory", "FailsInCloudTest")]
12 | public void RemotableInterface()
13 | {
14 | IShellWindows shellWindows = (IShellWindows)new ShellWindows();
15 | IServiceProvider serviceProvider = (IServiceProvider)shellWindows.FindWindowSW(
16 | PInvoke.CSIDL_DESKTOP,
17 | null,
18 | ShellWindowTypeConstants.SWC_DESKTOP,
19 | out int hwnd,
20 | ShellWindowFindWindowOptions.SWFO_NEEDDISPATCH);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/FILE_CREATE_FLAGS.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | namespace Microsoft.Windows.Sdk;
5 |
6 | ///
7 | /// Written here explicitly to verify that the code generator will suppress codegen where a type already exists.
8 | ///
9 | internal enum FILE_CREATE_FLAGS
10 | {
11 | CREATE_NEW = 1,
12 | CREATE_ALWAYS = 2,
13 | OPEN_EXISTING = 3,
14 | OPEN_ALWAYS = 4,
15 | TRUNCATE_EXISTING = 5,
16 | }
17 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/FlexibleArrayTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Runtime.InteropServices;
5 | using Microsoft.Win32.SafeHandles;
6 | using Windows.Win32.System.Ole;
7 |
8 | public class FlexibleArrayTests
9 | {
10 | [Fact]
11 | public unsafe void FlexibleArraySizing()
12 | {
13 | const int count = 3;
14 | PAGESET* pPageSet = (PAGESET*)Marshal.AllocHGlobal(PAGESET.SizeOf(count));
15 | try
16 | {
17 | pPageSet->rgPages[0].nFromPage = 0;
18 |
19 | Span pageRange = pPageSet->rgPages.AsSpan(count);
20 | for (int i = 0; i < count; i++)
21 | {
22 | pageRange[i].nFromPage = i * 2;
23 | pageRange[i].nToPage = (i * 2) + 1;
24 | }
25 | }
26 | finally
27 | {
28 | Marshal.FreeHGlobal((IntPtr)pPageSet);
29 | }
30 | }
31 |
32 | [Fact]
33 | public void SizeOf_Minimum1Element()
34 | {
35 | Assert.Equal(PAGESET.SizeOf(1), PAGESET.SizeOf(0));
36 | Assert.Equal(Marshal.SizeOf(), PAGESET.SizeOf(2) - PAGESET.SizeOf(1));
37 | }
38 |
39 | [Fact]
40 | [Trait("WindowsOnly", "true")]
41 | public unsafe void NonBlittableType_Char()
42 | {
43 | // The argument values are not relevant here.
44 | // The function is expected to return a failure error code in success cases.
45 | // This is a regression test for https://github.com/microsoft/CsWin32/issues/1184,
46 | // where the mere invocation of the function caused .NET Framework to throw a marshaling exception.
47 | uint size = 0;
48 | Windows.Win32.PInvoke.SetupDiGetDeviceInterfaceDetail(
49 | new SafeFileHandle(IntPtr.Zero, false),
50 | default,
51 | null,
52 | 0,
53 | &size,
54 | null);
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/GenerationSandbox.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/NativeMethods.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "..\\..\\src\\Microsoft.Windows.CsWin32\\settings.schema.json",
3 | "emitSingleFile": true,
4 | "multiTargetingFriendlyAPIs": true,
5 | "comInterop": {
6 | "preserveSigMethods": [
7 | "IEnumDebugPropertyInfo.Next"
8 | ]
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | BCRYPT_KEY_HANDLE
2 | BM_REQUEST_TYPE
3 | BOOL
4 | BOOLEAN
5 | CHAR
6 | CreateCursor
7 | CreateFile
8 | CSIDL_DESKTOP
9 | DISPLAYCONFIG_VIDEO_SIGNAL_INFO
10 | EnumWindows
11 | FILE_ACCESS_RIGHTS
12 | FLICK_DATA
13 | GetForegroundWindow
14 | GetProcAddress
15 | GetTickCount
16 | GetWindowText
17 | GetWindowTextLength
18 | RmRegisterResources
19 | HDC_UserSize
20 | HIWORD
21 | HRESULT_FROM_WIN32
22 | IDirectorySearch
23 | IEnumDebugPropertyInfo
24 | IPersistFile
25 | IServiceProvider
26 | IShellWindows
27 | IStream
28 | KEY_EVENT_RECORD
29 | LoadLibrary
30 | LOWORD
31 | MainAVIHeader
32 | MAKELPARAM
33 | MAKELRESULT
34 | MAKEWPARAM
35 | MAX_PATH
36 | NTSTATUS
37 | PAGESET
38 | PathParseIconLocation
39 | PROCESS_BASIC_INFORMATION
40 | PZZSTR
41 | PZZWSTR
42 | RECT
43 | RegLoadAppKey
44 | RM_PROCESS_INFO
45 | S_OK
46 | SetupDiGetDeviceInterfaceDetail
47 | SHDESCRIPTIONID
48 | SHELLFLAGSTATE
49 | ShellLink
50 | ShellWindowFindWindowOptions
51 | ShellWindows
52 | ShellWindowTypeConstants
53 | SHFILEOPSTRUCTW
54 | SIZE
55 | VARDESC
56 | WER_REPORT_INFORMATION
57 | wglGetProcAddress
58 | WPARAM
59 | WriteFile
60 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/SystemDrawingStructTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Drawing;
5 | using Windows.Win32.Foundation;
6 |
7 | public class SystemDrawingStructTests
8 | {
9 | [Fact]
10 | public void Size()
11 | {
12 | SIZE s = new SIZE(1, 1);
13 | Size s2 = s;
14 | Assert.False(s.IsEmpty);
15 | Assert.False(s2.IsEmpty);
16 |
17 | Assert.True(default(SIZE).IsEmpty);
18 | }
19 |
20 | [Fact]
21 | public void NotLossyConversionBetweenSizeAndSIZE()
22 | {
23 | SIZE nativeSize = new SIZE(1, 1);
24 | Size managedSize = nativeSize;
25 | SIZE roundtrippedNativeSize = managedSize;
26 | Assert.Equal(nativeSize, roundtrippedNativeSize);
27 | }
28 |
29 | [Fact]
30 | public void NotLossyConversionBetweenSizeAndSIZE_Ctors()
31 | {
32 | SIZE nativeSize = new SIZE(1, 1);
33 | Size managedSize = nativeSize;
34 | SIZE roundtrippedNativeSize = new SIZE(managedSize);
35 | Assert.Equal(nativeSize, roundtrippedNativeSize);
36 | }
37 |
38 | [Fact]
39 | public void Rect()
40 | {
41 | RECT r = new RECT(1, 1, 2, 2);
42 | Rectangle r2 = r;
43 | Assert.False(r.IsEmpty);
44 | Assert.False(r2.IsEmpty);
45 |
46 | Assert.True(default(RECT).IsEmpty);
47 | }
48 |
49 | [Fact]
50 | public void NotLossyConversionBetweenRectangleAndRECT()
51 | {
52 | RECT nativeSize = new RECT(1, 1, 2, 2);
53 | Rectangle managedSize = nativeSize;
54 | RECT roundtrippedNativeSize = managedSize;
55 | Assert.Equal(nativeSize, roundtrippedNativeSize);
56 | }
57 |
58 | [Fact]
59 | public void NotLossyConversionBetweenRectangleAndRECT_Ctors()
60 | {
61 | RECT nativeSize = new RECT(1, 1, 2, 2);
62 | Rectangle managedSize = nativeSize;
63 | RECT roundtrippedNativeSize = new RECT(managedSize);
64 | Assert.Equal(nativeSize, roundtrippedNativeSize);
65 | }
66 |
67 | [Fact]
68 | public void RectangleAndRECTFromXYWH_AreEqual()
69 | {
70 | RECT nativeSize = RECT.FromXYWH(1, 1, 2, 2);
71 | Rectangle managedSize = new Rectangle(1, 1, 2, 2);
72 | Assert.Equal(nativeSize.left, managedSize.Left);
73 | Assert.Equal(nativeSize.right, managedSize.Right);
74 | Assert.Equal(nativeSize.top, managedSize.Top);
75 | Assert.Equal(nativeSize.bottom, managedSize.Bottom);
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/TestUtils.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Diagnostics;
5 |
6 | internal static class TestUtils
7 | {
8 | #if DEBUG // Only tests that are conditioned for Debug mode can assert this.
9 | internal static void AssertDebugAssertFailed(Action action)
10 | {
11 | // We're mutating a static collection.
12 | // Protect against concurrent tests mutating the collection while we're using it.
13 | lock (Trace.Listeners)
14 | {
15 | TraceListener[] listeners = Trace.Listeners.Cast().ToArray();
16 | Trace.Listeners.Clear();
17 | Trace.Listeners.Add(new ThrowingTraceListener());
18 |
19 | try
20 | {
21 | action();
22 | Assert.Fail("Expected Debug.Assert to fail.");
23 | }
24 | catch (DebugAssertFailedException)
25 | {
26 | // PASS
27 | }
28 | finally
29 | {
30 | Trace.Listeners.Clear();
31 | Trace.Listeners.AddRange(listeners);
32 | }
33 | }
34 | }
35 | #endif
36 |
37 | private class DebugAssertFailedException : Exception
38 | {
39 | }
40 |
41 | private class ThrowingTraceListener : TraceListener
42 | {
43 | public override void Fail(string? message) => throw new DebugAssertFailedException();
44 |
45 | public override void Fail(string? message, string? detailMessage) => throw new DebugAssertFailedException();
46 |
47 | public override void Write(string? message)
48 | {
49 | }
50 |
51 | public override void WriteLine(string? message)
52 | {
53 | }
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Tests/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
3 | "shadowCopy": false
4 | }
5 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Unmarshalled.Tests/COMTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | #pragma warning disable IDE0005
5 |
6 | using Windows.Win32;
7 | using Windows.Win32.System.Com;
8 |
9 | public class COMTests
10 | {
11 | #if NET7_0_OR_GREATER
12 | [Fact]
13 | public void COMStaticGuid()
14 | {
15 | Assert.Equal(typeof(IPersistFile).GUID, IPersistFile.IID_Guid);
16 | Assert.Equal(typeof(IPersistFile).GUID, GetGuid());
17 | }
18 |
19 | private static Guid GetGuid()
20 | where T : IComIID
21 | => T.Guid;
22 | #endif
23 | }
24 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Unmarshalled.Tests/ComHelpers.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | #if NET7_0_OR_GREATER
5 |
6 | using System.Runtime.InteropServices;
7 | using Windows.Win32.Foundation;
8 | using Windows.Win32.System.Com;
9 |
10 | namespace Windows.Win32;
11 |
12 | // The `unsafe` modifier is only allowed to appear on the class declaration -- not the partial method declaration.
13 | // See https://github.com/dotnet/csharplang/discussions/7298 for more.
14 | internal unsafe partial class ComHelpers
15 | {
16 | static partial void PopulateIUnknownImpl(IUnknown.Vtbl* vtable)
17 | where TComInterface : unmanaged
18 | {
19 | // IUnknown member initialization of the v-table would go here.
20 | vtable->QueryInterface_1 = TestComWrappers.ComWrappersForIUnknown.QueryInterface_1;
21 | vtable->AddRef_2 = TestComWrappers.ComWrappersForIUnknown.AddRef_2;
22 | vtable->Release_3 = TestComWrappers.ComWrappersForIUnknown.Release_3;
23 | }
24 |
25 | private unsafe class TestComWrappers : ComWrappers
26 | {
27 | internal static readonly IUnknown.Vtbl ComWrappersForIUnknown = GetComWrappersUnknown();
28 |
29 | // Abstracts that need implementation
30 | protected override unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count)
31 | {
32 | count = 0;
33 | return null;
34 | }
35 |
36 | protected override object? CreateObject(nint externalComObject, CreateObjectFlags flags) => null;
37 |
38 | protected override void ReleaseObjects(global::System.Collections.IEnumerable objects) => throw new NotImplementedException();
39 |
40 | private static IUnknown.Vtbl GetComWrappersUnknown()
41 | {
42 | GetIUnknownImpl(out IntPtr fpQueryInterface, out IntPtr fpAddRef, out IntPtr fpRelease);
43 | return new IUnknown.Vtbl()
44 | {
45 | QueryInterface_1 = (delegate* unmanaged[Stdcall])fpQueryInterface,
46 | AddRef_2 = (delegate* unmanaged[Stdcall])fpAddRef,
47 | Release_3 = (delegate* unmanaged[Stdcall])fpRelease,
48 | };
49 | }
50 | }
51 | }
52 |
53 | #endif
54 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Unmarshalled.Tests/GeneratedForm.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | #pragma warning disable CA1812 // dead code
5 | #pragma warning disable CS0168 // Variable is declared but never used
6 |
7 | using Windows.Win32;
8 | using Windows.Win32.Foundation;
9 | using Windows.Win32.System.Com;
10 | using Windows.Win32.System.Com.Events;
11 | using Windows.Win32.System.Variant;
12 |
13 | ///
14 | /// Contains "tests" that never run. Merely compiling is enough to verify the generated code has the right API shape.
15 | ///
16 | internal static unsafe class GeneratedForm
17 | {
18 | private static unsafe void COMStructsPreserveSig()
19 | {
20 | IEventSubscription o = default;
21 |
22 | // Default is non-preservesig
23 | VARIANT v = o.GetPublisherProperty(null);
24 | BSTR bstr = o.MethodName;
25 |
26 | // NativeMethods.json opts into PreserveSig for these particular methods.
27 | HRESULT hr = o.GetSubscriberProperty(null, out v);
28 | hr = o.get_MachineName(out SysFreeStringSafeHandle sh);
29 | o.MachineName = bstr;
30 | }
31 |
32 | #if NET5_0_OR_GREATER
33 | private static unsafe void IStream_GetsCCW()
34 | {
35 | IStream.Vtbl vtbl;
36 | IStream.PopulateVTable(&vtbl);
37 | }
38 | #endif
39 |
40 | #if NET7_0_OR_GREATER
41 | private static unsafe void GetVTable()
42 | {
43 | IUnknown.Vtbl* vtbl = GetVtable();
44 |
45 | static IUnknown.Vtbl* GetVtable()
46 | where T : IVTable
47 | => T.VTable;
48 | }
49 | #endif
50 |
51 | private static unsafe void IUnknownGetsVtbl()
52 | {
53 | // WinForms needs the v-table to be declared for these base interfaces.
54 | IUnknown.Vtbl v;
55 | IDispatch.Vtbl v2;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Unmarshalled.Tests/GenerationSandbox.Unmarshalled.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Unmarshalled.Tests/NativeMethods.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "..\\..\\src\\Microsoft.Windows.CsWin32\\settings.schema.json",
3 | "emitSingleFile": true,
4 | "multiTargetingFriendlyAPIs": true,
5 | "allowMarshaling": false,
6 | "comInterop": {
7 | "preserveSigMethods": [
8 | "IEventSubscription.GetSubscriberProperty",
9 | "IEventSubscription.get_MachineName"
10 | ]
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.Unmarshalled.Tests/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | IEventSubscription
2 | IPersistFile
3 | IStream
4 |
--------------------------------------------------------------------------------
/test/GenerationSandbox.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | net9.0-windows7.0;net8.0-windows7.0;net472
6 | Exe
7 |
8 | x64
9 | true
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/ConstantsTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | public class ConstantsTests : GeneratorTestBase
5 | {
6 | public ConstantsTests(ITestOutputHelper logger)
7 | : base(logger)
8 | {
9 | }
10 |
11 | [Theory]
12 | [InlineData("SECURITY_NULL_SID_AUTHORITY")] // SID_IDENTIFIER_AUTHORITY with byte[6] inline array
13 | [InlineData("g_wszStreamBufferRecordingDuration")] // string
14 | [InlineData("HWND_BOTTOM")] // A constant typed as a typedef'd struct
15 | [InlineData("D2D1_DEFAULT_FLATTENING_TOLERANCE")] // a float constant
16 | [InlineData("WIA_CATEGORY_FINISHED_FILE")] // GUID constant
17 | [InlineData("DEVPKEY_MTPBTH_IsConnected")] // DEVPROPKEY constant
18 | [InlineData("PKEY_AudioEndpoint_FormFactor")] // PROPERTYKEY constant
19 | [InlineData("X509_CERT")] // A constant defined as PCSTR
20 | [InlineData("RT_CURSOR")] // PCWSTR constant
21 | [InlineData("HBMMENU_POPUP_RESTORE")] // A HBITMAP handle as a constant
22 | [InlineData("CONDITION_VARIABLE_INIT")] // A 0 constant typed void*
23 | [InlineData("DEVPKEY_Bluetooth_DeviceAddress")] // WDK constant defined as a type from the SDK
24 | public void InterestingConstants(string name)
25 | {
26 | this.compilation = this.compilation.WithOptions(this.compilation.Options.WithPlatform(Platform.X64));
27 | this.GenerateApi(name);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/DelegateTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | public class DelegateTests : GeneratorTestBase
5 | {
6 | public DelegateTests(ITestOutputHelper logger)
7 | : base(logger)
8 | {
9 | }
10 |
11 | [Theory]
12 | [CombinatorialData]
13 | public void InterestingDelegates(
14 | [CombinatorialValues(
15 | "LPD3DHAL_RENDERSTATECB")] // A delegate with a pointer parameter to a managed struct.
16 | string name,
17 | bool allowMarshaling)
18 | {
19 | var options = DefaultTestGeneratorOptions with
20 | {
21 | AllowMarshaling = allowMarshaling,
22 | };
23 | this.GenerateApi(name);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/EnumTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | public class EnumTests : GeneratorTestBase
5 | {
6 | public EnumTests(ITestOutputHelper logger)
7 | : base(logger)
8 | {
9 | }
10 |
11 | [Fact]
12 | public void EnumsIncludeAssociatedConstants()
13 | {
14 | this.GenerateApi("SERVICE_ERROR");
15 | EnumDeclarationSyntax enumDecl = Assert.IsType(this.FindGeneratedType("SERVICE_ERROR").Single());
16 |
17 | // The enum should contain the constant.
18 | Assert.Contains(enumDecl.Members, value => value.Identifier.ValueText == "SERVICE_NO_CHANGE");
19 |
20 | // The constant should not be generated as a separate constant.
21 | Assert.Empty(this.FindGeneratedConstant("SERVICE_NO_CHANGE"));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/ExternalMetadata/NOTICE.md:
--------------------------------------------------------------------------------
1 | This folder contains winmd files obtained from other sources which we use for testing.
2 |
3 | Metadata | Source
4 | --|--
5 | ServiceFabric.winmd | [youyuanwu/fabric-metadata](https://github.com/youyuanwu/fabric-metadata/raw/a1bcca6ad6f6a772c9e5ff4bdba80ae5e5f24cfc/.windows/winmd/ServiceFabric.winmd)
6 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/ExternalMetadata/ServiceFabric.winmd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/CsWin32/10ff614acb54f6d5a5dbb77c59bd8786e5c99097/test/Microsoft.Windows.CsWin32.Tests/ExternalMetadata/ServiceFabric.winmd
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/GeneratorConfiguration.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | internal record GeneratorConfiguration
5 | {
6 | internal static GeneratorConfiguration Default { get; } = new();
7 |
8 | internal ImmutableArray InputMetadataPaths { get; init; } = CollectAssemblyMetadata("ProjectionMetadataWinmd");
9 |
10 | internal ImmutableArray InputDocPaths { get; init; } = CollectAssemblyMetadata("ProjectionDocs");
11 |
12 | internal string ToGlobalConfigString()
13 | {
14 | StringBuilder globalConfigBuilder = new();
15 | globalConfigBuilder.AppendLine("is_global = true");
16 | globalConfigBuilder.AppendLine();
17 | AddPathsProperty("CsWin32InputMetadataPaths", this.InputMetadataPaths);
18 | AddPathsProperty("CsWin32InputDocPaths", this.InputDocPaths);
19 |
20 | return globalConfigBuilder.ToString();
21 |
22 | void AddPathsProperty(string name, ImmutableArray paths)
23 | {
24 | if (!paths.IsEmpty)
25 | {
26 | globalConfigBuilder.AppendLine($"build_property.{name} = {string.Join("|", paths)}");
27 | }
28 | }
29 | }
30 |
31 | private static ImmutableArray CollectAssemblyMetadata(string name) => [.. typeof(GeneratorTests).Assembly.GetCustomAttributes().Where(metadata => metadata.Key == name && metadata.Value is not null).Select(metadata => metadata.Value!)];
32 | }
33 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/GeneratorOptionsTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | public class GeneratorOptionsTests
5 | {
6 | [Fact]
7 | public void Validate_Default()
8 | {
9 | new GeneratorOptions().Validate();
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/GlobalUsings.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | global using System.Collections.Immutable;
5 | global using System.Reflection;
6 | global using System.Reflection.Metadata;
7 | global using System.Runtime.CompilerServices;
8 | global using System.Runtime.InteropServices;
9 | global using System.Text;
10 | global using Microsoft.CodeAnalysis;
11 | global using Microsoft.CodeAnalysis.CSharp;
12 | global using Microsoft.CodeAnalysis.CSharp.Syntax;
13 | global using Microsoft.CodeAnalysis.Testing;
14 | global using Microsoft.CodeAnalysis.Text;
15 | global using Microsoft.Windows.CsWin32;
16 | global using Xunit;
17 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/MacrosTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | public class MacrosTests : GeneratorTestBase
5 | {
6 | public MacrosTests(ITestOutputHelper logger)
7 | : base(logger)
8 | {
9 | }
10 |
11 | [Theory, PairwiseData]
12 | public void MacroAPIsGenerateWithAppropriateVisibility(bool publicVisibility)
13 | {
14 | this.generator = this.CreateGenerator(DefaultTestGeneratorOptions with { Public = publicVisibility });
15 | Assert.True(this.generator.TryGenerate("MAKELONG", CancellationToken.None));
16 | this.CollectGeneratedCode(this.generator);
17 | this.AssertNoDiagnostics();
18 | var makelongMethod = Assert.Single(this.FindGeneratedMethod("MAKELONG"));
19 | Assert.True(makelongMethod.Modifiers.Any(publicVisibility ? SyntaxKind.PublicKeyword : SyntaxKind.InternalKeyword));
20 | }
21 |
22 | [Theory]
23 | [MemberData(nameof(AvailableMacros))]
24 | public void MacroAPIsGenerate(string macro)
25 | {
26 | this.generator = this.CreateGenerator();
27 | Assert.True(this.generator.TryGenerate(macro, CancellationToken.None));
28 | this.CollectGeneratedCode(this.generator);
29 | this.AssertNoDiagnostics();
30 | Assert.Single(this.FindGeneratedMethod(macro));
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/Microsoft.Windows.CsWin32.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net8.0
5 | Exe
6 |
7 |
8 |
9 |
10 | <_AssemblyMetadata1 Include="@(ProjectionMetadataWinmd)">
11 | %(Identity)
12 |
13 |
14 |
15 | <_AssemblyMetadata2 Include="@(ProjectionDocs)">
16 | %(Identity)
17 |
18 |
19 |
20 |
21 |
22 |
23 | PreserveNewest
24 |
25 |
26 | PreserveNewest
27 |
28 |
29 | PreserveNewest
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 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/MultiMetadataTests.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | public class MultiMetadataTests : GeneratorTestBase
5 | {
6 | public MultiMetadataTests(ITestOutputHelper logger)
7 | : base(logger)
8 | {
9 | }
10 |
11 | [Theory, PairwiseData]
12 | public void BasicServiceFabric(bool allowMarshaling)
13 | {
14 | this.generator = this.CreateSuperGenerator(DefaultMetadataPaths.Concat(new[] { ServiceFabricMetadataPath }).ToArray(), DefaultTestGeneratorOptions with { AllowMarshaling = allowMarshaling });
15 | Assert.True(this.generator.TryGenerate("IFabricStringResult", CancellationToken.None));
16 | this.CollectGeneratedCode(this.generator);
17 | this.AssertNoDiagnostics();
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/MyReferenceAssemblies.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | internal static class MyReferenceAssemblies
5 | {
6 | #pragma warning disable SA1202 // Elements should be ordered by access - because field initializer depend on each other
7 | private static readonly ImmutableArray AdditionalLegacyPackages = ImmutableArray.Create(
8 | new PackageIdentity("Microsoft.Windows.SDK.Contracts", "10.0.22621.2428"));
9 |
10 | private static readonly ImmutableArray AdditionalModernPackages = AdditionalLegacyPackages.AddRange(ImmutableArray.Create(
11 | ExtraPackages.Unsafe,
12 | ExtraPackages.Memory,
13 | ExtraPackages.Registry));
14 |
15 | internal static readonly ReferenceAssemblies NetStandard20 = ReferenceAssemblies.NetStandard.NetStandard20.AddPackages(AdditionalModernPackages);
16 | #pragma warning restore SA1202 // Elements should be ordered by access
17 |
18 | internal static class NetFramework
19 | {
20 | internal static readonly ReferenceAssemblies Net35 = ReferenceAssemblies.NetFramework.Net35.WindowsForms.AddPackages(AdditionalLegacyPackages);
21 | internal static readonly ReferenceAssemblies Net472 = ReferenceAssemblies.NetFramework.Net472.WindowsForms.AddPackages(AdditionalModernPackages);
22 | }
23 |
24 | internal static class Net
25 | {
26 | internal static readonly ReferenceAssemblies Net80 = ReferenceAssemblies.Net.Net80.AddPackages(AdditionalModernPackages);
27 | internal static readonly ReferenceAssemblies Net90 = ReferenceAssemblies.Net.Net90.AddPackages(AdditionalModernPackages);
28 | }
29 |
30 | internal static class ExtraPackages
31 | {
32 | internal static readonly PackageIdentity Unsafe = new PackageIdentity("System.Runtime.CompilerServices.Unsafe", "6.0.0");
33 | internal static readonly PackageIdentity Memory = new PackageIdentity("System.Memory", "4.5.5");
34 | internal static readonly PackageIdentity Registry = new PackageIdentity("Microsoft.Win32.Registry", "5.0.0");
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/NumberedLineWriter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | internal class NumberedLineWriter : TextWriter
5 | {
6 | private readonly ITestOutputHelper logger;
7 | private readonly StringBuilder lineBuilder = new StringBuilder();
8 | private int lineNumber;
9 |
10 | internal NumberedLineWriter(ITestOutputHelper logger)
11 | {
12 | this.logger = logger;
13 | }
14 |
15 | public override Encoding Encoding => Encoding.Unicode;
16 |
17 | public override void WriteLine(string? value)
18 | {
19 | this.logger.WriteLine($"{++this.lineNumber,6}: {this.lineBuilder}{value}");
20 | this.lineBuilder.Clear();
21 | }
22 |
23 | public override void Write(string? value)
24 | {
25 | if (value is null)
26 | {
27 | return;
28 | }
29 |
30 | if (value.EndsWith("\r\n", StringComparison.Ordinal))
31 | {
32 | this.WriteLine(value.Substring(0, value.Length - 2));
33 | }
34 | else if (value.EndsWith("\n", StringComparison.Ordinal))
35 | {
36 | this.WriteLine(value.Substring(0, value.Length - 1));
37 | }
38 | else
39 | {
40 | this.lineBuilder.Append(value);
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/TestUtils.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using System.Text.RegularExpressions;
5 |
6 | internal static class TestUtils
7 | {
8 | private const string ExpectedGeneratedSourceLineEnding = "\r\n";
9 | private static readonly Regex NewLineRegex = new(@"\r?\n");
10 |
11 | public static string NormalizeToExpectedLineEndings(string text)
12 | {
13 | return NewLineRegex.Replace(text, ExpectedGeneratedSourceLineEnding);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/test/Microsoft.Windows.CsWin32.Tests/xunit.runner.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://xunit.net/schema/current/xunit.runner.schema.json",
3 | "shadowCopy": false
4 | }
5 |
--------------------------------------------------------------------------------
/test/SpellChecker/NativeMethods.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "..\\..\\src\\Microsoft.Windows.CsWin32\\settings.schema.json"
3 | }
4 |
--------------------------------------------------------------------------------
/test/SpellChecker/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | CLSCTX
2 | CoCreateInstance
3 | CoTaskMemFree
4 | ISpellChecker
5 | ISpellCheckerFactory
6 | S_FALSE
7 | S_OK
8 | SpellCheckerFactory
9 |
--------------------------------------------------------------------------------
/test/SpellChecker/Program.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft Corporation. All rights reserved.
2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 |
4 | using Windows.Win32;
5 | using Windows.Win32.Foundation;
6 | using Windows.Win32.Globalization;
7 | using Windows.Win32.System.Com;
8 | using static Windows.Win32.PInvoke;
9 |
10 | unsafe
11 | {
12 | var spellCheckerFactory = (ISpellCheckerFactory)new SpellCheckerFactory();
13 |
14 | BOOL supported = spellCheckerFactory.IsSupported("en-US");
15 |
16 | if (!supported)
17 | {
18 | return;
19 | }
20 |
21 | ISpellChecker spellChecker = spellCheckerFactory.CreateSpellChecker("en-US");
22 |
23 | var text = @"""Cann I I haev some?""";
24 |
25 | Console.WriteLine(@"Check {0}", text);
26 |
27 | IEnumSpellingError errors = spellChecker.Check(text);
28 |
29 | Span suggestionResult = new PWSTR[1];
30 | while (true)
31 | {
32 | if (errors.Next(out ISpellingError error).ThrowOnFailure() == HRESULT.S_FALSE)
33 | {
34 | break;
35 | }
36 |
37 | uint startIndex = error.StartIndex;
38 | uint length = error.Length;
39 |
40 | var word = text.Substring((int)startIndex, (int)length);
41 |
42 | CORRECTIVE_ACTION action = error.CorrectiveAction;
43 |
44 | switch (action)
45 | {
46 | case CORRECTIVE_ACTION.CORRECTIVE_ACTION_DELETE:
47 | Console.WriteLine(@"Delete ""{0}""", word);
48 | break;
49 | case CORRECTIVE_ACTION.CORRECTIVE_ACTION_REPLACE:
50 | PWSTR replacement = error.Replacement;
51 | Console.WriteLine(@"Replace ""{0}"" with ""{1}""", word, replacement);
52 | CoTaskMemFree(replacement);
53 | break;
54 | case CORRECTIVE_ACTION.CORRECTIVE_ACTION_GET_SUGGESTIONS:
55 | Console.WriteLine(@"Suggest replacing ""{0}"" with:", word);
56 | IEnumString suggestions = spellChecker.Suggest(word);
57 | do
58 | {
59 | suggestions.Next(suggestionResult, null);
60 | if (suggestionResult[0].Value is not null)
61 | {
62 | Console.WriteLine($"\t{suggestionResult[0]}");
63 | CoTaskMemFree(suggestionResult[0]);
64 | }
65 | }
66 | while (suggestionResult[0].Value is not null);
67 |
68 | break;
69 | default:
70 | break;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/test/SpellChecker/SpellChecker.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Exe
6 | net8.0-windows8.0;net472
7 | false
8 | true
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test/WinRTInteropTest/NativeMethods.txt:
--------------------------------------------------------------------------------
1 | BeginPaint
2 | BS_PUSHBUTTON
3 | CreateDispatcherQueueController
4 | CreateWindowExW
5 | CW_USEDEFAULT
6 | DefWindowProc
7 | DestroyWindow
8 | DispatchMessage
9 | EndPaint
10 | GetMessage
11 | GetModuleHandle
12 | HDC
13 | HMENU
14 | HMODULE
15 | HWND
16 | ICompositorDesktopInterop
17 | IDC_ARROW
18 | IDI_APPLICATION
19 | InvalidateRect
20 | LoadCursor
21 | LoadIcon
22 | MSG
23 | PAINTSTRUCT
24 | PostMessage
25 | PostQuitMessage
26 | RegisterClassExW
27 | ShowWindow
28 | TranslateMessage
29 | UpdateWindow
30 | WM_CLOSE
31 | WM_COMMAND
32 | WM_CREATE
33 | WM_DESTROY
34 | WM_PAINT
35 | WNDCLASSEXW
36 |
--------------------------------------------------------------------------------
/test/WinRTInteropTest/WinRTInteropTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | WinExe
6 | net8.0-windows10.0.19041.0
7 | disable
8 | false
9 | true
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/tools/Check-DotNetRuntime.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Checks whether a given .NET Core runtime is installed.
4 | #>
5 | [CmdletBinding()]
6 | Param (
7 | [Parameter()]
8 | [ValidateSet('Microsoft.AspNetCore.App','Microsoft.NETCore.App')]
9 | [string]$Runtime='Microsoft.NETCore.App',
10 | [Parameter(Mandatory=$true)]
11 | [Version]$Version
12 | )
13 |
14 | $dotnet = Get-Command dotnet -ErrorAction SilentlyContinue
15 | if (!$dotnet) {
16 | # Nothing is installed.
17 | Write-Output $false
18 | exit 1
19 | }
20 |
21 | Function IsVersionMatch {
22 | Param(
23 | [Parameter()]
24 | $actualVersion
25 | )
26 | return $actualVersion -and
27 | $Version.Major -eq $actualVersion.Major -and
28 | $Version.Minor -eq $actualVersion.Minor -and
29 | (($Version.Build -eq -1) -or ($Version.Build -eq $actualVersion.Build)) -and
30 | (($Version.Revision -eq -1) -or ($Version.Revision -eq $actualVersion.Revision))
31 | }
32 |
33 | $installedRuntimes = dotnet --list-runtimes |? { $_.Split()[0] -ieq $Runtime } |% { $v = $null; [Version]::tryparse($_.Split()[1], [ref] $v); $v }
34 | $matchingRuntimes = $installedRuntimes |? { IsVersionMatch -actualVersion $_ }
35 | if (!$matchingRuntimes) {
36 | Write-Output $false
37 | exit 1
38 | }
39 |
40 | Write-Output $true
41 | exit 0
42 |
--------------------------------------------------------------------------------
/tools/Check-DotNetSdk.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Checks whether the .NET Core SDK required by this repo is installed.
4 | #>
5 | [CmdletBinding()]
6 | Param (
7 | )
8 |
9 | $dotnet = Get-Command dotnet -ErrorAction SilentlyContinue
10 | if (!$dotnet) {
11 | # Nothing is installed.
12 | Write-Output $false
13 | exit 1
14 | }
15 |
16 | # We need to set the current directory so dotnet considers the SDK required by our global.json file.
17 | Push-Location "$PSScriptRoot\.."
18 | try {
19 | dotnet -h 2>&1 | Out-Null
20 | if (($LASTEXITCODE -eq 129) -or # On Linux
21 | ($LASTEXITCODE -eq -2147450751) # On Windows
22 | ) {
23 | # These exit codes indicate no matching SDK exists.
24 | Write-Output $false
25 | exit 2
26 | }
27 |
28 | # The required SDK is already installed!
29 | Write-Output $true
30 | exit 0
31 | } catch {
32 | # I don't know why, but on some build agents (e.g. MicroBuild), an exception is thrown from the `dotnet` invocation when a match is not found.
33 | Write-Output $false
34 | exit 3
35 | } finally {
36 | Pop-Location
37 | }
38 |
--------------------------------------------------------------------------------
/tools/Convert-PDB.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Converts between Windows PDB and Portable PDB formats.
4 | .PARAMETER DllPath
5 | The path to the DLL whose PDB is to be converted.
6 | .PARAMETER PdbPath
7 | The path to the PDB to convert. May be omitted if the DLL was compiled on this machine and the PDB is still at its original path.
8 | .PARAMETER OutputPath
9 | The path of the output PDB to write.
10 | #>
11 | [CmdletBinding()]
12 | Param(
13 | [Parameter(Mandatory=$true,Position=0)]
14 | [string]$DllPath,
15 | [Parameter()]
16 | [string]$PdbPath,
17 | [Parameter(Mandatory=$true,Position=1)]
18 | [string]$OutputPath
19 | )
20 |
21 | if ($IsMacOS -or $IsLinux) {
22 | Write-Error "This script only works on Windows"
23 | return
24 | }
25 |
26 | $version = '1.1.0-beta2-21101-01'
27 | $baseDir = "$PSScriptRoot/../obj/tools"
28 | $pdb2pdbpath = "$baseDir/Microsoft.DiaSymReader.Pdb2Pdb.$version/tools/Pdb2Pdb.exe"
29 | if (-not (Test-Path $pdb2pdbpath)) {
30 | if (-not (Test-Path $baseDir)) { New-Item -Type Directory -Path $baseDir | Out-Null }
31 | $baseDir = (Resolve-Path $baseDir).Path # Normalize it
32 | Write-Verbose "& (& $PSScriptRoot/Get-NuGetTool.ps1) install Microsoft.DiaSymReader.Pdb2Pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json | Out-Null"
33 | & (& $PSScriptRoot/Get-NuGetTool.ps1) install Microsoft.DiaSymReader.Pdb2Pdb -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-tools/nuget/v3/index.json | Out-Null
34 | }
35 |
36 | $args = $DllPath,'/out',$OutputPath,'/nowarn','0021'
37 | if ($PdbPath) {
38 | $args += '/pdb',$PdbPath
39 | }
40 |
41 | Write-Verbose "$pdb2pdbpath $args"
42 | & $pdb2pdbpath $args
43 |
--------------------------------------------------------------------------------
/tools/Get-ArtifactsStagingDirectory.ps1:
--------------------------------------------------------------------------------
1 | Param(
2 | [switch]$CleanIfLocal
3 | )
4 | if ($env:BUILD_ARTIFACTSTAGINGDIRECTORY) {
5 | $ArtifactStagingFolder = $env:BUILD_ARTIFACTSTAGINGDIRECTORY
6 | } elseif ($env:RUNNER_TEMP) {
7 | $ArtifactStagingFolder = Join-Path $env:RUNNER_TEMP _artifacts
8 | } else {
9 | $ArtifactStagingFolder = [System.IO.Path]::GetFullPath("$PSScriptRoot/../obj/_artifacts")
10 | if ($CleanIfLocal -and (Test-Path $ArtifactStagingFolder)) {
11 | Remove-Item $ArtifactStagingFolder -Recurse -Force
12 | }
13 | }
14 |
15 | $ArtifactStagingFolder
16 |
--------------------------------------------------------------------------------
/tools/Get-LibTemplateBasis.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Returns the name of the well-known branch in the Library.Template repository upon which HEAD is based.
4 | #>
5 | [CmdletBinding(SupportsShouldProcess = $true)]
6 | Param(
7 | [switch]$ErrorIfNotRelated
8 | )
9 |
10 | # This list should be sorted in order of decreasing specificity.
11 | $branchMarkers = @(
12 | @{ commit = 'fd0a7b25ccf030bbd16880cca6efe009d5b1fffc'; branch = 'microbuild' };
13 | @{ commit = '05f49ce799c1f9cc696d53eea89699d80f59f833'; branch = 'main' };
14 | )
15 |
16 | foreach ($entry in $branchMarkers) {
17 | if (git rev-list HEAD | Select-String -Pattern $entry.commit) {
18 | return $entry.branch
19 | }
20 | }
21 |
22 | if ($ErrorIfNotRelated) {
23 | Write-Error "Library.Template has not been previously merged with this repo. Please review https://github.com/AArnott/Library.Template/tree/main?tab=readme-ov-file#readme for instructions."
24 | exit 1
25 | }
26 |
--------------------------------------------------------------------------------
/tools/Get-NuGetTool.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Downloads the NuGet.exe tool and returns the path to it.
4 | .PARAMETER NuGetVersion
5 | The version of the NuGet tool to acquire.
6 | #>
7 | Param(
8 | [Parameter()]
9 | [string]$NuGetVersion='6.12.2'
10 | )
11 |
12 | $toolsPath = & "$PSScriptRoot\Get-TempToolsPath.ps1"
13 | $binaryToolsPath = Join-Path $toolsPath $NuGetVersion
14 | if (!(Test-Path $binaryToolsPath)) { $null = mkdir $binaryToolsPath }
15 | $nugetPath = Join-Path $binaryToolsPath nuget.exe
16 |
17 | if (!(Test-Path $nugetPath)) {
18 | Write-Host "Downloading nuget.exe $NuGetVersion..." -ForegroundColor Yellow
19 | (New-Object System.Net.WebClient).DownloadFile("https://dist.nuget.org/win-x86-commandline/v$NuGetVersion/NuGet.exe", $nugetPath)
20 | }
21 |
22 | return (Resolve-Path $nugetPath).Path
23 |
--------------------------------------------------------------------------------
/tools/Get-ProcDump.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Downloads 32-bit and 64-bit procdump executables and returns the path to where they were installed.
4 | #>
5 | $version = '0.0.1'
6 | $baseDir = "$PSScriptRoot\..\obj\tools"
7 | $procDumpToolPath = "$baseDir\procdump.$version\bin"
8 | if (-not (Test-Path $procDumpToolPath)) {
9 | if (-not (Test-Path $baseDir)) { New-Item -Type Directory -Path $baseDir | Out-Null }
10 | $baseDir = (Resolve-Path $baseDir).Path # Normalize it
11 | & (& $PSScriptRoot\Get-NuGetTool.ps1) install procdump -version $version -PackageSaveMode nuspec -OutputDirectory $baseDir -Source https://api.nuget.org/v3/index.json | Out-Null
12 | }
13 |
14 | (Resolve-Path $procDumpToolPath).Path
15 |
--------------------------------------------------------------------------------
/tools/Get-SymbolFiles.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Collect the list of PDBs built in this repo.
4 | .PARAMETER Path
5 | The directory to recursively search for PDBs.
6 | .PARAMETER Tests
7 | A switch indicating to find PDBs only for test binaries instead of only for shipping shipping binaries.
8 | #>
9 | [CmdletBinding()]
10 | param (
11 | [parameter(Mandatory=$true)]
12 | [string]$Path,
13 | [switch]$Tests
14 | )
15 |
16 | $ActivityName = "Collecting symbols from $Path"
17 | Write-Progress -Activity $ActivityName -CurrentOperation "Discovery PDB files"
18 | $PDBs = Get-ChildItem -rec "$Path/*.pdb"
19 |
20 | # Filter PDBs to product OR test related.
21 | $testregex = "unittest|tests|\.test\.|WinRTInteropTest|SpellChecker"
22 |
23 | Write-Progress -Activity $ActivityName -CurrentOperation "De-duplicating symbols"
24 | $PDBsByHash = @{}
25 | $i = 0
26 | $PDBs |% {
27 | Write-Progress -Activity $ActivityName -CurrentOperation "De-duplicating symbols" -PercentComplete (100 * $i / $PDBs.Length)
28 | $hash = Get-FileHash $_
29 | $i++
30 | Add-Member -InputObject $_ -MemberType NoteProperty -Name Hash -Value $hash.Hash
31 | Write-Output $_
32 | } | Sort-Object CreationTime |% {
33 | # De-dupe based on hash. Prefer the first match so we take the first built copy.
34 | if (-not $PDBsByHash.ContainsKey($_.Hash)) {
35 | $PDBsByHash.Add($_.Hash, $_.FullName)
36 | Write-Output $_
37 | }
38 | } |? {
39 | if ($Tests) {
40 | $_.FullName -match $testregex
41 | } else {
42 | $_.FullName -notmatch $testregex
43 | }
44 | } |% {
45 | # Collect the DLLs/EXEs as well.
46 | $rootName = "$($_.Directory)/$($_.BaseName)"
47 | if ($rootName.EndsWith('.ni')) {
48 | $rootName = $rootName.Substring(0, $rootName.Length - 3)
49 | }
50 |
51 | $dllPath = "$rootName.dll"
52 | $exePath = "$rootName.exe"
53 | if (Test-Path $dllPath) {
54 | $BinaryImagePath = $dllPath
55 | } elseif (Test-Path $exePath) {
56 | $BinaryImagePath = $exePath
57 | } else {
58 | Write-Warning "`"$_`" found with no matching binary file."
59 | $BinaryImagePath = $null
60 | }
61 |
62 | if ($BinaryImagePath) {
63 | Write-Output $BinaryImagePath
64 | Write-Output $_.FullName
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/tools/Get-TempToolsPath.ps1:
--------------------------------------------------------------------------------
1 | if ($env:AGENT_TEMPDIRECTORY) {
2 | $path = "$env:AGENT_TEMPDIRECTORY\$env:BUILD_BUILDID"
3 | } elseif ($env:localappdata) {
4 | $path = "$env:localappdata\gitrepos\tools"
5 | } else {
6 | $path = "$PSScriptRoot\..\obj\tools"
7 | }
8 |
9 | if (!(Test-Path $path)) {
10 | New-Item -ItemType Directory -Path $Path | Out-Null
11 | }
12 |
13 | (Resolve-Path $path).Path
14 |
--------------------------------------------------------------------------------
/tools/Prepare-Legacy-Symbols.ps1:
--------------------------------------------------------------------------------
1 | Param(
2 | [string]$Path
3 | )
4 |
5 | $ArtifactStagingFolder = & "$PSScriptRoot/Get-ArtifactsStagingDirectory.ps1"
6 | $ArtifactStagingFolder += '/symbols-legacy'
7 | robocopy $Path $ArtifactStagingFolder /mir /njh /njs /ndl /nfl
8 | $WindowsPdbSubDirName = 'symstore'
9 |
10 | Get-ChildItem "$ArtifactStagingFolder\*.pdb" -Recurse |% {
11 | $dllPath = "$($_.Directory)/$($_.BaseName).dll"
12 | $exePath = "$($_.Directory)/$($_.BaseName).exe"
13 | if (Test-Path $dllPath) {
14 | $BinaryImagePath = $dllPath
15 | } elseif (Test-Path $exePath) {
16 | $BinaryImagePath = $exePath
17 | } else {
18 | Write-Warning "`"$_`" found with no matching binary file."
19 | $BinaryImagePath = $null
20 | }
21 |
22 | if ($BinaryImagePath) {
23 | # Convert the PDB to legacy Windows PDBs
24 | Write-Host "Converting PDB for $_" -ForegroundColor DarkGray
25 | $WindowsPdbDir = "$($_.Directory.FullName)\$WindowsPdbSubDirName"
26 | if (!(Test-Path $WindowsPdbDir)) { mkdir $WindowsPdbDir | Out-Null }
27 | $legacyPdbPath = "$WindowsPdbDir\$($_.BaseName).pdb"
28 | & "$PSScriptRoot\Convert-PDB.ps1" -DllPath $BinaryImagePath -PdbPath $_ -OutputPath $legacyPdbPath
29 | if ($LASTEXITCODE -ne 0) {
30 | Write-Warning "PDB conversion of `"$_`" failed."
31 | }
32 |
33 | Move-Item $legacyPdbPath $_ -Force
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/tools/artifacts/APIScanInputs.ps1:
--------------------------------------------------------------------------------
1 | $inputs = & "$PSScriptRoot/symbols.ps1"
2 |
3 | if (!$inputs) { return }
4 |
5 | # Filter out specific files that target OS's that are not subject to APIScan.
6 | # Files that are subject but are not supported must be scanned and an SEL exception filed.
7 | $outputs = @{}
8 | $forbiddenSubPaths = @(
9 | , 'linux-*'
10 | , 'osx*'
11 | )
12 |
13 | $inputs.GetEnumerator() | % {
14 | $list = $_.Value | ? {
15 | $path = $_.Replace('\', '/')
16 | return !($forbiddenSubPaths | ? { $path -like "*/$_/*" })
17 | }
18 | $outputs[$_.Key] = $list
19 | }
20 |
21 |
22 | $outputs
23 |
--------------------------------------------------------------------------------
/tools/artifacts/LocBin.ps1:
--------------------------------------------------------------------------------
1 | # Identify LCE files and the binary files they describe
2 | $BinRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\bin")
3 | if (!(Test-Path $BinRoot)) { return }
4 |
5 | $FilesToCopy = @()
6 | $FilesToCopy += Get-ChildItem -Recurse -File -Path $BinRoot |? { $_.FullName -match '\\Localize\\' }
7 |
8 | Get-ChildItem -rec "$BinRoot\*.lce" -File | % {
9 | $FilesToCopy += $_
10 | $FilesToCopy += $_.FullName.SubString(0, $_.FullName.Length - 4)
11 | }
12 |
13 | $FilesToCopy += Get-ChildItem -rec "$BinRoot\*.lcg" -File | % { [xml](Get-Content $_) } | % { $_.lcx.name }
14 |
15 | @{
16 | "$BinRoot" = $FilesToCopy;
17 | }
18 |
--------------------------------------------------------------------------------
/tools/artifacts/VSInsertion.ps1:
--------------------------------------------------------------------------------
1 | # This artifact captures everything needed to insert into VS (NuGet packages, insertion metadata, etc.)
2 |
3 | [CmdletBinding()]
4 | Param (
5 | )
6 |
7 | if ($IsMacOS -or $IsLinux) {
8 | # We only package up for insertions on Windows agents since they are where optprof can happen.
9 | Write-Verbose "Skipping VSInsertion artifact since we're not on Windows."
10 | return @{}
11 | }
12 |
13 | $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
14 | $BuildConfiguration = $env:BUILDCONFIGURATION
15 | if (!$BuildConfiguration) {
16 | $BuildConfiguration = 'Debug'
17 | }
18 |
19 | $PackagesRoot = "$RepoRoot/bin/Packages/$BuildConfiguration"
20 | $NuGetPackages = "$PackagesRoot/NuGet"
21 | $VsixPackages = "$PackagesRoot/Vsix"
22 |
23 | if (!(Test-Path $NuGetPackages)) {
24 | Write-Warning "Skipping because NuGet packages haven't been built yet."
25 | return @{}
26 | }
27 |
28 | $result = @{
29 | "$NuGetPackages" = (Get-ChildItem $NuGetPackages -Recurse)
30 | }
31 |
32 | if (Test-Path $VsixPackages) {
33 | $result["$PackagesRoot"] += Get-ChildItem $VsixPackages -Recurse
34 | }
35 |
36 | if ($env:IsOptProf) {
37 | $VSRepoPackages = "$PackagesRoot/VSRepo"
38 | $result["$VSRepoPackages"] = (Get-ChildItem "$VSRepoPackages\*.VSInsertionMetadata.*.nupkg");
39 | }
40 |
41 | $result
42 |
--------------------------------------------------------------------------------
/tools/artifacts/Variables.ps1:
--------------------------------------------------------------------------------
1 | # This artifact captures all variables defined in the ..\variables folder.
2 | # It "snaps" the values of these variables where we can compute them during the build,
3 | # and otherwise captures the scripts to run later during an Azure Pipelines environment release.
4 |
5 | $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot/../..")
6 | $ArtifactBasePath = "$RepoRoot/obj/_artifacts"
7 | $VariablesArtifactPath = Join-Path $ArtifactBasePath variables
8 | if (-not (Test-Path $VariablesArtifactPath)) { New-Item -ItemType Directory -Path $VariablesArtifactPath | Out-Null }
9 |
10 | # Copy variables, either by value if the value is calculable now, or by script
11 | Get-ChildItem "$PSScriptRoot/../variables" |% {
12 | $value = $null
13 | if (-not $_.BaseName.StartsWith('_')) { # Skip trying to interpret special scripts
14 | # First check the environment variables in case the variable was set in a queued build
15 | # Always use all caps for env var access because Azure Pipelines converts variables to upper-case for env vars,
16 | # and on non-Windows env vars are case sensitive.
17 | $envVarName = $_.BaseName.ToUpper()
18 | if (Test-Path env:$envVarName) {
19 | $value = Get-Content "env:$envVarName"
20 | }
21 |
22 | # If that didn't give us anything, try executing the script right now from its original position
23 | if (-not $value) {
24 | $value = & $_.FullName
25 | }
26 |
27 | if ($value) {
28 | # We got something, so wrap it with quotes so it's treated like a literal value.
29 | $value = "'$value'"
30 | }
31 | }
32 |
33 | # If that didn't get us anything, just copy the script itself
34 | if (-not $value) {
35 | $value = Get-Content -LiteralPath $_.FullName
36 | }
37 |
38 | Set-Content -LiteralPath "$VariablesArtifactPath/$($_.Name)" -Value $value
39 | }
40 |
41 | @{
42 | "$VariablesArtifactPath" = (Get-ChildItem $VariablesArtifactPath -Recurse);
43 | }
44 |
--------------------------------------------------------------------------------
/tools/artifacts/build_logs.ps1:
--------------------------------------------------------------------------------
1 | $ArtifactStagingFolder = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1"
2 |
3 | if (!(Test-Path $ArtifactStagingFolder/build_logs)) { return }
4 |
5 | @{
6 | "$ArtifactStagingFolder/build_logs" = (Get-ChildItem -Recurse "$ArtifactStagingFolder/build_logs")
7 | }
8 |
--------------------------------------------------------------------------------
/tools/artifacts/coverageResults.ps1:
--------------------------------------------------------------------------------
1 | $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
2 |
3 | $coverageFiles = @(Get-ChildItem "$RepoRoot/test/*.cobertura.xml" -Recurse | Where {$_.FullName -notlike "*/In/*" -and $_.FullName -notlike "*\In\*" })
4 |
5 | # Prepare code coverage reports for merging on another machine
6 | $repoRoot = $env:SYSTEM_DEFAULTWORKINGDIRECTORY
7 | if (!$repoRoot) { $repoRoot = $env:GITHUB_WORKSPACE }
8 | if ($repoRoot) {
9 | Write-Host "Substituting $repoRoot with `"{reporoot}`""
10 | $coverageFiles |% {
11 | $content = Get-Content -LiteralPath $_ |% { $_ -Replace [regex]::Escape($repoRoot), "{reporoot}" }
12 | Set-Content -LiteralPath $_ -Value $content -Encoding UTF8
13 | }
14 | } else {
15 | Write-Warning "coverageResults: Cloud build not detected. Machine-neutral token replacement skipped."
16 | }
17 |
18 | if (!((Test-Path $RepoRoot\bin) -and (Test-Path $RepoRoot\obj))) { return }
19 |
20 | @{
21 | $RepoRoot = (
22 | $coverageFiles +
23 | (Get-ChildItem "$RepoRoot\obj\*.cs" -Recurse)
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/tools/artifacts/deployables.ps1:
--------------------------------------------------------------------------------
1 | $RepoRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..")
2 | $BuildConfiguration = $env:BUILDCONFIGURATION
3 | if (!$BuildConfiguration) {
4 | $BuildConfiguration = 'Debug'
5 | }
6 |
7 | $PackagesRoot = "$RepoRoot/bin/Packages/$BuildConfiguration"
8 |
9 | if (!(Test-Path $PackagesRoot)) { return }
10 |
11 | @{
12 | "$PackagesRoot" = (Get-ChildItem $PackagesRoot -Recurse)
13 | }
14 |
--------------------------------------------------------------------------------
/tools/artifacts/projectAssetsJson.ps1:
--------------------------------------------------------------------------------
1 | $ObjRoot = [System.IO.Path]::GetFullPath("$PSScriptRoot\..\..\obj")
2 |
3 | if (!(Test-Path $ObjRoot)) { return }
4 |
5 | @{
6 | "$ObjRoot" = (
7 | (Get-ChildItem "$ObjRoot\project.assets.json" -Recurse)
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/tools/artifacts/symbols.ps1:
--------------------------------------------------------------------------------
1 | $BinPath = [System.IO.Path]::GetFullPath("$PSScriptRoot/../../bin")
2 | if (!(Test-Path $BinPath)) { return }
3 | $symbolfiles = & "$PSScriptRoot/../Get-SymbolFiles.ps1" -Path $BinPath | Get-Unique
4 |
5 | @{
6 | "$BinPath" = $SymbolFiles;
7 | }
8 |
--------------------------------------------------------------------------------
/tools/artifacts/testResults.ps1:
--------------------------------------------------------------------------------
1 | [CmdletBinding()]
2 | Param(
3 | )
4 |
5 | $result = @{}
6 |
7 | $testRoot = Resolve-Path "$PSScriptRoot\..\..\test"
8 | $result[$testRoot] = (Get-ChildItem "$testRoot\TestResults" -Recurse -Directory | Get-ChildItem -Recurse -File)
9 |
10 | $artifactStaging = & "$PSScriptRoot/../Get-ArtifactsStagingDirectory.ps1"
11 | $testlogsPath = Join-Path $artifactStaging "test_logs"
12 | if (Test-Path $testlogsPath) {
13 | $result[$testlogsPath] = Get-ChildItem $testlogsPath -Recurse;
14 | }
15 |
16 | $result
17 |
--------------------------------------------------------------------------------
/tools/artifacts/test_symbols.ps1:
--------------------------------------------------------------------------------
1 | $BinPath = [System.IO.Path]::GetFullPath("$PSScriptRoot/../../bin")
2 | if (!(Test-Path $BinPath)) { return }
3 | $symbolfiles = & "$PSScriptRoot/../Get-SymbolFiles.ps1" -Path $BinPath -Tests | Get-Unique
4 |
5 | @{
6 | "$BinPath" = $SymbolFiles;
7 | }
8 |
--------------------------------------------------------------------------------
/tools/publish-CodeCov.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | Uploads code coverage to codecov.io
4 | .PARAMETER CodeCovToken
5 | Code coverage token to use
6 | .PARAMETER PathToCodeCoverage
7 | Path to root of code coverage files
8 | .PARAMETER Name
9 | Name to upload with codecoverge
10 | .PARAMETER Flags
11 | Flags to upload with codecoverge
12 | #>
13 | [CmdletBinding()]
14 | Param (
15 | [Parameter(Mandatory=$true)]
16 | [string]$CodeCovToken,
17 | [Parameter(Mandatory=$true)]
18 | [string]$PathToCodeCoverage,
19 | [string]$Name,
20 | [string]$Flags
21 | )
22 |
23 | $RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path
24 |
25 | Get-ChildItem -Recurse -LiteralPath $PathToCodeCoverage -Filter "*.cobertura.xml" | % {
26 | $relativeFilePath = Resolve-Path -relative $_.FullName
27 |
28 | Write-Host "Uploading: $relativeFilePath" -ForegroundColor Yellow
29 | & (& "$PSScriptRoot/Get-CodeCovTool.ps1") -t $CodeCovToken -f $relativeFilePath -R $RepoRoot -F $Flags -n $Name
30 | }
31 |
--------------------------------------------------------------------------------
/tools/variables/BusinessGroupName.ps1:
--------------------------------------------------------------------------------
1 | 'Visual Studio - VS Core'
2 |
--------------------------------------------------------------------------------
/tools/variables/DotNetSdkVersion.ps1:
--------------------------------------------------------------------------------
1 | $globalJson = Get-Content -LiteralPath "$PSScriptRoot\..\..\global.json" | ConvertFrom-Json
2 | $globalJson.sdk.version
3 |
--------------------------------------------------------------------------------
/tools/variables/InsertJsonValues.ps1:
--------------------------------------------------------------------------------
1 | $vstsDropNames = & "$PSScriptRoot\VstsDropNames.ps1"
2 | $BuildConfiguration = $env:BUILDCONFIGURATION
3 | if (!$BuildConfiguration) {
4 | $BuildConfiguration = 'Debug'
5 | }
6 |
7 | $BasePath = "$PSScriptRoot\..\..\bin\Packages\$BuildConfiguration\Vsix"
8 |
9 | if (Test-Path $BasePath) {
10 | $vsmanFiles = @()
11 | Get-ChildItem $BasePath *.vsman -Recurse -File |% {
12 | $version = (Get-Content $_.FullName | ConvertFrom-Json).info.buildVersion
13 | $fn = $_.Name
14 | $vsmanFiles += "$fn{$version}=https://vsdrop.corp.microsoft.com/file/v1/$vstsDropNames;$fn"
15 | }
16 |
17 | [string]::join(',',$vsmanFiles)
18 | }
19 |
--------------------------------------------------------------------------------
/tools/variables/InsertPropsValues.ps1:
--------------------------------------------------------------------------------
1 | $InsertedPkgs = (& "$PSScriptRoot\..\artifacts\VSInsertion.ps1")
2 |
3 | $icv=@()
4 | foreach ($kvp in $InsertedPkgs.GetEnumerator()) {
5 | $kvp.Value |% {
6 | if ($_.Name -match "^(.*?)\.(\d+\.\d+\.\d+(?:\.\d+)?(?:-.*?)?)(?:\.symbols)?\.nupkg$") {
7 | $id = $Matches[1]
8 | $version = $Matches[2]
9 | $icv += "$id=$version"
10 | }
11 | }
12 | }
13 |
14 | Write-Output ([string]::join(',',$icv))
15 |
--------------------------------------------------------------------------------
/tools/variables/InsertTargetBranch.ps1:
--------------------------------------------------------------------------------
1 | # This is the default branch of the VS repo that we will use to insert into VS.
2 | 'main'
3 |
--------------------------------------------------------------------------------
/tools/variables/InsertVersionsValues.ps1:
--------------------------------------------------------------------------------
1 | # When you need binding redirects in the VS repo updated to match
2 | # assemblies that you build here, remove the "return" statement
3 | # and update the hashtable below with the T4 macro you'll use for
4 | # your libraries as defined in the src\ProductData\AssemblyVersions.tt file.
5 | return
6 |
7 | $MacroName = 'LibraryNoDotsVersion'
8 | $SampleProject = "$PSScriptRoot\..\..\src\LibraryName"
9 | [string]::join(',',(@{
10 | ($MacroName) = & { (dotnet nbgv get-version --project $SampleProject --format json | ConvertFrom-Json).AssemblyVersion };
11 | }.GetEnumerator() |% { "$($_.key)=$($_.value)" }))
12 |
--------------------------------------------------------------------------------
/tools/variables/IsSigned.ps1:
--------------------------------------------------------------------------------
1 | if ($env:SYSTEM_COLLECTIONID -eq 'cb55739e-4afe-46a3-970f-1b49d8ee7564') {
2 | if ($env:BUILD_REASON -eq 'Schedule') {
3 | 'true'
4 | } else {
5 | if ($env:SIGNSELECTION) {
6 | $env:SIGNSELECTION
7 | } else {
8 | 'false'
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/tools/variables/LocLanguages.ps1:
--------------------------------------------------------------------------------
1 | ## For faster PR/CI builds localize only for 2 languages, ENU and JPN provide good enough coverage
2 | if ($env:BUILD_REASON -eq 'PullRequest') {
3 | 'ENU,JPN'
4 | } else {
5 | 'VS'
6 | }
7 |
--------------------------------------------------------------------------------
/tools/variables/ProfilingInputsDropName.ps1:
--------------------------------------------------------------------------------
1 | if ($env:SYSTEM_TEAMPROJECT) {
2 | "ProfilingInputs/$env:SYSTEM_TEAMPROJECT/$env:BUILD_REPOSITORY_NAME/$env:BUILD_SOURCEBRANCHNAME/$env:BUILD_BUILDID"
3 | } else {
4 | Write-Warning "No Azure Pipelines build detected. No Azure Pipelines drop name will be computed."
5 | }
6 |
--------------------------------------------------------------------------------
/tools/variables/SymbolsFeatureName.ps1:
--------------------------------------------------------------------------------
1 | 'Microsoft.Windows.CsWin32'
2 |
--------------------------------------------------------------------------------
/tools/variables/VstsDropNames.ps1:
--------------------------------------------------------------------------------
1 | "Products/$env:SYSTEM_TEAMPROJECT/$env:BUILD_REPOSITORY_NAME/$env:BUILD_SOURCEBRANCHNAME/$env:BUILD_BUILDID"
2 |
--------------------------------------------------------------------------------
/tools/variables/_all.ps1:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env pwsh
2 |
3 | <#
4 | .SYNOPSIS
5 | This script returns a hashtable of build variables that should be set
6 | at the start of a build or release definition's execution.
7 | #>
8 |
9 | [CmdletBinding(SupportsShouldProcess = $true)]
10 | param (
11 | )
12 |
13 | $vars = @{}
14 |
15 | Get-ChildItem "$PSScriptRoot\*.ps1" -Exclude "_*" |% {
16 | Write-Host "Computing $($_.BaseName) variable"
17 | $vars[$_.BaseName] = & $_
18 | }
19 |
20 | $vars
21 |
--------------------------------------------------------------------------------
/tools/variables/_define.ps1:
--------------------------------------------------------------------------------
1 | <#
2 | .SYNOPSIS
3 | This script translates the variables returned by the _all.ps1 script
4 | into commands that instruct Azure Pipelines to actually set those variables for other pipeline tasks to consume.
5 |
6 | The build or release definition may have set these variables to override
7 | what the build would do. So only set them if they have not already been set.
8 | #>
9 |
10 | [CmdletBinding()]
11 | param (
12 | )
13 |
14 | (& "$PSScriptRoot\_all.ps1").GetEnumerator() |% {
15 | # Always use ALL CAPS for env var names since Azure Pipelines converts variable names to all caps and on non-Windows OS, env vars are case sensitive.
16 | $keyCaps = $_.Key.ToUpper()
17 | if ((Test-Path "env:$keyCaps") -and (Get-Content "env:$keyCaps")) {
18 | Write-Host "Skipping setting $keyCaps because variable is already set to '$(Get-Content env:$keyCaps)'." -ForegroundColor Cyan
19 | } else {
20 | Write-Host "$keyCaps=$($_.Value)" -ForegroundColor Yellow
21 | if ($env:TF_BUILD) {
22 | # Create two variables: the first that can be used by its simple name and accessible only within this job.
23 | Write-Host "##vso[task.setvariable variable=$keyCaps]$($_.Value)"
24 | # and the second that works across jobs and stages but must be fully qualified when referenced.
25 | Write-Host "##vso[task.setvariable variable=$keyCaps;isOutput=true]$($_.Value)"
26 | } elseif ($env:GITHUB_ACTIONS) {
27 | Add-Content -LiteralPath $env:GITHUB_ENV -Value "$keyCaps=$($_.Value)"
28 | }
29 | Set-Item -LiteralPath "env:$keyCaps" -Value $_.Value
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3 | "version": "0.3",
4 | "assemblyVersion": {
5 | "precision": "revision"
6 | },
7 | "publicReleaseRefSpec": [
8 | "^refs/heads/main$",
9 | "^refs/heads/v\\d+(?:\\.\\d+)?$"
10 | ],
11 | "cloudBuild": {
12 | "setVersionVariables": false
13 | }
14 | }
15 |
--------------------------------------------------------------------------------