internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { if (!this.HasTemporaryWrapper) { return base.FindExistingWrapper(out wrapperInfo, componentTimestamp); } wrapperInfo = null; return false; }
internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { if (!this.HasTemporaryWrapper) { return(base.FindExistingWrapper(out wrapperInfo, componentTimestamp)); } wrapperInfo = null; return(false); }
/* * Method: FindExistingWrapper * * Checks if there's a preexisting wrapper for this reference. */ internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { if (!HasTemporaryWrapper) { return(base.FindExistingWrapper(out wrapperInfo, componentTimestamp)); } // if this reference has a temporary wrapper, it can't possibly have a preexisting one wrapperInfo = null; return(false); }
internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { wrapperInfo = null; string wrapperPath = this.GetWrapperPath(); if (!File.Exists(wrapperPath)) { return false; } wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; return this.IsWrapperUpToDate(wrapperInfo, componentTimestamp); }
internal ComReferenceInfo(ComReferenceInfo copyFrom) { this.attr = copyFrom.attr; this.typeLibName = copyFrom.typeLibName; this.typeLibPath = copyFrom.typeLibPath; this.typeLibPointer = copyFrom.typeLibPointer; this.primaryOfAxImpRef = copyFrom.primaryOfAxImpRef; this.resolvedWrapper = copyFrom.resolvedWrapper; this.taskItem = new TaskItem(copyFrom.taskItem); this.dependentWrapperPaths = copyFrom.dependentWrapperPaths; this.referencePathItem = copyFrom.referencePathItem; }
/* * Method: GenerateWrapper * * Generates a wrapper for this reference. */ internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; // The tool gets the public key for itself, but we get it here anyway to // give nice messages in errors cases. StrongNameKeyPair keyPair = null; byte[] publicKey = null; GetAndValidateStrongNameKey(out keyPair, out publicKey); bool generateWrapperSucceeded = true; string tlbName = ReferenceInfo.taskItem.GetMetadata(ComReferenceItemMetadataNames.tlbReferenceName); // Generate wrapper out-of-proc using aximp.exe from the target framework. MUST // HAVE SET SDKTOOLSPATH TO THE TARGET SDK TO WORK var axImp = new ResolveComReference.AxImp(); if (ReferenceInfo != null) { axImp.ActiveXControlName = ReferenceInfo.strippedTypeLibPath; } axImp.BuildEngine = BuildEngine; axImp.ToolPath = ToolPath; axImp.EnvironmentVariables = EnvironmentVariables; axImp.DelaySign = DelaySign; axImp.GenerateSource = false; axImp.KeyContainer = KeyContainer; axImp.KeyFile = KeyFile; axImp.Silent = Silent; if (ReferenceInfo != null && ReferenceInfo.primaryOfAxImpRef != null && ReferenceInfo.primaryOfAxImpRef.resolvedWrapper != null && ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path != null) { // This path should hit unless there was a prior resolution error or bug in the resolution code. // The reason is that everything (tlbs and pias) gets resolved before AxImp references. axImp.RuntimeCallableWrapperAssembly = ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path; } axImp.OutputAssembly = Path.Combine(OutputDirectory, GetWrapperFileName()); generateWrapperSucceeded = axImp.Execute(); string wrapperPath = GetWrapperPath(); // store the wrapper info... wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); // ...and we're done! return(generateWrapperSucceeded); }
/// <summary> /// Compare the strong name signing state of the existing wrapper to the signing /// state we are requesting in this run of the task. Return true if they match (e.g. /// from a signing perspective, the wrapper is up-to-date) or false otherwise. /// </summary> private bool SigningRequirementsMatchExistingWrapper(ComReferenceWrapperInfo wrapperInfo) { StrongNameLevel desiredStrongNameLevel = StrongNameLevel.None; if (!string.IsNullOrEmpty(KeyFile) || !string.IsNullOrEmpty(KeyContainer)) { desiredStrongNameLevel = DelaySign ? StrongNameLevel.DelaySigned : StrongNameLevel.FullySigned; } // ...and see what we have already StrongNameLevel currentStrongNameLevel = StrongNameUtils.GetAssemblyStrongNameLevel(wrapperInfo.path); // if not matching, need to regenerate wrapper if (desiredStrongNameLevel != currentStrongNameLevel) { return(false); } // if the wrapper needs a strong name, see if the public keys match if (desiredStrongNameLevel == StrongNameLevel.DelaySigned || desiredStrongNameLevel == StrongNameLevel.FullySigned) { // get desired public key StrongNameUtils.GetStrongNameKey(Log, KeyFile, KeyContainer, out _, out byte[] desiredPublicKey); // get current public key AssemblyName assemblyName = AssemblyName.GetAssemblyName(wrapperInfo.path); if (assemblyName == null) { return(false); } byte[] currentPublicKey = assemblyName.GetPublicKey(); if (currentPublicKey.Length != desiredPublicKey.Length) { return(false); } // compare public keys byte by byte for (int i = 0; i < currentPublicKey.Length; i++) { if (currentPublicKey[i] != desiredPublicKey[i]) { return(false); } } } return(true); }
internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { wrapperInfo = null; string wrapperPath = this.GetWrapperPath(); if (!File.Exists(wrapperPath)) { return(false); } wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; return(this.IsWrapperUpToDate(wrapperInfo, componentTimestamp)); }
/* * Method: GenerateWrapper * * Generates a wrapper for this reference. */ internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; // The tool gets the public key for itself, but we get it here anyway to // give nice messages in errors cases. StrongNameKeyPair keyPair = null; byte[] publicKey = null; GetAndValidateStrongNameKey(out keyPair, out publicKey); bool generateWrapperSucceeded = true; string tlbName = ReferenceInfo.taskItem.GetMetadata(ComReferenceItemMetadataNames.tlbReferenceName); // Generate wrapper out-of-proc using aximp.exe from the target framework. MUST // HAVE SET SDKTOOLSPATH TO THE TARGET SDK TO WORK var axImp = new ResolveComReference.AxImp(); axImp.ActiveXControlName = ReferenceInfo.strippedTypeLibPath; axImp.BuildEngine = BuildEngine; axImp.ToolPath = ToolPath; axImp.EnvironmentVariables = EnvironmentVariables; axImp.DelaySign = DelaySign; axImp.GenerateSource = false; axImp.KeyContainer = KeyContainer; axImp.KeyFile = KeyFile; axImp.Silent = Silent; if (ReferenceInfo != null && ReferenceInfo.primaryOfAxImpRef != null && ReferenceInfo.primaryOfAxImpRef.resolvedWrapper != null && ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path != null) { // This path should hit unless there was a prior resolution error or bug in the resolution code. // The reason is that everything (tlbs and pias) gets resolved before AxImp references. axImp.RuntimeCallableWrapperAssembly = ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path; } axImp.OutputAssembly = Path.Combine(OutputDirectory, GetWrapperFileName()); generateWrapperSucceeded = axImp.Execute(); string wrapperPath = GetWrapperPath(); // store the wrapper info... wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); // ...and we're done! return generateWrapperSucceeded; }
/* * Method: FindExistingWrapper * * Checks if there's a preexisting wrapper for this reference. */ internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { wrapperInfo = null; string wrapperPath = GetWrapperPath(); // now see if the wrapper assembly actually exists if (!File.Exists(wrapperPath)) { return(false); } wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; return(IsWrapperUpToDate(wrapperInfo, componentTimestamp)); }
internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; StrongNameKeyPair keyPair = null; byte[] publicKey = null; StrongNameUtils.GetStrongNameKey(base.Log, base.KeyFile, base.KeyContainer, out keyPair, out publicKey); if (!base.DelaySign && (keyPair == null)) { if ((base.KeyContainer != null) && (base.KeyContainer.Length > 0)) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "ResolveComReference.StrongNameUtils.NoKeyPairInContainer", new object[] { base.KeyContainer }); throw new StrongNameException(); } if ((base.KeyFile != null) && (base.KeyFile.Length > 0)) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "ResolveComReference.StrongNameUtils.NoKeyPairInFile", new object[] { base.KeyFile }); throw new StrongNameException(); } } bool flag = true; this.ReferenceInfo.taskItem.GetMetadata("TlbReferenceName"); ResolveComReference.AxImp imp = new ResolveComReference.AxImp { ActiveXControlName = this.ReferenceInfo.typeLibPath, BuildEngine = base.BuildEngine, ToolPath = base.ToolPath, EnvironmentVariables = base.EnvironmentVariables, DelaySign = base.DelaySign, GenerateSource = false, KeyContainer = base.KeyContainer, KeyFile = base.KeyFile }; if (((this.ReferenceInfo != null) && (this.ReferenceInfo.primaryOfAxImpRef != null)) && ((this.ReferenceInfo.primaryOfAxImpRef.resolvedWrapper != null) && (this.ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path != null))) { imp.RuntimeCallableWrapperAssembly = this.ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path; } imp.OutputAssembly = Path.Combine(this.OutputDirectory, base.GetWrapperFileName()); flag = imp.Execute(); string wrapperPath = base.GetWrapperPath(); wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); return(flag); }
/// <summary> /// Checks if the existing wrapper is up to date. /// </summary> protected virtual bool IsWrapperUpToDate(ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { Debug.Assert(!string.IsNullOrEmpty(ReferenceInfo.strippedTypeLibPath), "ReferenceInfo.path should be valid if we got here"); if (string.IsNullOrEmpty(ReferenceInfo.strippedTypeLibPath)) { throw new ComReferenceResolutionException(); } // if wrapper doesn't exist, wrapper is obviously not up to date if (!FileSystems.Default.FileExists(wrapperInfo.path)) { return(false); } // if typelib file has a DIFFERENT last write time, wrapper is not up to date // the reason we're comparing write times in an unusual way is that type libraries are unusual // "source files" for wrappers. If you upgrade/downgrade a system component, its write // time may be earlier than before but we should still regenerate the wrapper. if (DateTime.Compare(File.GetLastWriteTime(ReferenceInfo.strippedTypeLibPath), componentTimestamp) != 0) { return(false); } // Compare our the existing wrapper's strong name state to the one we are requesting. if (!SigningRequirementsMatchExistingWrapper(wrapperInfo)) { return(false); } // ok, everything's looking fine, now just verify the assembly file is valid try { wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); } catch (BadImageFormatException) { // ouch, this assembly is malformed... need to regenerate the wrapper. wrapperInfo.assembly = null; } return(wrapperInfo.assembly != null); }
internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { string str; string str2; wrapperInfo = null; TypeLibConverter converter = new TypeLibConverter(); if (!converter.GetPrimaryInteropAssembly(this.ReferenceInfo.attr.guid, this.ReferenceInfo.attr.wMajorVerNum, this.ReferenceInfo.attr.wMinorVerNum, this.ReferenceInfo.attr.lcid, out str, out str2)) { return(false); } try { if ((str2 != null) && (str2.Length > 0)) { Uri uri = new Uri(str2); Assembly assembly = Assembly.UnsafeLoadFrom(uri.LocalPath); wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = uri.LocalPath; wrapperInfo.assembly = assembly; wrapperInfo.originalPiaName = new AssemblyNameExtension(AssemblyName.GetAssemblyName(uri.LocalPath)); } else { Assembly assembly2 = Assembly.Load(str); wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = assembly2.Location; wrapperInfo.assembly = assembly2; wrapperInfo.originalPiaName = new AssemblyNameExtension(str, true); } } catch (FileNotFoundException) { } catch (BadImageFormatException) { base.Log.LogWarningWithCodeFromResources("ResolveComReference.BadAssemblyImage", new object[] { str }); } return(wrapperInfo != null); }
bool IComReferenceResolver.ResolveComClassicReference(System.Runtime.InteropServices.ComTypes.TYPELIBATTR typeLibAttr, string outputDirectory, string wrapperType, string refName, out ComReferenceWrapperInfo wrapperInfo) { ComReferenceInfo info; bool topLevelRef = false; wrapperInfo = null; System.Runtime.InteropServices.ComTypes.TYPELIBATTR typelibattr = typeLibAttr; if (ComReference.RemapAdoTypeLib(base.Log, ref typeLibAttr)) { base.Log.LogMessageFromResources(MessageImportance.Low, "ResolveComReference.RemappingAdoTypeLib", new object[] { typelibattr.wMajorVerNum, typelibattr.wMinorVerNum }); } if (this.IsExistingProjectReference(typeLibAttr, wrapperType, out info)) { topLevelRef = true; wrapperType = info.taskItem.GetMetadata("WrapperTool"); } else if (this.IsExistingDependencyReference(typeLibAttr, out info)) { if ((wrapperType == null) || ComReferenceTypes.IsPiaOrTlbImp(wrapperType)) { string key = ComReference.UniqueKeyFromTypeLibAttr(typeLibAttr); if (this.cachePia.ContainsKey(key)) { wrapperType = "primary"; } else if (this.cacheTlb.ContainsKey(key)) { wrapperType = "tlbimp"; } } } else { try { info = new ComReferenceInfo(); if (info.InitializeWithTypeLibAttrs(base.Log, typeLibAttr, null, this.TargetProcessorArchitecture)) { this.allDependencyRefs.Add(info); } else { info.ReleaseTypeLibPtr(); return false; } } catch (COMException exception) { base.Log.LogWarningWithCodeFromResources("ResolveComReference.CannotLoadTypeLib", new object[] { typeLibAttr.guid, typeLibAttr.wMajorVerNum.ToString(CultureInfo.InvariantCulture), typeLibAttr.wMinorVerNum.ToString(CultureInfo.InvariantCulture), exception.Message }); info.ReleaseTypeLibPtr(); return false; } } if (refName == null) { refName = info.typeLibName; } return this.ResolveComClassicReference(info, outputDirectory, wrapperType, refName, topLevelRef, info.dependentWrapperPaths, out wrapperInfo); }
/* * Method: GenerateWrapper * * Generates a wrapper for this reference. */ internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string rootNamespace = ReferenceInfo.typeLibName; string wrapperPath = GetWrapperPath(); bool generateWrapperSucceeded = true; if (ExecuteAsTool) { // delegate generation of the assembly to an instance of the TlbImp ToolTask. MUST // HAVE SET SDKTOOLSPATH TO THE TARGET SDK TO WORK var tlbImp = new ResolveComReference.TlbImp(); tlbImp.BuildEngine = BuildEngine; tlbImp.EnvironmentVariables = EnvironmentVariables; tlbImp.DelaySign = DelaySign; tlbImp.KeyContainer = KeyContainer; tlbImp.KeyFile = KeyFile; tlbImp.OutputAssembly = wrapperPath; tlbImp.ToolPath = ToolPath; tlbImp.TypeLibName = ReferenceInfo.fullTypeLibPath; tlbImp.AssemblyNamespace = rootNamespace; tlbImp.AssemblyVersion = null; tlbImp.PreventClassMembers = _noClassMembers; tlbImp.SafeArrayAsSystemArray = true; tlbImp.Silent = Silent; tlbImp.Transform = ResolveComReference.TlbImpTransformFlags.TransformDispRetVals; if (_referenceFiles != null) { // Issue is that there may be reference dependencies that need to be passed in. It is possible // that the set of references will also contain the file that is meant to be written here (when reference resolution // found the file in the output folder). We need to filter out this case. var fullPathToOutput = Path.GetFullPath(wrapperPath); // Current directory is the directory of the project file. tlbImp.ReferenceFiles = _referenceFiles.Where(rf => String.Compare(fullPathToOutput, rf, StringComparison.OrdinalIgnoreCase) != 0).ToArray(); } switch (_targetProcessorArchitecture) { case UtilitiesProcessorArchitecture.MSIL: tlbImp.Machine = "Agnostic"; break; case UtilitiesProcessorArchitecture.AMD64: tlbImp.Machine = "X64"; break; case UtilitiesProcessorArchitecture.IA64: tlbImp.Machine = "Itanium"; break; case UtilitiesProcessorArchitecture.X86: tlbImp.Machine = "X86"; break; case UtilitiesProcessorArchitecture.ARM: tlbImp.Machine = "ARM"; break; case null: break; default: // Transmit the flag directly from the .targets files and rely on tlbimp.exe to produce a good error message. tlbImp.Machine = _targetProcessorArchitecture; break; } generateWrapperSucceeded = tlbImp.Execute(); // store the wrapper info... wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = (HasTemporaryWrapper) ? null : wrapperPath; // Changed to ReflectionOnlyLoadFrom, related to bug: // RCR: Bad COM-interop assemblies being generated when using 64-bit MSBuild to build a project that is targeting 32-bit platform // The original call to UnsafeLoadFrom loads the assembly in preparation for execution. If the assembly is x86 and this is x64 msbuild.exe then we // have problems (UnsafeLoadFrom will fail). We only use this assembly for reference resolution so we don't need to be ready to execute the code. // // Its actually not clear to me that we even need to load the assembly at all. Reference resoluton is only used in the !ExecuteAsTool which is not // where we are right now. // // If we really do need to load it then: // // wrapperInfo.assembly = Assembly.ReflectionOnlyLoadFrom(wrapperPath); } else { // use framework classes in-proc to generate the assembly TypeLibConverter converter = new TypeLibConverter(); AssemblyBuilder assemblyBuilder = null; StrongNameKeyPair keyPair; byte[] publicKey; GetAndValidateStrongNameKey(out keyPair, out publicKey); try { TypeLibImporterFlags flags = TypeLibImporterFlags.SafeArrayAsSystemArray | TypeLibImporterFlags.TransformDispRetVals; if (_noClassMembers) { flags |= TypeLibImporterFlags.PreventClassMembers; } switch (_targetProcessorArchitecture) { case UtilitiesProcessorArchitecture.MSIL: flags |= TypeLibImporterFlags.ImportAsAgnostic; break; case UtilitiesProcessorArchitecture.AMD64: flags |= TypeLibImporterFlags.ImportAsX64; break; case UtilitiesProcessorArchitecture.IA64: flags |= TypeLibImporterFlags.ImportAsItanium; break; case UtilitiesProcessorArchitecture.X86: flags |= TypeLibImporterFlags.ImportAsX86; break; case UtilitiesProcessorArchitecture.ARM: flags |= TypeLibImporterFlags.ImportAsArm; break; default: // Let the type importer decide. break; } // Start the conversion process. We'll get callbacks on ITypeLibImporterNotifySink to resolve dependent refs. assemblyBuilder = converter.ConvertTypeLibToAssembly(ReferenceInfo.typeLibPointer, wrapperPath, flags, this, publicKey, keyPair, rootNamespace, null); } catch (COMException ex) { if (!Silent) { Log.LogWarningWithCodeFromResources("ResolveComReference.ErrorCreatingWrapperAssembly", ItemName, ex.Message); } throw new ComReferenceResolutionException(ex); } // if we're done, and this is not a temporary wrapper, write it out to disk if (!HasTemporaryWrapper) { WriteWrapperToDisk(assemblyBuilder, wrapperPath); } // store the wrapper info... wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = (HasTemporaryWrapper) ? null : wrapperPath; wrapperInfo.assembly = assemblyBuilder; } // ...and we're done! return generateWrapperSucceeded; }
/// <summary> /// Helper function - resolves an ActiveX reference given the type library attributes. /// </summary> /// <param name="referenceInfo">Information about the reference to be resolved</param> /// <param name="outputDirectory">Directory the interop DLL should be written to</param> /// <param name="refName">Name of reference</param> /// <param name="wrapperInfo">Information about wrapper locations</param> /// <returns>True if the reference was already found or successfully generated, false otherwise.</returns> internal bool ResolveComReferenceAx(ComReferenceInfo referenceInfo, string outputDirectory, string refName, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string typeLibKey = ComReference.UniqueKeyFromTypeLibAttr(referenceInfo.attr); // look in the Ax cache first if (_cacheAx.ContainsKey(typeLibKey)) { wrapperInfo = (ComReferenceWrapperInfo)_cacheAx[typeLibKey]; return true; } try { // not in the cache? see if anyone was kind enough to generate it for us AxReference reference = new AxReference(Log, Silent, this, referenceInfo, refName, outputDirectory, DelaySign, KeyFile, KeyContainer, IncludeVersionInInteropName, _aximpPath, BuildEngine, EnvironmentVariables); // wrapper doesn't exist or needs regeneration? generate it then if (!reference.FindExistingWrapper(out wrapperInfo, _timestampCache[referenceInfo.strippedTypeLibPath])) { if (!reference.GenerateWrapper(out wrapperInfo)) return false; } // if found or successfully generated, cache it. _cacheAx.Add(typeLibKey, wrapperInfo); } catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e)) { return false; } return true; }
/// <summary> /// Finds an existing wrapper for the specified component /// </summary> internal abstract bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp);
/* * Method: FindExistingWrapper * * Checks if there's a preexisting wrapper for this reference. */ internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { if (!HasTemporaryWrapper) { return base.FindExistingWrapper(out wrapperInfo, componentTimestamp); } // if this reference has a temporary wrapper, it can't possibly have a preexisting one wrapperInfo = null; return false; }
/* * Method: Resolve * * Gets the resolved assembly path for the typelib wrapper. */ internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { wrapperInfo = null; // Let NDP do the dirty work... TypeLibConverter converter = new TypeLibConverter(); string asmName, asmCodeBase; if (!converter.GetPrimaryInteropAssembly(ReferenceInfo.attr.guid, ReferenceInfo.attr.wMajorVerNum, ReferenceInfo.attr.wMinorVerNum, ReferenceInfo.attr.lcid, out asmName, out asmCodeBase)) { return(false); } // let's try to load the assembly to determine its path and if it's there try { if (asmCodeBase != null && asmCodeBase.Length > 0) { Uri uri = new Uri(asmCodeBase); // make sure the PIA can be loaded Assembly assembly = Assembly.UnsafeLoadFrom(uri.LocalPath); // got here? then assembly must have been loaded successfully. wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = uri.LocalPath; wrapperInfo.assembly = assembly; // We need to remember the original assembly name of this PIA in case it gets redirected to a newer // version and other COM components use that name to reference the PIA. assembly.FullName wouldn't // work here since we'd get the redirected assembly name. wrapperInfo.originalPiaName = new AssemblyNameExtension(AssemblyName.GetAssemblyName(uri.LocalPath)); } else { Assembly assembly = Assembly.Load(asmName); // got here? then assembly must have been loaded successfully. wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = assembly.Location; wrapperInfo.assembly = assembly; // We need to remember the original assembly name of this PIA in case it gets redirected to a newer // version and other COM components use that name to reference the PIA. wrapperInfo.originalPiaName = new AssemblyNameExtension(asmName, true); } } catch (FileNotFoundException) { // This means that assembly file cannot be found. // We don't need to do anything here; wrapperInfo is not set // and we'll assume that the assembly doesn't exist. } catch (BadImageFormatException) { // Similar case as above, except we should additionally warn the user that the assembly file // is not really a valid assembly file. if (!Silent) { Log.LogWarningWithCodeFromResources("ResolveComReference.BadAssemblyImage", asmName); } } // have we found the wrapper? if (wrapperInfo != null) { return(true); } return(false); }
/// <summary> /// Helper function - resolves a regular tlb COM classic reference given the type library attributes. /// </summary> /// <param name="referenceInfo">Information about the reference to be resolved</param> /// <param name="outputDirectory">Directory the interop DLL should be written to</param> /// <param name="refName">Name of reference</param> /// <param name="topLevelRef">True if this is a top-level reference</param> /// <param name="wrapperInfo">Information about wrapper locations</param> /// <returns>True if the reference was already found or successfully generated, false otherwise.</returns> internal bool ResolveComReferenceTlb(ComReferenceInfo referenceInfo, string outputDirectory, string refName, bool topLevelRef, List<string> dependencyPaths, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string typeLibKey = ComReference.UniqueKeyFromTypeLibAttr(referenceInfo.attr); // look in the TLB cache first if (_cacheTlb.ContainsKey(typeLibKey)) { wrapperInfo = (ComReferenceWrapperInfo)_cacheTlb[typeLibKey]; return true; } // is it a temporary wrapper? bool isTemporary = false; // no top level (included in the project) refs can have temporary wrappers if (!topLevelRef) { // wrapper is temporary if there's a top level tlb reference with the same typelib name, but different attributes foreach (ComReferenceInfo projectRefInfo in allProjectRefs) { if (ComReferenceTypes.IsTlbImp(projectRefInfo.taskItem.GetMetadata(ComReferenceItemMetadataNames.wrapperTool))) { // conflicting typelib names for different typelibs? generate a temporary wrapper if (!ComReference.AreTypeLibAttrEqual(referenceInfo.attr, projectRefInfo.attr) && String.Compare(referenceInfo.typeLibName, projectRefInfo.typeLibName, StringComparison.OrdinalIgnoreCase) == 0) { isTemporary = true; } } } } try { List<string> referencePaths = new List<string>(GetResolvedAssemblyReferenceItemSpecs()); if (dependencyPaths != null) { referencePaths.AddRange(dependencyPaths); } // not in the cache? see if anyone was kind enough to generate it for us TlbReference reference = new TlbReference(Log, Silent, this, referencePaths, referenceInfo, refName, outputDirectory, isTemporary, DelaySign, KeyFile, KeyContainer, this.NoClassMembers, this.TargetProcessorArchitecture, IncludeVersionInInteropName, ExecuteAsTool, _tlbimpPath, BuildEngine, EnvironmentVariables); // wrapper doesn't exist or needs regeneration? generate it then if (!reference.FindExistingWrapper(out wrapperInfo, _timestampCache[referenceInfo.strippedTypeLibPath])) { if (!reference.GenerateWrapper(out wrapperInfo)) return false; } // if found or successfully generated, cache it. _cacheTlb.Add(typeLibKey, wrapperInfo); } catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e)) { return false; } return true; }
internal bool ResolveComReferencePia(ComReferenceInfo referenceInfo, string refName, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string key = ComReference.UniqueKeyFromTypeLibAttr(referenceInfo.attr); if (this.cachePia.ContainsKey(key)) { wrapperInfo = (ComReferenceWrapperInfo) this.cachePia[key]; return true; } try { PiaReference reference = new PiaReference(base.Log, referenceInfo, refName); if (!reference.FindExistingWrapper(out wrapperInfo, this.timestampCache[referenceInfo.typeLibPath])) { return false; } this.cachePia.Add(key, wrapperInfo); } catch (Exception exception) { if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception)) { throw; } return false; } return true; }
protected virtual bool IsWrapperUpToDate(ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { if ((this.ReferenceInfo.typeLibPath == null) || (this.ReferenceInfo.typeLibPath.Length == 0)) { throw new ComReferenceResolutionException(); } if (!File.Exists(wrapperInfo.path)) { return(false); } if (DateTime.Compare(File.GetLastWriteTime(this.ReferenceInfo.typeLibPath), componentTimestamp) != 0) { return(false); } StrongNameLevel none = StrongNameLevel.None; if (((this.KeyFile != null) && (this.KeyFile.Length > 0)) || ((this.KeyContainer != null) && (this.KeyContainer.Length > 0))) { if (this.DelaySign) { none = StrongNameLevel.DelaySigned; } else { none = StrongNameLevel.FullySigned; } } StrongNameLevel assemblyStrongNameLevel = StrongNameUtils.GetAssemblyStrongNameLevel(wrapperInfo.path); if (none != assemblyStrongNameLevel) { return(false); } if ((none == StrongNameLevel.DelaySigned) || (none == StrongNameLevel.FullySigned)) { StrongNameKeyPair pair; byte[] publicKey = null; StrongNameUtils.GetStrongNameKey(base.Log, this.KeyFile, this.KeyContainer, out pair, out publicKey); AssemblyName assemblyName = AssemblyName.GetAssemblyName(wrapperInfo.path); if (assemblyName == null) { return(false); } byte[] buffer2 = assemblyName.GetPublicKey(); if (buffer2.Length != publicKey.Length) { return(false); } for (int i = 0; i < buffer2.Length; i++) { if (buffer2[i] != publicKey[i]) { return(false); } } } try { wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); } catch (BadImageFormatException) { wrapperInfo.assembly = null; } return(wrapperInfo.assembly != null); }
/// <summary> /// Compare the strong name signing state of the existing wrapper to the signing /// state we are requesting in this run of the task. Return true if they match (e.g. /// from a signing perspective, the wrapper is up-to-date) or false otherwise. /// </summary> private bool SigningRequirementsMatchExistingWrapper(ComReferenceWrapperInfo wrapperInfo) { StrongNameLevel desiredStrongNameLevel = StrongNameLevel.None; if ((KeyFile != null && KeyFile.Length > 0) || (KeyContainer != null && KeyContainer.Length > 0)) { if (DelaySign) { desiredStrongNameLevel = StrongNameLevel.DelaySigned; } else { desiredStrongNameLevel = StrongNameLevel.FullySigned; } } // ...and see what we have already StrongNameLevel currentStrongNameLevel = StrongNameUtils.GetAssemblyStrongNameLevel(wrapperInfo.path); // if not matching, need to regenerate wrapper if (desiredStrongNameLevel != currentStrongNameLevel) { return false; } // if the wrapper needs a strong name, see if the public keys match if (desiredStrongNameLevel == StrongNameLevel.DelaySigned || desiredStrongNameLevel == StrongNameLevel.FullySigned) { StrongNameKeyPair snkPair; byte[] desiredPublicKey = null; // get desired public key StrongNameUtils.GetStrongNameKey(Log, KeyFile, KeyContainer, out snkPair, out desiredPublicKey); // get current public key AssemblyName assemblyName = AssemblyName.GetAssemblyName(wrapperInfo.path); if (assemblyName == null) { return false; } byte[] currentPublicKey = assemblyName.GetPublicKey(); if (currentPublicKey.Length != desiredPublicKey.Length) { return false; } // compare public keys byte by byte for (int i = 0; i < currentPublicKey.Length; i++) { if (currentPublicKey[i] != desiredPublicKey[i]) { return false; } } } return true; }
internal bool ResolveComClassicReference(ComReferenceInfo referenceInfo, string outputDirectory, string wrapperType, string refName, bool topLevelRef, List<string> dependencyPaths, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; bool flag = false; if (ComReferenceTypes.IsPia(wrapperType)) { flag = this.ResolveComReferencePia(referenceInfo, refName, out wrapperInfo); } else if (ComReferenceTypes.IsTlbImp(wrapperType)) { flag = this.ResolveComReferenceTlb(referenceInfo, outputDirectory, refName, topLevelRef, dependencyPaths, out wrapperInfo); } else if (ComReferenceTypes.IsAxImp(wrapperType)) { flag = this.ResolveComReferenceAx(referenceInfo, outputDirectory, refName, out wrapperInfo); } else if ((wrapperType == null) || ComReferenceTypes.IsPiaOrTlbImp(wrapperType)) { flag = this.ResolveComReferencePia(referenceInfo, refName, out wrapperInfo); if (!flag) { flag = this.ResolveComReferenceTlb(referenceInfo, outputDirectory, refName, false, dependencyPaths, out wrapperInfo); } } else { Microsoft.Build.Shared.ErrorUtilities.VerifyThrow(false, "Unknown wrapper type!"); } referenceInfo.resolvedWrapper = wrapperInfo; this.timestampCache[referenceInfo.typeLibPath] = File.GetLastWriteTime(referenceInfo.typeLibPath); return flag; }
protected virtual bool IsWrapperUpToDate(ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { if ((this.ReferenceInfo.typeLibPath == null) || (this.ReferenceInfo.typeLibPath.Length == 0)) { throw new ComReferenceResolutionException(); } if (!File.Exists(wrapperInfo.path)) { return false; } if (DateTime.Compare(File.GetLastWriteTime(this.ReferenceInfo.typeLibPath), componentTimestamp) != 0) { return false; } StrongNameLevel none = StrongNameLevel.None; if (((this.KeyFile != null) && (this.KeyFile.Length > 0)) || ((this.KeyContainer != null) && (this.KeyContainer.Length > 0))) { if (this.DelaySign) { none = StrongNameLevel.DelaySigned; } else { none = StrongNameLevel.FullySigned; } } StrongNameLevel assemblyStrongNameLevel = StrongNameUtils.GetAssemblyStrongNameLevel(wrapperInfo.path); if (none != assemblyStrongNameLevel) { return false; } if ((none == StrongNameLevel.DelaySigned) || (none == StrongNameLevel.FullySigned)) { StrongNameKeyPair pair; byte[] publicKey = null; StrongNameUtils.GetStrongNameKey(base.Log, this.KeyFile, this.KeyContainer, out pair, out publicKey); AssemblyName assemblyName = AssemblyName.GetAssemblyName(wrapperInfo.path); if (assemblyName == null) { return false; } byte[] buffer2 = assemblyName.GetPublicKey(); if (buffer2.Length != publicKey.Length) { return false; } for (int i = 0; i < buffer2.Length; i++) { if (buffer2[i] != publicKey[i]) { return false; } } } try { wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); } catch (BadImageFormatException) { wrapperInfo.assembly = null; } return (wrapperInfo.assembly != null); }
/* * Method: Resolve * * Gets the resolved assembly path for the typelib wrapper. */ internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { wrapperInfo = null; // Let NDP do the dirty work... TypeLibConverter converter = new TypeLibConverter(); string asmName, asmCodeBase; if (!converter.GetPrimaryInteropAssembly(ReferenceInfo.attr.guid, ReferenceInfo.attr.wMajorVerNum, ReferenceInfo.attr.wMinorVerNum, ReferenceInfo.attr.lcid, out asmName, out asmCodeBase)) { return false; } // let's try to load the assembly to determine its path and if it's there try { if (asmCodeBase != null && asmCodeBase.Length > 0) { Uri uri = new Uri(asmCodeBase); // make sure the PIA can be loaded Assembly assembly = Assembly.UnsafeLoadFrom(uri.LocalPath); // got here? then assembly must have been loaded successfully. wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = uri.LocalPath; wrapperInfo.assembly = assembly; // We need to remember the original assembly name of this PIA in case it gets redirected to a newer // version and other COM components use that name to reference the PIA. assembly.FullName wouldn't // work here since we'd get the redirected assembly name. wrapperInfo.originalPiaName = new AssemblyNameExtension(AssemblyName.GetAssemblyName(uri.LocalPath)); } else { Assembly assembly = Assembly.Load(asmName); // got here? then assembly must have been loaded successfully. wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = assembly.Location; wrapperInfo.assembly = assembly; // We need to remember the original assembly name of this PIA in case it gets redirected to a newer // version and other COM components use that name to reference the PIA. wrapperInfo.originalPiaName = new AssemblyNameExtension(asmName, true); } } catch (FileNotFoundException) { // This means that assembly file cannot be found. // We don't need to do anything here; wrapperInfo is not set // and we'll assume that the assembly doesn't exist. } catch (BadImageFormatException) { // Similar case as above, except we should additionally warn the user that the assembly file // is not really a valid assembly file. if (!Silent) { Log.LogWarningWithCodeFromResources("ResolveComReference.BadAssemblyImage", asmName); } } // have we found the wrapper? if (wrapperInfo != null) { return true; } return false; }
internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string typeLibName = this.ReferenceInfo.typeLibName; string wrapperPath = base.GetWrapperPath(); StrongNameKeyPair keyPair = null; byte[] publicKey = null; StrongNameUtils.GetStrongNameKey(base.Log, base.KeyFile, base.KeyContainer, out keyPair, out publicKey); if (base.DelaySign) { keyPair = null; if (publicKey == null) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "StrongNameUtils.NoPublicKeySpecified", new object[0]); throw new StrongNameException(); } } else { publicKey = null; if (keyPair == null) { if ((base.KeyContainer != null) && (base.KeyContainer.Length > 0)) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "ResolveComReference.StrongNameUtils.NoKeyPairInContainer", new object[] { base.KeyContainer }); throw new StrongNameException(); } if ((base.KeyFile != null) && (base.KeyFile.Length > 0)) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "ResolveComReference.StrongNameUtils.NoKeyPairInFile", new object[] { base.KeyFile }); throw new StrongNameException(); } } } bool flag = true; if (!base.ExecuteAsTool) { TypeLibConverter converter = new TypeLibConverter(); AssemblyBuilder assemblyBuilder = null; try { TypeLibImporterFlags flags = TypeLibImporterFlags.TransformDispRetVals | TypeLibImporterFlags.SafeArrayAsSystemArray; if (this.noClassMembers) { flags |= TypeLibImporterFlags.PreventClassMembers; } string str4 = this.targetProcessorArchitecture; if (str4 != null) { if (!(str4 == "MSIL")) { if (str4 == "AMD64") { goto Label_0323; } if (str4 == "IA64") { goto Label_032F; } if (str4 == "x86") { goto Label_033B; } } else { flags |= TypeLibImporterFlags.ImportAsAgnostic; } } goto Label_0345; Label_0323: flags |= TypeLibImporterFlags.ImportAsX64; goto Label_0345; Label_032F: flags |= TypeLibImporterFlags.ImportAsItanium; goto Label_0345; Label_033B: flags |= TypeLibImporterFlags.ImportAsX86; Label_0345: assemblyBuilder = converter.ConvertTypeLibToAssembly(this.ReferenceInfo.typeLibPointer, wrapperPath, flags, this, publicKey, keyPair, typeLibName, null); } catch (COMException exception) { base.Log.LogWarningWithCodeFromResources("ResolveComReference.ErrorCreatingWrapperAssembly", new object[] { this.ItemName, exception.Message }); throw new ComReferenceResolutionException(exception); } if (!this.HasTemporaryWrapper) { this.WriteWrapperToDisk(assemblyBuilder, wrapperPath); } wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = this.HasTemporaryWrapper ? null : wrapperPath; wrapperInfo.assembly = assemblyBuilder; return flag; } ResolveComReference.TlbImp imp = new ResolveComReference.TlbImp { BuildEngine = base.BuildEngine, EnvironmentVariables = base.EnvironmentVariables, DelaySign = base.DelaySign, KeyContainer = base.KeyContainer, KeyFile = base.KeyFile, OutputAssembly = wrapperPath, ToolPath = base.ToolPath, TypeLibName = this.ReferenceInfo.typeLibPath, AssemblyNamespace = typeLibName, AssemblyVersion = null, PreventClassMembers = this.noClassMembers, SafeArrayAsSystemArray = true, Transform = ResolveComReference.TlbImpTransformFlags.TransformDispRetVals }; if (this.referenceFiles != null) { string fullPathToOutput = Path.GetFullPath(wrapperPath); imp.ReferenceFiles = (from rf in this.referenceFiles where string.Compare(fullPathToOutput, rf, StringComparison.OrdinalIgnoreCase) != 0 select rf).ToArray<string>(); } string targetProcessorArchitecture = this.targetProcessorArchitecture; if (targetProcessorArchitecture != null) { if (!(targetProcessorArchitecture == "MSIL")) { if (targetProcessorArchitecture == "AMD64") { imp.Machine = "X64"; } else if (targetProcessorArchitecture == "IA64") { imp.Machine = "Itanium"; } else if (targetProcessorArchitecture == "x86") { imp.Machine = "X86"; } else { imp.Machine = this.targetProcessorArchitecture; } } else { imp.Machine = "Agnostic"; } } flag = imp.Execute(); wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = this.HasTemporaryWrapper ? null : wrapperPath; return flag; }
/* * Method: ResolveComClassicReference * * Resolves a COM classic reference given the type library attributes and the type of wrapper to use. * If wrapper type is not specified, this method will first look for an existing reference in the project, * fall back to looking for a PIA and finally try to generate a regular tlbimp wrapper. */ internal bool ResolveComClassicReference(ComReferenceInfo referenceInfo, string outputDirectory, string wrapperType, string refName, bool topLevelRef, List<string> dependencyPaths, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; bool retVal = false; // only look for an existing PIA if (ComReferenceTypes.IsPia(wrapperType)) { retVal = ResolveComReferencePia(referenceInfo, refName, out wrapperInfo); } // find/generate a tlb wrapper else if (ComReferenceTypes.IsTlbImp(wrapperType)) { retVal = ResolveComReferenceTlb(referenceInfo, outputDirectory, refName, topLevelRef, dependencyPaths, out wrapperInfo); } // find/generate an Ax wrapper else if (ComReferenceTypes.IsAxImp(wrapperType)) { retVal = ResolveComReferenceAx(referenceInfo, outputDirectory, refName, out wrapperInfo); } // find/generate a pia/tlb wrapper (it's only possible to get here via a callback) else if (wrapperType == null || ComReferenceTypes.IsPiaOrTlbImp(wrapperType)) { // if this reference does not exist in the project, try looking for a PIA first retVal = ResolveComReferencePia(referenceInfo, refName, out wrapperInfo); if (!retVal) { // failing that, try a regular tlb wrapper retVal = ResolveComReferenceTlb(referenceInfo, outputDirectory, refName, false /* dependency */, dependencyPaths, out wrapperInfo); } } else { ErrorUtilities.VerifyThrow(false, "Unknown wrapper type!"); } referenceInfo.resolvedWrapper = wrapperInfo; // update the timestamp cache with the timestamp of the component we just processed _timestampCache[referenceInfo.strippedTypeLibPath] = File.GetLastWriteTime(referenceInfo.strippedTypeLibPath); return retVal; }
/* * Method: ResolveComClassicReference * * Resolves a COM classic reference given the type library attributes and the type of wrapper to use. * If wrapper type is not specified, this method will first look for an existing reference in the project, * fall back to looking for a PIA and finally try to generate a regular tlbimp wrapper. * * This is the method available for references to call back to resolve their dependencies */ bool IComReferenceResolver.ResolveComClassicReference(TYPELIBATTR typeLibAttr, string outputDirectory, string wrapperType, string refName, out ComReferenceWrapperInfo wrapperInfo) { // does this reference exist in the project or is it a dependency? bool topLevelRef = false; wrapperInfo = null; // remap the type lib to ADO 2.7 if necessary TYPELIBATTR oldAttr = typeLibAttr; if (ComReference.RemapAdoTypeLib(Log, Silent, ref typeLibAttr) && !Silent) { // if successfully remapped the reference to ADO 2.7, notify the user Log.LogMessageFromResources(MessageImportance.Low, "ResolveComReference.RemappingAdoTypeLib", oldAttr.wMajorVerNum, oldAttr.wMinorVerNum); } ComReferenceInfo referenceInfo; // find an existing ref in the project (taking the desired wrapperType into account, if any) if (IsExistingProjectReference(typeLibAttr, wrapperType, out referenceInfo)) { // IsExistingProjectReference should not return null... Debug.Assert(referenceInfo != null, "IsExistingProjectReference should not return null"); topLevelRef = true; wrapperType = referenceInfo.taskItem.GetMetadata(ComReferenceItemMetadataNames.wrapperTool); } // was this dependency already processed? else if (IsExistingDependencyReference(typeLibAttr, out referenceInfo)) { Debug.Assert(referenceInfo != null, "IsExistingDependencyReference should not return null"); // we've seen this dependency before, so we should know what its wrapper type is. if (wrapperType == null || ComReferenceTypes.IsPiaOrTlbImp(wrapperType)) { string typeLibKey = ComReference.UniqueKeyFromTypeLibAttr(typeLibAttr); if (_cachePia.ContainsKey(typeLibKey)) { wrapperType = ComReferenceTypes.primary; } else if (_cacheTlb.ContainsKey(typeLibKey)) { wrapperType = ComReferenceTypes.tlbimp; } } } // if not found anywhere, create a new ComReferenceInfo object and resolve it. else { try { referenceInfo = new ComReferenceInfo(); if (referenceInfo.InitializeWithTypeLibAttrs(Log, Silent, typeLibAttr, null, this.TargetProcessorArchitecture)) { allDependencyRefs.Add(referenceInfo); } else { referenceInfo.ReleaseTypeLibPtr(); return false; } } catch (COMException ex) { if (!Silent) { Log.LogWarningWithCodeFromResources("ResolveComReference.CannotLoadTypeLib", typeLibAttr.guid, typeLibAttr.wMajorVerNum.ToString(CultureInfo.InvariantCulture), typeLibAttr.wMinorVerNum.ToString(CultureInfo.InvariantCulture), ex.Message); } referenceInfo.ReleaseTypeLibPtr(); // can't resolve an unregistered and unknown dependency, so return false return false; } } // if we don't have the reference name, use the typelib name if (refName == null) { refName = referenceInfo.typeLibName; } return ResolveComClassicReference(referenceInfo, outputDirectory, wrapperType, refName, topLevelRef, referenceInfo.dependentWrapperPaths, out wrapperInfo); }
internal bool ResolveComReferenceAx(ComReferenceInfo referenceInfo, string outputDirectory, string refName, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string key = ComReference.UniqueKeyFromTypeLibAttr(referenceInfo.attr); if (this.cacheAx.ContainsKey(key)) { wrapperInfo = (ComReferenceWrapperInfo) this.cacheAx[key]; return true; } try { AxReference reference = new AxReference(base.Log, this, referenceInfo, refName, outputDirectory, this.DelaySign, this.KeyFile, this.KeyContainer, this.IncludeVersionInInteropName, this.aximpPath, base.BuildEngine, this.EnvironmentVariables); if (!reference.FindExistingWrapper(out wrapperInfo, this.timestampCache[referenceInfo.typeLibPath]) && !reference.GenerateWrapper(out wrapperInfo)) { return false; } this.cacheAx.Add(key, wrapperInfo); } catch (Exception exception) { if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception)) { throw; } return false; } return true; }
/* * Method: IsWrapperUpToDate * * Checks if the existing wrapper is up to date. */ protected virtual bool IsWrapperUpToDate(ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { Debug.Assert(ReferenceInfo.strippedTypeLibPath != null && ReferenceInfo.strippedTypeLibPath.Length > 0, "ReferenceInfo.path should be valid if we got here"); if (ReferenceInfo.strippedTypeLibPath == null || ReferenceInfo.strippedTypeLibPath.Length == 0) throw new ComReferenceResolutionException(); // if wrapper doesn't exist, wrapper is obviously not up to date if (!File.Exists(wrapperInfo.path)) return false; // if typelib file has a DIFFERENT last write time, wrapper is not up to date // the reason we're comparing write times in an unusual way is that type libraries are unusual // "source files" for wrappers. If you upgrade/downgrade a system component, its write // time may be earlier than before but we should still regenerate the wrapper. if (DateTime.Compare(File.GetLastWriteTime(ReferenceInfo.strippedTypeLibPath), componentTimestamp) != 0) return false; // Compare our the existing wrapper's strong name state to the one we are requesting. if (!SigningRequirementsMatchExistingWrapper(wrapperInfo)) { return false; } // ok, everything's looking fine, now just verify the assembly file is valid try { wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path); } catch (BadImageFormatException) { // ouch, this assembly is malformed... need to regenerate the wrapper. wrapperInfo.assembly = null; } return (wrapperInfo.assembly != null); }
internal bool ResolveComReferenceTlb(ComReferenceInfo referenceInfo, string outputDirectory, string refName, bool topLevelRef, List<string> dependencyPaths, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string key = ComReference.UniqueKeyFromTypeLibAttr(referenceInfo.attr); if (this.cacheTlb.ContainsKey(key)) { wrapperInfo = (ComReferenceWrapperInfo) this.cacheTlb[key]; return true; } bool hasTemporaryWrapper = false; if (!topLevelRef) { foreach (ComReferenceInfo info in this.allProjectRefs) { if ((ComReferenceTypes.IsTlbImp(info.taskItem.GetMetadata("WrapperTool")) && !ComReference.AreTypeLibAttrEqual(referenceInfo.attr, info.attr)) && (string.Compare(referenceInfo.typeLibName, info.typeLibName, StringComparison.OrdinalIgnoreCase) == 0)) { hasTemporaryWrapper = true; } } } try { List<string> referenceFiles = new List<string>(this.GetResolvedAssemblyReferenceItemSpecs()); if (dependencyPaths != null) { referenceFiles.AddRange(dependencyPaths); } TlbReference reference = new TlbReference(base.Log, this, referenceFiles, referenceInfo, refName, outputDirectory, hasTemporaryWrapper, this.DelaySign, this.KeyFile, this.KeyContainer, this.NoClassMembers, this.TargetProcessorArchitecture, this.IncludeVersionInInteropName, this.ExecuteAsTool, this.tlbimpPath, base.BuildEngine, this.EnvironmentVariables); if (!reference.FindExistingWrapper(out wrapperInfo, this.timestampCache[referenceInfo.typeLibPath]) && !reference.GenerateWrapper(out wrapperInfo)) { return false; } this.cacheTlb.Add(key, wrapperInfo); } catch (Exception exception) { if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception)) { throw; } return false; } return true; }
/* * Method: FindExistingWrapper * * Checks if there's a preexisting wrapper for this reference. */ internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp) { wrapperInfo = null; string wrapperPath = GetWrapperPath(); // now see if the wrapper assembly actually exists if (!File.Exists(wrapperPath)) { return false; } wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = wrapperPath; return IsWrapperUpToDate(wrapperInfo, componentTimestamp); }
/* * Method: GenerateWrapper * * Generates a wrapper for this reference. */ internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string rootNamespace = ReferenceInfo.typeLibName; string wrapperPath = GetWrapperPath(); bool generateWrapperSucceeded = true; if (ExecuteAsTool) { // delegate generation of the assembly to an instance of the TlbImp ToolTask. MUST // HAVE SET SDKTOOLSPATH TO THE TARGET SDK TO WORK var tlbImp = new ResolveComReference.TlbImp(); tlbImp.BuildEngine = BuildEngine; tlbImp.EnvironmentVariables = EnvironmentVariables; tlbImp.DelaySign = DelaySign; tlbImp.KeyContainer = KeyContainer; tlbImp.KeyFile = KeyFile; tlbImp.OutputAssembly = wrapperPath; tlbImp.ToolPath = ToolPath; tlbImp.TypeLibName = ReferenceInfo.fullTypeLibPath; tlbImp.AssemblyNamespace = rootNamespace; tlbImp.AssemblyVersion = null; tlbImp.PreventClassMembers = _noClassMembers; tlbImp.SafeArrayAsSystemArray = true; tlbImp.Silent = Silent; tlbImp.Transform = ResolveComReference.TlbImpTransformFlags.TransformDispRetVals; if (_referenceFiles != null) { // Issue is that there may be reference dependencies that need to be passed in. It is possible // that the set of references will also contain the file that is meant to be written here (when reference resolution // found the file in the output folder). We need to filter out this case. var fullPathToOutput = Path.GetFullPath(wrapperPath); // Current directory is the directory of the project file. tlbImp.ReferenceFiles = _referenceFiles.Where(rf => String.Compare(fullPathToOutput, rf, StringComparison.OrdinalIgnoreCase) != 0).ToArray(); } switch (_targetProcessorArchitecture) { case UtilitiesProcessorArchitecture.MSIL: tlbImp.Machine = "Agnostic"; break; case UtilitiesProcessorArchitecture.AMD64: tlbImp.Machine = "X64"; break; case UtilitiesProcessorArchitecture.IA64: tlbImp.Machine = "Itanium"; break; case UtilitiesProcessorArchitecture.X86: tlbImp.Machine = "X86"; break; case UtilitiesProcessorArchitecture.ARM: tlbImp.Machine = "ARM"; break; case null: break; default: // Transmit the flag directly from the .targets files and rely on tlbimp.exe to produce a good error message. tlbImp.Machine = _targetProcessorArchitecture; break; } generateWrapperSucceeded = tlbImp.Execute(); // store the wrapper info... wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = (HasTemporaryWrapper) ? null : wrapperPath; // Changed to ReflectionOnlyLoadFrom, related to bug: // RCR: Bad COM-interop assemblies being generated when using 64-bit MSBuild to build a project that is targeting 32-bit platform // The original call to UnsafeLoadFrom loads the assembly in preparation for execution. If the assembly is x86 and this is x64 msbuild.exe then we // have problems (UnsafeLoadFrom will fail). We only use this assembly for reference resolution so we don't need to be ready to execute the code. // // Its actually not clear to me that we even need to load the assembly at all. Reference resoluton is only used in the !ExecuteAsTool which is not // where we are right now. // // If we really do need to load it then: // // wrapperInfo.assembly = Assembly.ReflectionOnlyLoadFrom(wrapperPath); } else { // use framework classes in-proc to generate the assembly TypeLibConverter converter = new TypeLibConverter(); AssemblyBuilder assemblyBuilder = null; StrongNameKeyPair keyPair; byte[] publicKey; GetAndValidateStrongNameKey(out keyPair, out publicKey); try { TypeLibImporterFlags flags = TypeLibImporterFlags.SafeArrayAsSystemArray | TypeLibImporterFlags.TransformDispRetVals; if (_noClassMembers) { flags |= TypeLibImporterFlags.PreventClassMembers; } switch (_targetProcessorArchitecture) { case UtilitiesProcessorArchitecture.MSIL: flags |= TypeLibImporterFlags.ImportAsAgnostic; break; case UtilitiesProcessorArchitecture.AMD64: flags |= TypeLibImporterFlags.ImportAsX64; break; case UtilitiesProcessorArchitecture.IA64: flags |= TypeLibImporterFlags.ImportAsItanium; break; case UtilitiesProcessorArchitecture.X86: flags |= TypeLibImporterFlags.ImportAsX86; break; case UtilitiesProcessorArchitecture.ARM: flags |= TypeLibImporterFlags.ImportAsArm; break; default: // Let the type importer decide. break; } // Start the conversion process. We'll get callbacks on ITypeLibImporterNotifySink to resolve dependent refs. assemblyBuilder = converter.ConvertTypeLibToAssembly(ReferenceInfo.typeLibPointer, wrapperPath, flags, this, publicKey, keyPair, rootNamespace, null); } catch (COMException ex) { if (!Silent) { Log.LogWarningWithCodeFromResources("ResolveComReference.ErrorCreatingWrapperAssembly", ItemName, ex.Message); } throw new ComReferenceResolutionException(ex); } // if we're done, and this is not a temporary wrapper, write it out to disk if (!HasTemporaryWrapper) { WriteWrapperToDisk(assemblyBuilder, wrapperPath); } // store the wrapper info... wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = (HasTemporaryWrapper) ? null : wrapperPath; wrapperInfo.assembly = assemblyBuilder; } // ...and we're done! return(generateWrapperSucceeded); }
internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string typeLibName = this.ReferenceInfo.typeLibName; string wrapperPath = base.GetWrapperPath(); StrongNameKeyPair keyPair = null; byte[] publicKey = null; StrongNameUtils.GetStrongNameKey(base.Log, base.KeyFile, base.KeyContainer, out keyPair, out publicKey); if (base.DelaySign) { keyPair = null; if (publicKey == null) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "StrongNameUtils.NoPublicKeySpecified", new object[0]); throw new StrongNameException(); } } else { publicKey = null; if (keyPair == null) { if ((base.KeyContainer != null) && (base.KeyContainer.Length > 0)) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "ResolveComReference.StrongNameUtils.NoKeyPairInContainer", new object[] { base.KeyContainer }); throw new StrongNameException(); } if ((base.KeyFile != null) && (base.KeyFile.Length > 0)) { base.Log.LogErrorWithCodeFromResources(null, this.ReferenceInfo.SourceItemSpec, 0, 0, 0, 0, "ResolveComReference.StrongNameUtils.NoKeyPairInFile", new object[] { base.KeyFile }); throw new StrongNameException(); } } } bool flag = true; if (!base.ExecuteAsTool) { TypeLibConverter converter = new TypeLibConverter(); AssemblyBuilder assemblyBuilder = null; try { TypeLibImporterFlags flags = TypeLibImporterFlags.TransformDispRetVals | TypeLibImporterFlags.SafeArrayAsSystemArray; if (this.noClassMembers) { flags |= TypeLibImporterFlags.PreventClassMembers; } string str4 = this.targetProcessorArchitecture; if (str4 != null) { if (!(str4 == "MSIL")) { if (str4 == "AMD64") { goto Label_0323; } if (str4 == "IA64") { goto Label_032F; } if (str4 == "x86") { goto Label_033B; } } else { flags |= TypeLibImporterFlags.ImportAsAgnostic; } } goto Label_0345; Label_0323: flags |= TypeLibImporterFlags.ImportAsX64; goto Label_0345; Label_032F: flags |= TypeLibImporterFlags.ImportAsItanium; goto Label_0345; Label_033B: flags |= TypeLibImporterFlags.ImportAsX86; Label_0345: assemblyBuilder = converter.ConvertTypeLibToAssembly(this.ReferenceInfo.typeLibPointer, wrapperPath, flags, this, publicKey, keyPair, typeLibName, null); } catch (COMException exception) { base.Log.LogWarningWithCodeFromResources("ResolveComReference.ErrorCreatingWrapperAssembly", new object[] { this.ItemName, exception.Message }); throw new ComReferenceResolutionException(exception); } if (!this.HasTemporaryWrapper) { this.WriteWrapperToDisk(assemblyBuilder, wrapperPath); } wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = this.HasTemporaryWrapper ? null : wrapperPath; wrapperInfo.assembly = assemblyBuilder; return(flag); } ResolveComReference.TlbImp imp = new ResolveComReference.TlbImp { BuildEngine = base.BuildEngine, EnvironmentVariables = base.EnvironmentVariables, DelaySign = base.DelaySign, KeyContainer = base.KeyContainer, KeyFile = base.KeyFile, OutputAssembly = wrapperPath, ToolPath = base.ToolPath, TypeLibName = this.ReferenceInfo.typeLibPath, AssemblyNamespace = typeLibName, AssemblyVersion = null, PreventClassMembers = this.noClassMembers, SafeArrayAsSystemArray = true, Transform = ResolveComReference.TlbImpTransformFlags.TransformDispRetVals }; if (this.referenceFiles != null) { string fullPathToOutput = Path.GetFullPath(wrapperPath); imp.ReferenceFiles = (from rf in this.referenceFiles where string.Compare(fullPathToOutput, rf, StringComparison.OrdinalIgnoreCase) != 0 select rf).ToArray <string>(); } string targetProcessorArchitecture = this.targetProcessorArchitecture; if (targetProcessorArchitecture != null) { if (!(targetProcessorArchitecture == "MSIL")) { if (targetProcessorArchitecture == "AMD64") { imp.Machine = "X64"; } else if (targetProcessorArchitecture == "IA64") { imp.Machine = "Itanium"; } else if (targetProcessorArchitecture == "x86") { imp.Machine = "X86"; } else { imp.Machine = this.targetProcessorArchitecture; } } else { imp.Machine = "Agnostic"; } } flag = imp.Execute(); wrapperInfo = new ComReferenceWrapperInfo(); wrapperInfo.path = this.HasTemporaryWrapper ? null : wrapperPath; return(flag); }
internal abstract bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp);
/// <summary> /// Helper function - resolves a PIA COM classic reference given the type library attributes. /// </summary> /// <param name="referenceInfo">Information about the reference to be resolved</param> /// <param name="refName">Name of reference</param> /// <param name="wrapperInfo">Information about wrapper locations</param> /// <returns>True if the reference was already found or successfully generated, false otherwise.</returns> internal bool ResolveComReferencePia(ComReferenceInfo referenceInfo, string refName, out ComReferenceWrapperInfo wrapperInfo) { wrapperInfo = null; string typeLibKey = ComReference.UniqueKeyFromTypeLibAttr(referenceInfo.attr); // look in the PIA cache first if (_cachePia.ContainsKey(typeLibKey)) { wrapperInfo = (ComReferenceWrapperInfo)_cachePia[typeLibKey]; return true; } try { // if not in the cache, we have no choice but to go looking for the PIA PiaReference reference = new PiaReference(Log, Silent, referenceInfo, refName); // if not found, fail (we do not fall back to tlbimp wrappers if we're looking specifically for a PIA) if (!reference.FindExistingWrapper(out wrapperInfo, _timestampCache[referenceInfo.strippedTypeLibPath])) { return false; } // if found, add it to the PIA cache _cachePia.Add(typeLibKey, wrapperInfo); } catch (Exception e) when (ExceptionHandling.IsIoRelatedException(e)) { return false; } return true; }