1 #if !NET_CORE
2 
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 using Microsoft.Win32;
7 
8 namespace Mono.Cecil.Tests {
9 	public class WindowsRuntimeAssemblyResolver : DefaultAssemblyResolver {
10 
11 		readonly Dictionary<string, AssemblyDefinition> assemblies = new Dictionary<string, AssemblyDefinition> ();
12 
CreateInstance()13 		public static WindowsRuntimeAssemblyResolver CreateInstance ()
14 		{
15 			if (Platform.OnMono)
16 				return null;
17 			try {
18 				return new WindowsRuntimeAssemblyResolver ();
19 			} catch {
20 				return null;
21 			}
22 		}
23 
Resolve(AssemblyNameReference name)24 		public override AssemblyDefinition Resolve (AssemblyNameReference name)
25 		{
26 			AssemblyDefinition assembly;
27 			if (assemblies.TryGetValue(name.Name, out assembly))
28 				return assembly;
29 
30 			return base.Resolve (name);
31 		}
32 
WindowsRuntimeAssemblyResolver()33 		private WindowsRuntimeAssemblyResolver ()
34 		{
35 			LoadWindowsSdk ("v8.1", "8.1", (installationFolder) => {
36 				var fileName = Path.Combine (installationFolder, @"References\CommonConfiguration\Neutral\Annotated\Windows.winmd");
37 				var assembly = AssemblyDefinition.ReadAssembly (fileName);
38 				Register (assembly);
39 			});
40 
41 			LoadWindowsSdk ("v10.0", "10", (installationFolder) => {
42 				var referencesFolder = Path.Combine (installationFolder, "References");
43 				var assemblies = Directory.GetFiles (referencesFolder, "*.winmd", SearchOption.AllDirectories);
44 
45 				foreach (var assemblyPath in assemblies) {
46 					var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
47 					Register (assembly);
48 				}
49 			});
50 		}
51 
Register(AssemblyDefinition assembly)52 		void Register (AssemblyDefinition assembly)
53 		{
54 			assemblies [assembly.Name.Name] = assembly;
55 			RegisterAssembly (assembly);
56 		}
57 
Dispose(bool disposing)58 		protected override void Dispose (bool disposing)
59 		{
60 			if (!disposing)
61 				return;
62 
63 			foreach (var assembly in assemblies.Values)
64 				assembly.Dispose ();
65 
66 			base.Dispose (true);
67 		}
68 
LoadWindowsSdk(string registryVersion, string windowsKitsVersion, Action<string> registerAssembliesCallback)69 		void LoadWindowsSdk (string registryVersion, string windowsKitsVersion, Action<string> registerAssembliesCallback)
70 		{
71 #if NET_4_0
72 			using (var localMachine32Key = RegistryKey.OpenBaseKey (RegistryHive.LocalMachine, RegistryView.Registry32)) {
73 				using (var sdkKey = localMachine32Key.OpenSubKey (@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\v" + registryVersion)) {
74 #else
75 			{
76 				// this will fail on 64-bit process as there's no way (other than pinoke) to read from 32-bit registry view
77 				using (var sdkKey = Registry.LocalMachine.OpenSubKey (@"SOFTWARE\Microsoft\Microsoft SDKs\Windows\" + registryVersion)) {
78 #endif
79 					string installationFolder = null;
80 					if (sdkKey != null)
81 						installationFolder = (string)sdkKey.GetValue ("InstallationFolder");
82 					if (string.IsNullOrEmpty (installationFolder)) {
83 #if NET_4_0
84 						var programFilesX86 = Environment.GetFolderPath (Environment.SpecialFolder.ProgramFilesX86);
85 #else
86 						var programFilesX86 = Environment.GetEnvironmentVariable ("ProgramFiles(x86)");
87 #endif
88 						installationFolder = Path.Combine (programFilesX86, @"Windows Kits\" + windowsKitsVersion);
89 					}
90 					registerAssembliesCallback (installationFolder);
91 				}
92 			}
93 		}
94 	}
95 }
96 #endif