Created
October 27, 2016 01:45
-
-
Save jcotton42/b807966a9ecfb4ca925bad24ae658c6b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Collections.ObjectModel; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using Microsoft.Win32.SafeHandles; | |
using static JCotton.ManagedDismapi.Interop.NativeMethods; | |
[module: DefaultCharSet(CharSet.Unicode)] | |
namespace JCotton.ManagedDismapi.Interop | |
{ | |
public delegate void DismProgressCallback( | |
uint current, | |
uint total, | |
IntPtr userData | |
); | |
public static class NativeMethods { | |
public const string DISMAPI = "dismapi"; | |
#region Constants | |
public const string DISM_ONLINE_IMAGE = "DISM_{53BFAE52-B167-4E2F-A258-0A37B57FF845}"; | |
public const uint DISM_SESSION_DEFAULT = 0; | |
#region Success codes | |
/// The operation completed successfully | |
public const int S_OK = 0; | |
/// The machine needs to be restarted | |
public const int ERROR_SUCCESS_REBOOT_REQUIRED = 3010; | |
/// The DISM session needs to be reloaded. | |
public const int DISMAPI_S_RELOAD_IMAGE_SESSION_REQUIRED = 0x00000001; | |
#endregion Success codes | |
#region Failure codes | |
public const int DISMAPI_E_DISMAPI_ALREADY_INITIALIZED = 1; | |
/// The requested operation requires elevation | |
public const int ERROR_ELEVATION_REQUIRED_HR = unchecked((int)0x800702E4); | |
/// DISM API was not initialized for this process | |
public const int DISMAPI_E_DISMAPI_NOT_INITIALIZED = unchecked((int)0xC0040001); | |
/// A DismSession was being shutdown when another operation was called on it | |
public const int DISMAPI_E_SHUTDOWN_IN_PROGRESS = unchecked((int)0xC0040002); | |
/// A DismShutdown was called while there were open DismSession handles | |
public const int DISMAPI_E_OPEN_SESSION_HANDLES = unchecked((int)0xC0040003); | |
/// An invalid DismSession handle was passed into a DISMAPI function | |
public const int DISMAPI_E_INVALID_DISM_SESSION = unchecked((int)0xC0040004); | |
/// An invalid image index was specified | |
public const int DISMAPI_E_INVALID_IMAGE_INDEX = unchecked((int)0xC0040005); | |
/// An invalid image name was specified | |
public const int DISMAPI_E_INVALID_IMAGE_NAME = unchecked((int)0xC0040006); | |
/// An image that is not a mounted WIM or mounted VHD was attempted to be unmounted | |
public const int DISMAPI_E_UNABLE_TO_UNMOUNT_IMAGE_PATH = unchecked((int)0xC0040007); | |
/// Failed to gain access to the log file user specified. Logging has been disabled.. | |
public const int DISMAPI_E_LOGGING_DISABLED = unchecked((int)0xC0040009); | |
/// A DismSession with open handles was attempted to be unmounted | |
public const int DISMAPI_E_OPEN_HANDLES_UNABLE_TO_UNMOUNT_IMAGE_PATH = unchecked((int)0xC004000A); | |
/// A DismSession with open handles was attempted to be mounted | |
public const int DISMAPI_E_OPEN_HANDLES_UNABLE_TO_MOUNT_IMAGE_PATH = unchecked((int)0xC004000B); | |
/// A DismSession with open handles was attempted to be remounted | |
public const int DISMAPI_E_OPEN_HANDLES_UNABLE_TO_REMOUNT_IMAGE_PATH = unchecked((int)0xC004000C); | |
/// One or several parent features are disabled so current feature can not be enabled. | |
/// Solutions: | |
/// 1 Call function DismGetFeatureParent to get all parent features and enable all of them. Or | |
/// 2 Set EnableAll to TRUE when calling function DismEnableFeature. | |
public const int DISMAPI_E_PARENT_FEATURE_DISABLED = unchecked((int)0xC004000D); | |
/// The offline image specified is the running system. The macro DISM_ONLINE_IMAGE must be | |
/// used instead. | |
public const int DISMAPI_E_MUST_SPECIFY_ONLINE_IMAGE = unchecked((int)0xC004000E); | |
/// The specified product key could not be validated. Check that the specified | |
/// product key is valid and that it matches the target edition. | |
public const int DISMAPI_E_INVALID_PRODUCT_KEY = unchecked((int)0xC004000F); | |
/// The image needs to be remounted before any servicing operation. | |
public const int DISMAPI_E_NEEDS_REMOUNT = unchecked((int)0XC1510114); | |
/// The feature is not present in the package. | |
public const int DISMAPI_E_UNKNOWN_FEATURE = unchecked((int)0x800f080c); | |
/// The current package and feature servicing infrastructure is busy. Wait a | |
/// bit and try the operation again. | |
public const int DISMAPI_E_BUSY = unchecked((int)0x800f0902); | |
public const int E_HR_REQUEST_ABORTED = unchecked((int)0x800704D3); | |
#endregion Failure codes | |
#endregion Constants | |
#region Support functions | |
public static Collection<T> PtrToCollection<T>(IntPtr ptr, uint count) | |
=> PtrToCollection<T>(ptr, count, Marshal.SizeOf<T>(), Marshal.PtrToStructure<T>); | |
public static Collection<T> PtrToCollection<T>(IntPtr ptr, uint count, int size, Func<IntPtr, T> marshaller) { | |
var items = new Collection<T>(); | |
for(var i = 0; i < count; i++) { | |
items.Add(marshaller(ptr)); | |
ptr += size; | |
} | |
return items; | |
} | |
public static IntPtr CollectionToPtr<T>(ICollection<T> collection) | |
=> CollectionToPtr<T>(collection, (item, ptr) => Marshal.StructureToPtr(item, ptr, false)); | |
public static IntPtr CollectionToPtr<T>(ICollection<T> collection, Action<T, IntPtr> marshaller) { | |
var size = Marshal.SizeOf<T>(); | |
var ptr = Marshal.AllocHGlobal(size * collection.Count); | |
var p = ptr; | |
foreach(var item in collection) { | |
marshaller(item, p); | |
p += size; | |
} | |
return ptr; | |
} | |
#endregion | |
#region Imported functions | |
[DllImport(DISMAPI)] | |
public static extern int DismInitialize( | |
LogLevel logLevel, | |
[Optional] string logFilePath, | |
[Optional] string scratchDirectory | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismShutdown(); | |
[DllImport(DISMAPI)] | |
public static extern int DismMountImage( | |
string imageFilePath, | |
string mountPath, | |
uint imageIndex, | |
[Optional] string imageName, | |
ImageIdentifier imageIdentifier, | |
MountFlags flags, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismUnmountImage( | |
string mountPath, | |
UnmountFlags flags, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismOpenSession( | |
string imagePath, | |
[Optional] string windowsDirectory, | |
[Optional] string systemDrive, | |
out uint session | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismCloseSession( | |
uint session | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetLastErrorMessage( | |
out IntPtr errorMessage | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismRemountImage( | |
string mountPath | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismCommitImage( | |
uint session, | |
CommitFlags flags, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetImageInfo( | |
string imageFilePath, | |
out IntPtr imageInfo, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetMountedImageInfo( | |
out IntPtr mountedImageInfo, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismCleanupMountpoints(); | |
[DllImport(DISMAPI)] | |
public static extern int DismCheckImageHealth( | |
uint session, | |
bool scanImage, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData, | |
out ImageHealthState imageHealthState | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismRestoreImageHealth( | |
uint session, | |
[Optional] string[] sourcePaths, | |
[Optional] uint sourcePathCount, | |
bool limitAccess, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismDelete( | |
IntPtr structure | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismAddPackage( | |
uint session, | |
string packagePath, | |
bool ignoreCheck, | |
bool preventPending, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismRemovePackage( | |
uint session, | |
string identifier, | |
PackageIdentifier packageIdentifier, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismEnableFeature( | |
uint session, | |
string featureName, | |
[Optional] string identifier, | |
[Optional] PackageIdentifier packageIdentifier, | |
bool limitAccess, | |
[Optional] string[] sourcePaths, | |
[Optional] uint sourcePathCount, | |
bool enableAll, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismDisableFeature( | |
uint session, | |
string featureName, | |
[Optional] string packageName, | |
bool removePayload, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetPackages( | |
uint session, | |
out IntPtr packages, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetPackageInfoEx( | |
uint session, | |
string identifier, | |
PackageIdentifier packageIdentifier, | |
out IntPtr packageInfoEx | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetFeatures( | |
uint session, | |
[Optional] string identifer, | |
[Optional] PackageIdentifier packageIdentifier, | |
out IntPtr features, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetFeatureInfo( | |
uint session, | |
string featureName, | |
[Optional] string identifier, | |
[Optional] PackageIdentifier packageIdentifier, | |
out IntPtr featureInfo | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetFeatureParent( | |
uint session, | |
string featureName, | |
[Optional] string identifier, | |
[Optional] PackageIdentifier packageIdentifier, | |
out IntPtr features, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismApplyUnattend( | |
uint session, | |
string unattendFile, | |
bool singleSession | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismAddDriver( | |
uint seesion, | |
string driverPath, | |
bool forceUnsigned | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismRemoveDriver( | |
uint session, | |
string driverPath | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetDrivers( | |
uint session, | |
bool allDrivers, | |
out IntPtr driverPakcages, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetDriverInfo( | |
uint session, | |
string driverPath, | |
out IntPtr drivers, | |
out uint count, | |
[Optional] out IntPtr driverPackage | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetCapabilities( | |
uint session, | |
out IntPtr capabilities, | |
out uint count | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismGetCapabilityInfo( | |
uint session, | |
string name, | |
out IntPtr info | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismAddCapability( | |
uint session, | |
string name, | |
bool limitAccess, | |
[Optional] string[] sourcePaths, | |
[Optional] uint sourcePathCount, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
[DllImport(DISMAPI)] | |
public static extern int DismRemoveCapability( | |
uint session, | |
string name, | |
[Optional] SafeWaitHandle cancelEvent, | |
[Optional] DismProgressCallback progress, | |
[Optional] IntPtr userData | |
); | |
#endregion | |
} | |
[Flags] | |
public enum MountFlags : uint { | |
ReadWrite = 0x0, | |
ReadOnly = 0x1, | |
Optimize = 0x2, | |
CheckIntegrity = 0x4 | |
} | |
[Flags] | |
public enum UnmountFlags : uint { | |
Commit = 0x0, | |
Discard = 0x1 | |
} | |
[Flags] | |
public enum CommitFlags : uint { | |
GenerateIntegrity = 0x10000, | |
Append = 0x20000 | |
} | |
public enum LogLevel { | |
Errors = 0, | |
ErrorsAndWarnings, | |
ErrorsAndWarningsAndInfo | |
} | |
public enum ImageIdentifier { | |
Index = 0, | |
Name | |
} | |
public enum MountMode { | |
ReadWrite = 0, | |
ReadOnly | |
} | |
public enum ImageType { | |
Unsupported = -1, | |
WIM = 0, | |
VHD = 1 | |
} | |
public enum MountStatus { | |
OK, | |
NeedsRemount, | |
Invalid | |
} | |
public enum ImageHealthState { | |
Healthy, | |
Repairable, | |
NonRepairable | |
} | |
public enum PackageIdentifier { | |
None, | |
Name, | |
Path | |
} | |
public enum PackageFeatureState { | |
NotPresent, | |
UninstallPending, | |
Staged, | |
Resolved, | |
Removed = Resolved, | |
Installed, | |
InstallPending, | |
Superseded, | |
PartiallyInstalled | |
} | |
public enum ReleaseType { | |
CriticalUpdate, | |
Driver, | |
FeaturePack, | |
Hotfix, | |
SecurityUpdate, | |
SoftwareUpdate, | |
Update, | |
UpdateRollup, | |
LanguagePack, | |
Foundation, | |
ServicePack, | |
Product, | |
LocalPack, | |
Other | |
} | |
public enum RestartType { | |
No, | |
Possible, | |
Required | |
} | |
public enum FullyOfflineInstallableType { | |
Installable, | |
NotInstallable, | |
Undetermined | |
} | |
public enum ImageBootability { | |
Yes, | |
No, | |
Unknown | |
} | |
public enum DriverSignature { | |
Unknown, | |
Unsigned, | |
Signed | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
internal struct SYSTEMTIME { | |
public ushort Year; | |
public ushort Month; | |
public ushort DayOfWeek; | |
public ushort Day; | |
public ushort Hour; | |
public ushort Minute; | |
public ushort Second; | |
public ushort Millisecond; | |
public DateTime ToDateTime() => new DateTime(Year, Month, Day, Hour, Minute, Second, Millisecond); | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] | |
internal struct DismCustomProperty { | |
[MarshalAs(UnmanagedType.LPWStr)] public string Name; | |
[MarshalAs(UnmanagedType.LPWStr)] public string Value; | |
[MarshalAs(UnmanagedType.LPWStr)] public string Path; | |
} | |
public sealed class WindowsPackage { | |
internal WindowsPackage() {} | |
public string PackageName { get; private set; } | |
public PackageFeatureState State { get; private set; } | |
public ReleaseType ReleaseType { get; private set; } | |
public DateTime InstallTime { get; private set; } | |
internal static WindowsPackage FromIntPtr(IntPtr ptr) { | |
var pkg = new WindowsPackage(); | |
pkg.PackageName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.State = (PackageFeatureState)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.ReleaseType = (ReleaseType)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.InstallTime = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
return pkg; | |
} | |
} | |
public sealed class WindowsPackageInfo { | |
internal WindowsPackageInfo() {} | |
public string PackageName { get; private set; } | |
public PackageFeatureState State { get; private set; } | |
public ReleaseType ReleaseType { get; private set; } | |
public DateTime InstallTime { get; private set; } | |
public bool IsApplicable { get; private set; } | |
public string Copyright { get; private set; } | |
public string Company { get; private set; } | |
public DateTime CreationTime { get; private set; } | |
public string DisplayName { get; private set; } | |
public string Description { get; private set; } | |
public string InstallClient { get; private set; } | |
public string InstallPackageName { get; private set; } | |
public DateTime LastUpdateTime { get; private set; } | |
public string ProductName { get; private set; } | |
public string ProductVersion { get; private set; } | |
public RestartType RestartRequired { get; private set; } | |
public FullyOfflineInstallableType FullyOffline { get; private set; } | |
public string SupportInformation { get; private set; } | |
public ReadOnlyDictionary<string, string> CustomProperties { get; private set; } | |
public ReadOnlyCollection<WindowsFeature> Features { get; private set; } | |
public string CapabilityId { get; private set; } | |
internal static WindowsPackageInfo FromIntPtr(IntPtr ptr) { | |
var pkg = new WindowsPackageInfo(); | |
pkg.PackageName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.State = (PackageFeatureState)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.ReleaseType = (ReleaseType)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.InstallTime = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
ptr += Marshal.SizeOf<SYSTEMTIME>(); | |
pkg.IsApplicable = Marshal.ReadInt32(ptr) == 1; | |
ptr += Marshal.SizeOf<int>(); | |
pkg.Copyright = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.Company = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.CreationTime = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
ptr += Marshal.SizeOf<SYSTEMTIME>(); | |
pkg.DisplayName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.Description = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.InstallClient = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.InstallPackageName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.LastUpdateTime = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
ptr += Marshal.SizeOf<SYSTEMTIME>(); | |
pkg.ProductName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.ProductVersion = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.RestartRequired = (RestartType)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.FullyOffline = (FullyOfflineInstallableType)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.SupportInformation = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
var collectionPtr = Marshal.ReadIntPtr(ptr); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
var count = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
pkg.CustomProperties = new ReadOnlyDictionary<string, string>( | |
PtrToCollection<DismCustomProperty>(collectionPtr, count) | |
.ToDictionary( | |
cp => cp.Path + "\\" + cp.Name, | |
cp => cp.Value)); | |
collectionPtr = Marshal.ReadIntPtr(ptr); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
count = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
pkg.Features = new ReadOnlyCollection<WindowsFeature>(PtrToCollection<WindowsFeature>( | |
collectionPtr, | |
count)); | |
pkg.CapabilityId = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
return pkg; | |
} | |
} | |
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Unicode, Pack = 1)] | |
public sealed class WindowsFeature { | |
internal WindowsFeature() {} | |
private string featureName; | |
private PackageFeatureState state; | |
public string FeatureName => featureName; | |
public PackageFeatureState State => state; | |
internal static WindowsFeature FromIntPtr(IntPtr ptr) => Marshal.PtrToStructure<WindowsFeature>(ptr); | |
} | |
public sealed class WindowsFeatureInfo { | |
internal WindowsFeatureInfo() {} | |
public string FeatureName { get; private set; } | |
public PackageFeatureState State { get; private set; } | |
public string DisplayName { get; private set; } | |
public string Description { get; private set; } | |
public RestartType RestartRequired { get; private set; } | |
public ReadOnlyDictionary<string, string> CustomProperties { get; private set; } | |
internal static WindowsFeatureInfo FromIntPtr(IntPtr ptr) { | |
var feature = new WindowsFeatureInfo(); | |
feature.FeatureName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
feature.State = (PackageFeatureState)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
feature.DisplayName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
feature.Description = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
feature.RestartRequired = (RestartType)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
var collectionPtr = Marshal.ReadIntPtr(ptr); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
var count = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
feature.CustomProperties = new ReadOnlyDictionary<string, string>( | |
PtrToCollection<DismCustomProperty>(collectionPtr, count) | |
.ToDictionary( | |
cp => cp.Path + "\\" + cp.Name, | |
cp => cp.Value)); | |
return feature; | |
} | |
} | |
[StructLayout(LayoutKind.Auto, CharSet = CharSet.Unicode, Pack = 1)] | |
public sealed class WindowsCapability { | |
internal WindowsCapability() { } | |
private string name; | |
private PackageFeatureState state; | |
public string Name => name; | |
public PackageFeatureState State => state; | |
internal static WindowsCapability FromIntPtr(IntPtr ptr) => Marshal.PtrToStructure<WindowsCapability>(ptr); | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] | |
public sealed class WindowsCapabilityInfo { | |
internal WindowsCapabilityInfo() {} | |
[MarshalAs(UnmanagedType.LPWStr)] private string name; | |
private PackageFeatureState state; | |
[MarshalAs(UnmanagedType.LPWStr)] private string displayName; | |
[MarshalAs(UnmanagedType.LPWStr)] private string description; | |
private uint downloadSize; | |
private uint installSize; | |
public string Name => name; | |
public PackageFeatureState State => state; | |
public string DisplayName => displayName; | |
public string Description => description; | |
public uint DownloadSize => downloadSize; | |
public uint InstallSize => installSize; | |
internal static WindowsCapabilityInfo FromIntPtr(IntPtr ptr) => Marshal.PtrToStructure<WindowsCapabilityInfo>(ptr); | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] | |
internal struct DismString { | |
[MarshalAs(UnmanagedType.LPWStr)] public string Value; | |
internal static DismString FromIntPtr(IntPtr ptr) => Marshal.PtrToStructure<DismString>(ptr); | |
} | |
public sealed class WIMCustomizedInfo { | |
internal WIMCustomizedInfo() {} | |
public uint Size { get; private set; } | |
public uint DirectoryCount { get; private set; } | |
public uint FileCount { get; private set; } | |
public DateTime CreationTime { get; private set; } | |
public DateTime LastModifiedTime { get; private set; } | |
internal static WIMCustomizedInfo FromIntPtr(IntPtr ptr) { | |
var info = new WIMCustomizedInfo(); | |
info.Size = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.DirectoryCount = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.FileCount = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.CreationTime = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
ptr += Marshal.SizeOf<SYSTEMTIME>(); | |
info.LastModifiedTime = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
return info; | |
} | |
} | |
public sealed class WindowsImageInfo { | |
internal WindowsImageInfo() {} | |
public ImageType ImageType { get; private set; } | |
public uint ImageIndex { get; private set; } | |
public string ImageName { get; private set; } | |
public string ImageDescription { get; private set; } | |
public ulong ImageSize { get; private set; } | |
public uint Architecture { get; private set; } | |
public string ProductName { get; private set; } | |
public string EditionId { get; private set; } | |
public string InstallationType { get; private set; } | |
public string Hal { get; private set; } | |
public string ProductType { get; private set; } | |
public string ProductSuite { get; private set; } | |
public Version Version { get; private set; } | |
public Version ServicePackVersion { get; private set; } | |
public ImageBootability Bootability { get; private set; } | |
public string SystemRoot { get; private set; } | |
public ReadOnlyCollection<string> Languages { get; private set; } | |
public string DefaultLanguage { get; private set; } | |
public WIMCustomizedInfo CustomizedInfo { get; private set; } | |
internal WindowsImageInfo FromIntPtr(IntPtr ptr) { | |
var info = new WindowsImageInfo(); | |
info.ImageType = (ImageType)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
info.ImageIndex = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.ImageName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.ImageDescription = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.ImageSize = (ulong)Marshal.ReadInt64(ptr); | |
ptr += Marshal.SizeOf<ulong>(); | |
info.Architecture = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.ProductName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.EditionId = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.InstallationType = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.Hal = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.ProductType = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
info.ProductSuite = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
var major = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
var minor = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
var build = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.Version = new Version(major, minor, build); | |
var spBuild = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
var spLevel = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.ServicePackVersion = new Version(spLevel, 0, spBuild); | |
info.Bootability = (ImageBootability)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
info.SystemRoot = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
var collectionPtr = Marshal.ReadIntPtr(ptr); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
var collectionCount = (uint)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
info.Languages = | |
new ReadOnlyCollection<string>( | |
PtrToCollection<DismString>(collectionPtr, collectionCount).Select(s => s.Value).ToList()); | |
info.DefaultLanguage = info.Languages[Marshal.ReadInt32(ptr)]; // this will be fine unless Windows supports more than 2147483647 langauges | |
ptr += Marshal.SizeOf<uint>(); | |
info.CustomizedInfo = Marshal.PtrToStructure<WIMCustomizedInfo>(Marshal.ReadIntPtr(ptr)); | |
return info; | |
} | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] | |
public sealed class MountedWindowsImageInfo { | |
internal MountedWindowsImageInfo() {} | |
private string mountPath; | |
private string imageFilePath; | |
private uint imageIndex; | |
private MountMode mountMode; | |
private MountStatus mountStatus; | |
public string MountPath => mountPath; | |
public string ImageFilePath => imageFilePath; | |
public uint ImageIndex => imageIndex; | |
public MountMode MountMode => mountMode; | |
public MountStatus MountStatus => mountStatus; | |
internal static MountedWindowsImageInfo FromIntPtr(IntPtr ptr) => Marshal.PtrToStructure<MountedWindowsImageInfo>(ptr); | |
} | |
public sealed class WindowsDriverPackage { | |
internal WindowsDriverPackage() {} | |
public string PublishedName { get; private set; } | |
public string OriginalFileName { get; private set; } | |
public bool IsInBox { get; private set; } | |
public string CatalogFile { get; private set; } | |
public string ClassName { get; private set; } | |
public Guid ClassGuid { get; private set; } | |
public string ClassDescription { get; private set; } | |
public bool IsBootCritical { get; private set; } | |
public DriverSignature DriverSignature { get; private set; } | |
public string ProviderName { get; private set; } | |
public DateTime Date { get; private set; } | |
public Version Version { get; private set; } | |
internal WindowsDriverPackage FromIntPtr(IntPtr ptr) { | |
var pkg = new WindowsDriverPackage(); | |
pkg.PublishedName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.OriginalFileName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.IsInBox = Marshal.ReadInt32(ptr) == 1; | |
ptr += Marshal.SizeOf<int>(); | |
pkg.CatalogFile = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.ClassName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.ClassGuid = new Guid(Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr))); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.ClassDescription = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.IsBootCritical = Marshal.ReadInt32(ptr) == 1; | |
ptr += Marshal.SizeOf<int>(); | |
pkg.DriverSignature = (DriverSignature)Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<int>(); | |
pkg.ProviderName = Marshal.PtrToStringUni(Marshal.ReadIntPtr(ptr)); | |
ptr += Marshal.SizeOf<IntPtr>(); | |
pkg.Date = Marshal.PtrToStructure<SYSTEMTIME>(ptr).ToDateTime(); | |
ptr += Marshal.SizeOf<SYSTEMTIME>(); | |
var majorVersion = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
var minorVersion = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
var build = Marshal.ReadInt32(ptr); | |
ptr += Marshal.SizeOf<uint>(); | |
var revision = Marshal.ReadInt32(ptr); | |
pkg.Version = new Version(majorVersion, minorVersion, build, revision); | |
return pkg; | |
} | |
} | |
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)] | |
public sealed class WindowsDriver { | |
internal WindowsDriver() {} | |
private string manufacturerName; | |
private string hardwareDescription; | |
private string hardwareId; | |
private uint architecture; | |
private string serviceName; | |
private string compatibleIds; | |
private string excludeIds; | |
public string ManufacturerName => manufacturerName; | |
public string HardwareDescription => hardwareDescription; | |
public string HardwareId => hardwareId; | |
public uint Architecture => architecture; | |
public string ServiceName => serviceName; | |
public string CompatibleIds => compatibleIds; | |
public string ExcludeIds => excludeIds; | |
internal static WindowsDriver FromIntPtr(IntPtr ptr) => Marshal.PtrToStructure<WindowsDriver>(ptr); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment