Skip to content

Commit

Permalink
Build a NuGet Package for ConPTY (#12980)
Browse files Browse the repository at this point in the history
This pull request introduces a packaging phase that emits
Microsoft.Windows.Console.ConPTY, a nuget package that contains the
pseudoconsole API as well as the requisite copies of conhost.

* winconpty learned to load a version of OpenConsole.exe specific to the
  processor architecture on its hosting machine
* the package, as well as its contents, is signed properly and is nearly
  ready for distribution via nuget.org
* the API in conpty-static.h has been adjusted to expose
  CreatePseudoConsoleAsUser and stamp out the correct DLL import/export
  annotations.
* getting .NET to play right was somewhat challenging, but I tested this
  against .NET 6.0 and it seemed to work properly; it shipped conpty.dll
  in the right places, and it shipped OpenConsole.exe next to the
  published application.

In the future, we could provide an interop assembly for C# consumers;
that is, unfortunately, out of scope today.

Closes #3577
Closes #3568
Obsoletes #1130
  • Loading branch information
DHowett authored Apr 27, 2022
1 parent 6b936d9 commit 9611433
Show file tree
Hide file tree
Showing 14 changed files with 354 additions and 12 deletions.
1 change: 1 addition & 0 deletions .github/actions/spelling/excludes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ SUMS$
\.xpm$
\.yml$
\.zip$
^build/config/
^consolegit2gitfilters\.json$
^dep/
^doc/reference/master-sequence-list.csv$
Expand Down
2 changes: 2 additions & 0 deletions .github/actions/spelling/expect/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1116,6 +1116,7 @@ Imatch
ime
Imm
IMouse
IMPEXP
impl
inbox
inclusivity
Expand Down Expand Up @@ -2018,6 +2019,7 @@ reparenting
replatformed
Replymessage
repositorypath
Requiresx
rescap
Resequence
RESETCONTENT
Expand Down
51 changes: 51 additions & 0 deletions build/config/ESRPSigning_ConPTY.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"Version": "1.0.0",
"UseMinimatch": false,
"SignBatches": [
{
"MatchedPath": [
"conpty.dll",
"OpenConsole.exe"
],
"SigningInfo": {
"Operations": [
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolSign",
"Parameters": [
{
"parameterName": "OpusName",
"parameterValue": "Microsoft"
},
{
"parameterName": "OpusInfo",
"parameterValue": "http://www.microsoft.com"
},
{
"parameterName": "FileDigest",
"parameterValue": "/fd \"SHA256\""
},
{
"parameterName": "PageHash",
"parameterValue": "/NPH"
},
{
"parameterName": "TimeStamp",
"parameterValue": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
}
],
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-230012",
"OperationSetCode": "SigntoolVerify",
"Parameters": [],
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
}
}
]
}
131 changes: 130 additions & 1 deletion build/pipelines/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ parameters:
displayName: "Build Windows Terminal VPack"
type: boolean
default: false
- name: buildConPTY
displayName: "Build ConPTY NuGet"
type: boolean
default: false
- name: buildWPF
displayName: "Build Terminal WPF Control"
type: boolean
Expand Down Expand Up @@ -75,6 +79,13 @@ variables:
NoNuGetPackBetaVersion: true
${{ else }}:
NuGetPackBetaVersion: preview
# The NuGet packages have to use *somebody's* DLLs. We used to force them to
# use the Win10 build outputs, but if there isn't a Win10 build we should use
# the Win11 one.
${{ if containsValue(parameters.buildWindowsVersions, 'Win10') }}:
TerminalBestVersionForNuGetPackages: Win10
${{ else }}:
TerminalBestVersionForNuGetPackages: Win11

name: $(BuildDefinitionName)_$(date:yyMM).$(date:dd)$(rev:rrr)
resources:
Expand Down Expand Up @@ -208,6 +219,15 @@ jobs:
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /p:WindowsTerminalReleaseBuild=true /t:Terminal\wpf\PublicTerminalCore
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
- ${{ if eq(parameters.buildConPTY, true) }}:
- task: VSBuild@1
displayName: Build solution **\OpenConsole.sln for ConPTY
inputs:
solution: '**\OpenConsole.sln'
vsVersion: 16.0
msbuildArgs: /p:WindowsTerminalOfficialBuild=true /p:WindowsTerminalBranding=${{ parameters.branding }};PGOBuildMode=${{ parameters.pgoBuildMode }} /p:WindowsTerminalReleaseBuild=true /t:Conhost\Host_EXE;Conhost\winconpty_DLL
platform: $(BuildPlatform)
configuration: $(BuildConfiguration)
- task: PowerShell@2
displayName: Source Index PDBs
inputs:
Expand Down Expand Up @@ -252,6 +272,24 @@ jobs:
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/appx
ArtifactName: appx-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
- ${{ if eq(parameters.buildConPTY, true) }}:
- task: CopyFiles@2
displayName: Copy ConPTY to Artifacts
inputs:
Contents: |-
$(Build.SourcesDirectory)/bin/**/conpty.dll
$(Build.SourcesDirectory)/bin/**/conpty.lib
$(Build.SourcesDirectory)/bin/**/conpty.pdb
$(Build.SourcesDirectory)/bin/**/OpenConsole.exe
$(Build.SourcesDirectory)/bin/**/OpenConsole.pdb
TargetFolder: $(Build.ArtifactStagingDirectory)/conpty
OverWrite: true
flattenFolders: true
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (ConPTY)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)/conpty
ArtifactName: conpty-dll-$(BuildPlatform)-$(BuildConfiguration)-$(TerminalTargetWindowsVersion)
- ${{ if eq(parameters.buildWPF, true) }}:
- task: CopyFiles@2
displayName: Copy PublicTerminalCore.dll to Artifacts
Expand Down Expand Up @@ -358,6 +396,97 @@ jobs:
PathtoPublish: $(System.ArtifactsDirectory)
ArtifactName: appxbundle-signed-$(TerminalTargetWindowsVersion)

- ${{ if eq(parameters.buildConPTY, true) }}:
- job: PackageAndSignConPTY
strategy:
matrix:
${{ each config in parameters.buildConfigurations }}:
${{ config }}:
BuildConfiguration: ${{ config }}
displayName: Create NuGet Package (ConPTY)
dependsOn: Build
steps:
- checkout: self
clean: true
fetchDepth: 1
submodules: true
persistCredentials: True
- task: PkgESSetupBuild@12
displayName: Package ES - Setup Build
inputs:
disableOutputRedirect: true
- ${{ each platform in parameters.buildPlatforms }}:
- task: DownloadBuildArtifacts@0
displayName: Download ${{ platform }} ConPTY binaries
inputs:
artifactName: conpty-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
extractTars: false
- task: PowerShell@2
displayName: Move downloaded artifacts around
inputs:
targetType: inline
# Find all artifact files and move them up a directory. Ugh.
script: |-
Get-ChildItem bin -Recurse -Directory -Filter conpty-dll-* | % {
$_ | Get-ChildItem -Recurse -File | % {
Move-Item -Verbose $_.FullName $_.Directory.Parent.FullName
}
}
Move-Item bin\x86 bin\Win32
- task: EsrpCodeSigning@1
displayName: Submit ConPTY libraries and OpenConsole for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: '$(Build.SourcesDirectory)/bin'
signType: batchSigning
batchSignPolicyFile: '$(Build.SourcesDirectory)\build\config\ESRPSigning_ConPTY.json'

- task: NuGetToolInstaller@1
displayName: Use NuGet 5.10.0
inputs:
versionSpec: 5.10.0
- task: NuGetCommand@2
displayName: NuGet pack
inputs:
command: pack
packagesToPack: $(Build.SourcesDirectory)\src\winconpty\package\winconpty.nuspec
packDestination: '$(Build.ArtifactStagingDirectory)/nupkg'
versioningScheme: byEnvVar
versionEnvVar: XES_PACKAGEVERSIONNUMBER
- task: EsrpCodeSigning@1
displayName: Submit *.nupkg to ESRP for code signing
inputs:
ConnectedServiceName: 9d6d2960-0793-4d59-943e-78dcb434840a
FolderPath: $(Build.ArtifactStagingDirectory)/nupkg
Pattern: '*.nupkg'
UseMinimatch: true
signConfigType: inlineSignParams
inlineOperation: >-
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
},
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetVerify",
"Parameters": {},
"ToolName": "sign",
"ToolVersion": "1.0"
}
]
- task: PublishBuildArtifacts@1
displayName: Publish Artifact (nupkg)
inputs:
PathtoPublish: $(Build.ArtifactStagingDirectory)\nupkg
ArtifactName: conpty-nupkg-$(BuildConfiguration)


- ${{ if eq(parameters.buildWPF, true) }}:
- job: PackageAndSignWPF
strategy:
Expand All @@ -381,7 +510,7 @@ jobs:
- task: DownloadBuildArtifacts@0
displayName: Download ${{ platform }} PublicTerminalCore
inputs:
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)-Win10
artifactName: wpf-dll-${{ platform }}-$(BuildConfiguration)-$(TerminalBestVersionForNuGetPackages)
itemPattern: '**/*.dll'
downloadPath: bin\${{ platform }}\$(BuildConfiguration)\
extractTars: false
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalConnection/TerminalConnection.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,8 @@
<Import Project="$(OpenConsoleDir)src\cppwinrt.build.post.props" />
<ItemDefinitionGroup>
<ClCompile>
<!-- By defining this here, we ensure that we don't try to dllimport conpty -->
<PreprocessorDefinitions>CONPTY_IMPEXP=;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(IntDir)..\OpenConsoleProxy;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
Expand Down
2 changes: 2 additions & 0 deletions src/host/ft_host/Host.FeatureTests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
</ItemGroup>
<ItemDefinitionGroup>
<ClCompile>
<!-- By defining this here, we ensure that we don't try to dllimport conpty -->
<PreprocessorDefinitions>CONPTY_IMPEXP=;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
Expand Down
28 changes: 17 additions & 11 deletions src/inc/conpty-static.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,34 @@

#include <consoleapi.h>

#ifndef CONPTY_IMPEXP
#define CONPTY_IMPEXP __declspec(dllimport)
#endif

#ifndef CONPTY_EXPORT
#ifdef __cplusplus
extern "C" {
#define CONPTY_EXPORT extern "C" CONPTY_IMPEXP
#else
#define CONPTY_EXPORT extern CONPTY_IMPEXP
#endif
#endif

#define PSEUDOCONSOLE_RESIZE_QUIRK (2u)
#define PSEUDOCONSOLE_WIN32_INPUT_MODE (4u)
#define PSEUDOCONSOLE_PASSTHROUGH_MODE (8u)

HRESULT WINAPI ConptyCreatePseudoConsole(COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON* phPC);
CONPTY_EXPORT HRESULT WINAPI ConptyCreatePseudoConsole(COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON* phPC);

HRESULT WINAPI ConptyResizePseudoConsole(HPCON hPC, COORD size);
CONPTY_EXPORT HRESULT WINAPI ConptyCreatePseudoConsoleAsUser(HANDLE hToken, COORD size, HANDLE hInput, HANDLE hOutput, DWORD dwFlags, HPCON* phPC);

HRESULT WINAPI ConptyClearPseudoConsole(HPCON hPC);
CONPTY_EXPORT HRESULT WINAPI ConptyResizePseudoConsole(HPCON hPC, COORD size);

HRESULT WINAPI ConptyShowHidePseudoConsole(HPCON hPC, bool show);
CONPTY_EXPORT HRESULT WINAPI ConptyClearPseudoConsole(HPCON hPC);

HRESULT WINAPI ConptyReparentPseudoConsole(HPCON hPC, HWND newParent);
CONPTY_EXPORT HRESULT WINAPI ConptyShowHidePseudoConsole(HPCON hPC, bool show);

VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);
CONPTY_EXPORT HRESULT WINAPI ConptyReparentPseudoConsole(HPCON hPC, HWND newParent);

