Skip to content

Commit 46177d4

Browse files
committed
Add initial Appx/Msix support, starting with preprovisioning.
This is done using a combination of WinRT and COM, using all publicly available APIs. The APIs used in the Dism PowerShell module are non-public and therefore avoided while there's a supported mechanism.
1 parent 8817277 commit 46177d4

9 files changed

Lines changed: 354 additions & 8 deletions

File tree

.github/copilot-instructions.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,8 @@ The main build dependency is a current .NET SDK. Visual Studio is recommended fo
5555
- `PSADT.Interop` contains Win32 interop and CsWin32-generated symbols.
5656
- `PSADT` contains core C# utilities.
5757
- `PSAppDeployToolkit` contains PowerShell-facing C# types.
58+
59+
## API Usage Guidelines
60+
61+
- Expect accurate, well-researched answers about Windows APIs and COM interfaces. Do not fabricate API names or suggest hacky workarounds when proper documented APIs exist (e.g., Appx COM interfaces for reading package identity).
62+
- Acknowledge uncertainty rather than inventing answers.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace PSADT.Interop
2+
{
3+
/// <summary>
4+
/// Specifies the processor architectures supported by a package.
5+
/// </summary>
6+
[System.Diagnostics.CodeAnalysis.SuppressMessage("Naming", "CA1712:Do not prefix enum values with type name", Justification = "This is how it's named in the Win32 API.")]
7+
public enum APPX_PACKAGE_ARCHITECTURE
8+
{
9+
/// <summary>
10+
/// The x86 processor architecture.
11+
/// </summary>
12+
APPX_PACKAGE_ARCHITECTURE_X86 = Windows.Win32.Storage.Packaging.Appx.APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_X86,
13+
14+
/// <summary>
15+
/// The ARM processor architecture.
16+
/// </summary>
17+
APPX_PACKAGE_ARCHITECTURE_ARM = Windows.Win32.Storage.Packaging.Appx.APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_ARM,
18+
19+
/// <summary>
20+
/// The x64 processor architecture.
21+
/// </summary>
22+
APPX_PACKAGE_ARCHITECTURE_X64 = Windows.Win32.Storage.Packaging.Appx.APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_X64,
23+
24+
/// <summary>
25+
/// Any processor architecture.
26+
/// </summary>
27+
APPX_PACKAGE_ARCHITECTURE_NEUTRAL = Windows.Win32.Storage.Packaging.Appx.APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_NEUTRAL,
28+
29+
/// <summary>
30+
/// The 64-bit ARM processor architecture.
31+
/// </summary>
32+
APPX_PACKAGE_ARCHITECTURE_ARM64 = Windows.Win32.Storage.Packaging.Appx.APPX_PACKAGE_ARCHITECTURE.APPX_PACKAGE_ARCHITECTURE_ARM64,
33+
}
34+
}

src/PSADT/PSADT.Interop/NativeMethods.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4315,6 +4315,23 @@ internal static HRESULT CoCreateInstance<T>(in Guid rclsid, CLSCTX dwClsContext,
43154315
return res != HRESULT.S_OK ? throw ExceptionUtilities.GetException(res) : res;
43164316
}
43174317

4318+
/// <summary>
4319+
/// Creates and initializes a stream object that is associated with a specified file. The stream object can be used
4320+
/// to read from or write to the file.
4321+
/// </summary>
4322+
/// <param name="pszFile">The path of the file to be associated with the stream object.</param>
4323+
/// <param name="grfMode">The access mode for the stream object.</param>
4324+
/// <param name="dwAttributes">The file attributes for the file.</param>
4325+
/// <param name="fCreate">Indicates whether to create the file if it does not exist.</param>
4326+
/// <param name="pstmTemplate">A pointer to an existing stream object to be used as a template.</param>
4327+
/// <param name="ppstm">When this method returns, contains the interface pointer to the stream object.</param>
4328+
/// <returns>An HRESULT value indicating the success or failure of the operation.</returns>
4329+
internal static HRESULT SHCreateStreamOnFileEx(string pszFile, STGM grfMode, FileAttributes dwAttributes, BOOL fCreate, [Optional] IStream? pstmTemplate, out IStream ppstm)
4330+
{
4331+
HRESULT res = PInvoke.SHCreateStreamOnFileEx(pszFile.ThrowIfFileDoesNotExist(), (uint)grfMode, (uint)dwAttributes, fCreate, pstmTemplate, out ppstm);
4332+
return res != HRESULT.S_OK ? throw ExceptionUtilities.GetException(res) : res;
4333+
}
4334+
43184335
/// <summary>
43194336
/// Lookup table for system information class struct sizes.
43204337
/// </summary>

src/PSADT/PSADT.Interop/NativeMethods.txt

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
AdjustTokenPrivileges
33
APPLICATION_USER_MODEL_ID_MAX_LENGTH
44
APPLICATION_USER_MODEL_ID_MIN_LENGTH
5+
AppxBundleFactory
6+
AppxFactory
57
AssignProcessToJobObject
68
AttachThreadInput
79
AUTHZ_COMPUTE_PRIVILEGES
@@ -107,6 +109,13 @@ HTTRANSPARENT
107109
HTVSCROLL
108110
HTZOOM
109111
HWND_BROADCAST
112+
IAppxBundleFactory
113+
IAppxBundleManifestReader
114+
IAppxBundleReader
115+
IAppxFactory
116+
IAppxManifestPackageId
117+
IAppxManifestReader
118+
IAppxPackageReader
110119
IAudioSessionManager2
111120
IDWriteFactory
112121
IExecAction
@@ -121,8 +130,8 @@ IMAGE_RESOURCE_DATA_IS_DIRECTORY
121130
IMAGE_RESOURCE_DIRECTORY
122131
IMAGE_RESOURCE_DIRECTORY_ENTRY
123132
IMMDeviceEnumerator
124-
INFOTIPSIZE
125133
INFINITE
134+
INFOTIPSIZE
126135
InitializeAcl
127136
InitializeProcThreadAttributeList
128137
INVALID_FILE_ATTRIBUTES
@@ -284,8 +293,6 @@ POLICY_VIEW_AUDIT_INFORMATION
284293
POLICY_VIEW_LOCAL_INFORMATION
285294
POOL_TYPE
286295
PostQueuedCompletionStatus
287-
PROPERTYKEY
288-
PropVariantClear
289296
PROC_THREAD_ATTRIBUTE_ADDITIVE
290297
PROC_THREAD_ATTRIBUTE_ALL_APPLICATION_PACKAGES_POLICY
291298
PROC_THREAD_ATTRIBUTE_CHILD_PROCESS_POLICY
@@ -314,6 +321,8 @@ PROCESS_ACCESS_RIGHTS
314321
PROCESS_BASIC_INFORMATION
315322
PROCESS_INFORMATION
316323
ProcessIdToSessionId
324+
PROPERTYKEY
325+
PropVariantClear
317326
PUBLIC_OBJECT_BASIC_INFORMATION
318327
QueryDosDevice
319328
QueryFullProcessImageName
@@ -424,6 +433,7 @@ SetNamedSecurityInfo
424433
SetSecurityInfo
425434
SetTokenInformation
426435
SHChangeNotify
436+
SHCreateStreamOnFileEx
427437
SHELL_LINK_DATA_FLAGS
428438
ShellLink
429439
SHGetImageList
@@ -435,18 +445,17 @@ SHIL_JUMBO
435445
SHIL_LARGE
436446
SHIL_LAST
437447
SHIL_SMALL
438-
SLGP_FLAGS
439448
SHIL_SYSSMALL
440449
ShowWindow
441450
SHQueryUserNotificationState
442451
SHSTOCKICONID
452+
SLGP_FLAGS
443453
SLR_FLAGS
444454
STARTUPINFOEXW
445455
STATUS_ABANDON_HIBERFILE
446456
STATUS_ABANDONED
447457
STATUS_ABANDONED_WAIT_0
448458
STATUS_ABANDONED_WAIT_63
449-
STGM
450459
STATUS_ACCESS_AUDIT_BY_POLICY
451460
STATUS_ACCESS_DENIED
452461
STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT
@@ -2108,6 +2117,7 @@ STATUS_WX86_UNSIMULATE
21082117
STATUS_XML_ENCODING_MISMATCH
21092118
STATUS_XML_PARSE_ERROR
21102119
STATUS_XMLDSIG_ERROR
2120+
STGM
21112121
TASK_CREATION
21122122
TaskDialog
21132123
TaskScheduler
@@ -2143,9 +2153,9 @@ VER_SUITE_TERMINAL
21432153
VER_SUITE_WH_SERVER
21442154
VerLanguageName
21452155
VerQueryValue
2156+
VIRTUAL_KEY
21462157
VirtualAlloc
21472158
VirtualFree
2148-
VIRTUAL_KEY
21492159
VS_FIXEDFILEINFO
21502160
WaitForSingleObject
21512161
Windows.Win32.UI.Controls.IImageList
@@ -2353,11 +2363,11 @@ WM_WININICHANGE
23532363
WritePrivateProfileSection
23542364
WritePrivateProfileString
23552365
WTS_CURRENT_SERVER_HANDLE
2366+
WTS_PROCESS_INFO_EXW
2367+
WTS_PROCESS_INFOW
23562368
WTS_PROTOCOL_TYPE_CONSOLE
23572369
WTS_PROTOCOL_TYPE_ICA
23582370
WTS_PROTOCOL_TYPE_RDP
2359-
WTS_PROCESS_INFO_EXW
2360-
WTS_PROCESS_INFOW
23612371
WTS_SESSION_INFO_1W
23622372
WTSEnumerateSessionsEx
23632373
WTSFreeMemory

src/PSADT/PSADT.Interop/PSADT.Interop.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
<InternalsVisibleTo Include="PSADT.UserInterface" />
2323
<InternalsVisibleTo Include="PSADT.UserInterface.Interfaces" />
2424
<InternalsVisibleTo Include="PSADT.UserInterface.TestHarness" />
25+
<InternalsVisibleTo Include="PSADT.WindowsRuntime" />
2526
<InternalsVisibleTo Include="PSAppDeployToolkit" />
2627
</ItemGroup>
2728

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
using Windows.Win32.Storage.Packaging.Appx;
3+
4+
namespace PSADT.WindowsRuntime.Management.Deployment
5+
{
6+
/// <summary>
7+
/// Represents information about a Windows Runtime package.
8+
/// </summary>
9+
public sealed record ManifestInformation
10+
{
11+
/// <summary>
12+
/// Initializes a new instance of the <see cref="ManifestInformation"/> record based on the provided <see cref="IAppxManifestPackageId"/>.
13+
/// </summary>
14+
/// <param name="packageId">The package ID from which to initialize the package information.</param>
15+
internal ManifestInformation(IAppxManifestPackageId packageId)
16+
{
17+
Name = packageId.GetName().ToString();
18+
Architecture = (Interop.APPX_PACKAGE_ARCHITECTURE)packageId.GetArchitecture();
19+
Publisher = packageId.GetPublisher().ToString();
20+
ulong versionValue = packageId.GetVersion();
21+
Version = new((int)(versionValue >> 48), (int)((versionValue >> 32) & 0xFFFF), (int)((versionValue >> 16) & 0xFFFF), (int)(versionValue & 0xFFFF));
22+
ResourceId = packageId.GetResourceId().ToString();
23+
PackageFullName = packageId.GetPackageFullName().ToString();
24+
PackageFamilyName = packageId.GetPackageFamilyName().ToString();
25+
}
26+
27+
/// <summary>
28+
/// Gets the name of the package as defined in the manifest.
29+
/// </summary>
30+
public string Name { get; }
31+
32+
/// <summary>
33+
/// Gets the processor architecture as defined in the manifest.
34+
/// </summary>
35+
public Interop.APPX_PACKAGE_ARCHITECTURE Architecture { get; }
36+
37+
/// <summary>
38+
/// Gets the name of the package publisher as defined in the manifest.
39+
/// </summary>
40+
public string Publisher { get; }
41+
42+
/// <summary>
43+
/// Gets the version of the package as defined in the manifest.
44+
/// </summary>
45+
public Version Version { get; }
46+
47+
/// <summary>
48+
/// Gets the package resource identifier as defined in the manifest.
49+
/// </summary>
50+
public string ResourceId { get; }
51+
52+
/// <summary>
53+
/// Gets the package full name.
54+
/// </summary>
55+
public string PackageFullName { get; }
56+
57+
/// <summary>
58+
/// Gets the package family name.
59+
/// </summary>
60+
public string PackageFamilyName { get; }
61+
}
62+
}

0 commit comments

Comments
 (0)