Skip to content

Instantly share code, notes, and snippets.

@jcotton42
Created October 27, 2016 01:45
Show Gist options
  • Save jcotton42/b807966a9ecfb4ca925bad24ae658c6b to your computer and use it in GitHub Desktop.
Save jcotton42/b807966a9ecfb4ca925bad24ae658c6b to your computer and use it in GitHub Desktop.
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