HRESULT WINAPI ConptyPackPseudoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);
CONPTY_EXPORT VOID WINAPI ConptyClosePseudoConsole(HPCON hPC);

#ifdef __cplusplus
}
#endif
CONPTY_EXPORT HRESULT WINAPI ConptyPackPseudoConsole(HANDLE hServerProcess, HANDLE hRef, HANDLE hSignal, HPCON* phPC);
13 changes: 13 additions & 0 deletions src/winconpty/dll/winconpty.def
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
EXPORTS
; Plain old normal aliases
ConptyCreatePseudoConsole
ConptyCreatePseudoConsoleAsUser
ConptyResizePseudoConsole
ConptyClosePseudoConsole
ConptyClearPseudoConsole
ConptyShowHidePseudoConsole
ConptyReparentPseudoConsole
ConptyPackPseudoConsole

; Compatibility aliases for P/Invoke; only required for compatibility
; with the ConPTY surface exported from kernel32.
; New consumers are expected to use the Conpty* versions
CreatePseudoConsole = ConptyCreatePseudoConsole
ResizePseudoConsole = ConptyResizePseudoConsole
ClosePseudoConsole = ConptyClosePseudoConsole
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<!-- C# uses normalizes PlatformTarget, whereas C++ does not normalize Platform -->
<ConptyNativePlatform Condition="'$(ConptyNativePlatform)'==''">$(PlatformTarget)</ConptyNativePlatform>
<ConptyNativePlatform Condition="'$(ConptyNativePlatform)'==''">$(Platform)</ConptyNativePlatform>
<ConptyNativePlatform Condition="'$(ConptyNativePlatform)'=='Win32'">x86</ConptyNativePlatform>

<!-- x86 can run on x64 and ARM64, so needs to ship all three OpenConsoles. -->
<ConptyRequiresx86Host Condition="'$(ConptyNativePlatform)' == 'x86'">true</ConptyRequiresx86Host>
<ConptyRequiresx64Host Condition="'$(ConptyNativePlatform)' == 'x86'">true</ConptyRequiresx64Host>
<ConptyRequiresARM64Host Condition="'$(ConptyNativePlatform)' == 'x86'">true</ConptyRequiresARM64Host>

<!-- x64 can only run on x64 and ARM64, so needs to ship only two OpenConsoles. -->
<!-- ConptyRequiresx86Host not set -->
<ConptyRequiresx64Host Condition="'$(ConptyNativePlatform)' == 'x64'">true</ConptyRequiresx64Host>
<ConptyRequiresARM64Host Condition="'$(ConptyNativePlatform)' == 'x64'">true</ConptyRequiresARM64Host>

<!-- ARM64 can only run on ARM64, so only needs to ship the final OpenConsole. -->
<!-- ConptyRequiresx86Host not set -->
<!-- ConptyRequiresx64Host not set -->
<ConptyRequiresARM64Host Condition="'$(ConptyNativePlatform)' == 'ARM64'">true</ConptyRequiresARM64Host>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Condition="'$(ConptyRequiresx86Host)'=='true'" Include="$(MSBuildThisFileDirectory)\native\runtimes\x86\OpenConsole.exe">
<Link>x86\OpenConsole.exe</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</None>
<None Condition="'$(ConptyRequiresx64Host)'=='true'" Include="$(MSBuildThisFileDirectory)\native\runtimes\x64\OpenConsole.exe">
<Link>x64\OpenConsole.exe</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</None>
<None Condition="'$(ConptyRequiresARM64Host)'=='true'" Include="$(MSBuildThisFileDirectory)\native\runtimes\arm64\OpenConsole.exe">
<Link>arm64\OpenConsole.exe</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</None>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildThisProjectDirectory)\..\Microsoft.Windows.Console.ConPTY.props" />
</Project>
Loading

0 comments on commit 9611433

Please sign in to comment.